標題: MCU編程實踐之紅外中斷定時12864逐步講解一鍋燴 [打印本頁]
作者: 慢慢思考 時間: 2020-1-2 21:18
標題: MCU編程實踐之紅外中斷定時12864逐步講解一鍋燴
這個其實是紅外遙控編程過程實驗,思路是這樣的:
紅外接收管采用中斷口接收信號;
在中斷子程序中,在高低電平的變化時,用計時器來計時其高、低電平維持的時長;
將時長值直接用二進制數顯示在12864屏上;
以us為單位,手工計算各顯示數值的時長值(這個可以不做);
根據紅外遙控NEC標準,分析該遙控器的引導碼及比特碼的高低電平時長組成,以此獲得引導碼和比特碼的高低電平時長特征值,
依據得到的引導碼和比特碼的高低電平時長特征值,再編制程序獲得該遙控器的用戶碼值、各鍵的鍵值。
依據得到的用戶碼值、各鍵的鍵值,接下來就可以做遙控控制操作編程了。
這一套操作下來,你就擁有了獲得各種紅外遙控器用戶碼和鍵值的工具了,然后,你可以給家里的所有紅外遙控器做一個一桶姜山的專用遙控器了,然后你可以在網上訂印刷板、外殼等的,高檔一點的,全屏觸摸操作帶學習。
下面一步一步來:
一、12864屏
該屏下有字符顯示和圖形顯示兩種模式,我們選擇字符模式。
字符模式下,其最多可顯示64個半寬字符,或32個漢字,可混編,分為四排。輸入位置為一維座標確定,左上角的座標值為80H。
1.初始化
編程時,首先設置其為字符模式,命令代碼為10100B(我們這里直接用二進制,方便自己看說明書及更改功能設置)。
字符輸入時,我們一般都能看到一個光標,以在屏幕上指示正在輸入的位置,這個光標可以開可以關,用命令來設置;輸入時我們一般選擇光標向右移動、字符從左向右順序輸入(當然,你也可以倒著來,或新輸入的字符總是固定在這個位置),相應命令為110B。
然后將字符地址內存DDRAM全部清空,將DDRAM的地址計數器值歸位。該命令為1B。
字符輸入后,你可以控制其顯示或不顯示,光標也一樣,所以,我們還要設置其打開,相應命令為1110B。這個命令中,最后一位為0,表示游標位置反白關。
還有一個光標顯示移位控制命令,先用10100B吧。
這一步算是完成了,執行后,你應該能看到光標。如果沒有,那你的程序就有問題,仔細檢查,反正沒幾行,我遇到的問題,基本就是延時不夠,以及該延時的地方沒加延時。
下面給出這部分的匯編程序,當然,你也可以用C編。并行輸入,P0口為數據口:
XRS EQU 0B5H;P35 編程器不認P35,只好直接輸入P35的地址值了,下同
XRW EQU 0B6H;P36
XEN EQU 0B7H;P37
;XPSB EQU ? 這兩個,我的STC8A8K板,已硬件連電位了
;XRESET EQU ?
XCOM EQU 34H
XDAT EQU 35H
ORG 0000H
AJMP START
ORG 0100H
START:
ACALL XDELAY
ACALL XINIT
AJMP $
XINIT:
MOV XCOM,#110000B
ACALL XWRI
MOV XCOM,#1H
ACALL XWRI
MOV XCOM,#110B
ACALL XWRI
MOV XCOM,#1110B
ACALL XWRI
MOV XCOM,#10100B
ACALL XWRI
RET
XWRI:
CLR XEN
CLR XRS
CLR XRW
ACALL XDELAY
MOV P0,XCOM
SETB XEN
CLR XEN
ACALL XDELAY
RET
XWDAT:
CLR XEN
SETB XRS
CLR XRW
MOV P0,XDAT
SETB XEN
CLR XEN
ACALL XDELAY
RET
XDELAY: MOV 30h,#40 這個延時有點長,短了我的這個MCU不認帳,沒法
D1: MOV 31h,#25
D2: DJNZ 31h,D2
DJNZ 30h,D1
RET
END
2.輸入字符
這個簡單,輸入座標再輸入字符編碼,搞定。
至此,屏顯編程工作完成。
3.直接以二進制顯示一個存儲單元中的數值
比如我們要顯示10010110B這個值,我們把它先輸入到A寄存器中,將這個值一位一位地進行處理并顯示在屏幕上。
對于初學者,最好是先將其中任一位的顯示程序做通,然后再做這八位輸入的程序,這個功能的子程序如下:
XBIT:
MOV A,#10010110B
JB ACC.0,LOOP1
LOOP0:MOV XDAT,#30H
ACALL XWDAT
RET
LOOP1:MOV XDAT,#31H
ACALL XWDAT
RET
上面程序中的BACC.0就是最末一位,你可以換成其它位試試能否正確顯示。
這個做通了,下面做八位全部顯示的。
我們采用移位并循環法,從高位到低位逐位處理,子程序如下:
X8BIT:
MOV A,#10010110B
ACALL XBIT
RET
XBIT:
MOV R2,#08H
LOOP0:
RL A
JB ACC.0,LOOP1
MOV XDAT,#30H
ACALL XWDAT
DJNZ R2,LOOP0
RET
LOOP1:
MOV XDAT,#31H
ACALL XWDAT
DJNZ R2,LOOP0
RET
三、中斷程序
其實中斷的原理蠻簡單的,設定相應中斷開之后,一旦有中斷信號被接收到,即中斷口的電平被拉低,則程序就強行發生跳轉,這個跳轉是程序存儲器絕對地址的跳轉,不同編號的中斷有不同的跳轉地址(中斷向量),比如INT0,其跳轉地址為0003H,即程序跳轉到地址為0003H處開始執行。所以,在主程序中,應在0003H地址處寫入中斷子程序,但要注意因另一個中斷的跳轉地址為000BH,之間放不了幾行程序,所以這里一般是寫個跳轉指令,跳轉到一個專門的子程序來完成中斷后的任務:
ORG 0003H
LJMP INT0RED
對于中斷,MCU設計有總中斷控制開關(符號EA)、相應中斷控制開關(符號EX#)、中斷的觸發方式(IT#),以及各中斷的優先級控制(中斷優先級寄存器IP中)。這個要根據你編程的需要,先期進行設置,也就是中斷的初始化,這個可以在主程序中加一條ACALL INT0INI:
INT0INI:
SETB EX0
CLR IT0
SETB P32 中斷口。這個注意要置該端口為高電位
SETB EA
RET
中斷初始化完成了,現在就可以開始接收中斷并完成中斷后的任務了,下面我們編一段子程序,當收到中斷后,在屏幕指定位置顯示一個漢字:
INT0RED:
CLR EX0 關閉該中斷允許
MOV XCOM,#82H
LCALL XWRI
MOV XDAT,#0B1H
LCALL XWDAT
MOV XDAT,#0B2H
LCALL XWDAT
SETB EX0 完成后打開該中斷允許
RET
執行后屏幕上只有一個光標,按一下遙控器,應該顯示一個漢字。如果沒有,則把P32與地短接一下,如果有了,那就是紅外接收頭或遙控器有問題;如果不是,那么程序有問題。
另外,這段程序中的字符顯示程序部分,規范的做法是做一個子程序,但這里只是檢驗中斷程序,所以簡單一點就不做了。
四、計時程序
計時程序的原理也蠻簡單,你把它當作一個跑步計時秒表就行了,秒表的使用步驟就是先歸零,然后按開始,然后按結束,然后看時間,完成。
秒表也好,MCU的計時也好,其實都是計數,秒表計的是秒數,MCU的講計時器計的是機器 運行周期數,知道了周期長,弄到了周期數,則時長也就可以知道了。
1.在啟動計時功能之前,有一些東西需要先期設置,也就是初始化。
MCU的計時功能,其實只是MCU內的一種功能模塊的功能之一,它還有定時功能、計數功能,這一功能模塊,稱之為定時/計數器,這些功能其實都是基于計數功能來的,它可以計MCU的運行周期數,也可以計端口外部輸入的高低電位變化數,無非是計數來源不同。我們這里需要的是計數機器運行周期數,需先將其設置為計時功能,這個在工作方式寄存器TMOD中進行設置。
MCU為每個定時計數器設計了兩個字節的內部存儲單元,用于存儲計數值,高字節符號為TH#,低字節符號為TL#,這兩字節的存儲單元有四種不同的用法,均在工作方式寄存器TMOD中進行設置。我們這里采用工作方式1即16位計數器方式。
一般MCU內部都設計有幾個定時/計數模塊,編號從0開始。我們在設置時,用哪個就設置哪個。具體應用時要查該芯片的手冊。一般控制0號和1號的TMOD地址為89H。我們這里用MOV TMOD,#00000001B。
按前面說的,秒表啟動前,先將其歸零,用在這里,就是將TH和TL歸零。
啟動與停止控制在時間控制寄存器TCON中的某一位,可位尋址,符號為TR#,TR#=1時啟動,TR#=0時停止。
兩字節用于計數時,有一個問題,就是它最多只能計數65536個,超出怎么辦(也就是溢出)?MCU在TCON中有一位就用于反映這事,溢出時它會被自動置1,其符號為TF#。所以,一般情況下,為穩妥起見,我們會在初始化時,將其置0。如果我們在程序中要用到這個TF#值,那么每一次用后都要清0,清0方式有軟件清0和硬件清0。
下面就是初始化子程序:
T0INI:
MOV TMOD,#00000001B
MOV TH0,#00H
MOV TL0,#00H
CLR TF0
RET
2.計量紅外遙控器的第一個低電位的時長
我們知道,紅外中斷的產生就是接收頭收到信號后將中斷端口拉低為低電平,其最前端也就是引導碼是9mu的低電平,我們在一接收到中斷信號時就啟動計時器,當其端口電平變為高電平時則停止計時,這個計時值是存在TH#和TL#中的,然后我們直接把它顯示在屏幕上,然后計算看是不是在9毫秒左右(總會有些誤差的,原因多種)。
計時子程序如下:
JTRED1:
SETB TR0
JB P32,$
CLR TR1
RET
顯示子程序如下:
INT0RED:
CLR EX0
SETB TR0
JNB P3.2,$
CLR TR0
MOV A,TH0
ACALL X8BIT
MOV A,TL0
ACALL X8BIT
SETB EX0
RET
INT0INI:
SETB EX0
CLR IT0
SETB P3.2
SETB EA
RET
以上功能,實現了引導碼9mu段的時長二進制數顯示,主程序如下:
ORG 0000H
AJMP START
ORG 0003H
LJMP INT0RED
ORG 0100H
START:
ACALL XDELAY
ACALL INT0INI
ACALL XINIT
ACALL T0INI
AJMP $
運行后,按一下遙控器,就會有16位數字顯示。
再往下,不需要我再寫了吧?
作者: lzzasd 時間: 2020-1-3 08:23
我的直覺告訴我 樓主是高手 使用匯編的都是高手 匯編執行效率高 計算機底層不是匯編就是C
當時學黑客的時候 學匯編學的腦殼疼 用匯編寫個驅動替代原來的底層 可以做到殺人于無形 連系統都檢測不到 殺毒軟件更不要說了
作者: 慢慢思考 時間: 2020-1-5 20:53
謝謝看得起,我學匯編是因為匯編語言的操縱感特別強,有一種一切盡在掌握中的感覺,不象C有一種知其然不知其所以然的感覺,這種感覺讓我暫時放棄了C。
匯編還不算最底層,最底層的是機器碼,如果能把機器碼弄通了,拋開匯編,管你是多少位的CPU,那都是透明的。
作者: 這是我 時間: 2020-2-19 18:13
匯編的確看不明白,我買的開發板有個C的例程,是把紅外的用戶碼顯示在1602顯示屏上,我改了下,直接顯示在數碼管上,發現電視的遙控很正常,空調的同一個鍵每次按下碼都會變。
| 歡迎光臨 (http://www.denmoz.com/bbs/) |
Powered by Discuz! X3.1 |