;*************************************************************** A_BIT EQU 20H ;數碼管個位數存放內存位置 B_BIT EQU 21H ;數碼管十位數存放內存位置 NO_OUT EQU 24H ;最終控制號碼存放單元 A_NO EQU 25H ;數碼管個位數對應代碼存放內存位置 B_NO EQU 26H ;數碼管十位數對應代碼存放內存位置 ;22H,23H為控制碼及其反碼的存放單元 ;*******************<<主程序>>*********************************** ORG 0000H AJMP 0030H ORG 0013H ;外部中斷P3.3腳INT0入口地址 AJMP INT ;轉入外部中斷服務子程序(解碼程序) ORG 0030H AJMP MAIN ;轉入主程序 ;*************************************************************** MAIN: MOV NO_OUT,#0H SETB EA ;打開CPU總中斷請求 SETB IT1 ;設定INT1的觸發方式為脈沖負邊沿觸發 SETB EX1 ;打開INT1中斷請求 ;以下5行的功能是關閉8*8點陣的輸出,也就是把所有的行置0,這樣不管列為任何電平點陣都不會亮了. MOV R2,#8 ;輸出數據8位 hei: CLR P2.4 ;拉低SCL,以便下次拉高便可產生上升沿 CLR P2.5 ;數據先送入74hc164,等待clk上升沿的到來 SETB P2.4 ;低電平到高電平邊沿觸發到來,并行數據輸出至164的Q0-Q7 DJNZ R2,hei ;判斷輸出完畢了沒有 LOOP: ;MOV A,NO_OUT;將按鍵的鍵值通過P0口的8個LED顯示出來! ;CPL A ;由于P0發光二極管顯示的是電平的反狀態,所以取反 ;MOV P0,A ;發光二極管顯示輸出 LCALL DISPLAY;LED數碼管顯示輸出 AJMP LOOP;循環 ;********************<<中斷接受遙控程序>>************************ ;以下為進入P3.3腳外部中斷子程序,也就是解碼程序 INT: PUSH ACC PUSH PSW ;將PSW和ACC推入堆棧保護 CLR EA ;暫時關閉CPU的所有中斷請求 MOV R6,#10 SB: LCALL DL865 ;調用865微秒延時子程序 JB P3.3,EXIT ;延時865微秒后判斷P3.3腳是否出現高電平如果有就退出解碼程序 DJNZ R6, SB ;重復10次,目的是檢測在8650微秒內如果出現高電平就退出解碼程序 ;以上完成對遙控信號的9000微秒的初始低電平信號的識別。 JNB P3.3, $ ;等待高電平避開9毫秒低電平引導脈沖 LCALL DL4737 ;延時4.74毫秒避開4.5毫秒的結果碼 MOV R7,#16 ;忽略前26位系統識別碼 JJJJA:JNB P3.3,$ ;等待地址碼第一位的高電平信號 LCALL DL865 ;高電平開始后用865微秒的時間尺去判斷信號此時的高低電平狀態 MOV C,P3.3 ;將P3.3引腳此時的電平狀態0或1存入C中 JNC UUUA ;如果為0就跳轉到UUUA LCALL DL1000 ;檢測到高電平1的話延時1毫秒等待脈沖高電平結束 UUUA: DJNZ R7,JJJJA MOV R1,#22H ;設定22H為起始RAM區 MOV R2,#2 ;接收從22H到23H的2個內存,用于存放操作碼和操作反碼 PP: MOV R3,#8 ;每組數據為8位 JJJJ: JNB P3.3,$ ;等待地址碼第一位的高電平信號 LCALL DL865 ;高電平開始后用865微秒的時間尺去判斷信號此時的高低電平狀態 MOV C,P3.3 ;將P3.3引腳此時的電平狀態0或1存入C中 JNC UUU ;如果為0就跳轉到UUU LCALL DL1000 ;檢測到高電平1的話延時1毫秒等待脈沖高電平結束 UUU: MOV A,@R1 ;將R1中地址的給A RRC A ;將C中的值0或1移入A中的最低位 MOV @R1,A ;將A中的數暫時存放在R1數值的內存中 DJNZ R3,JJJJ ;接收滿8位換一個內存 INC R1 ;對R1中的值加1,換下一個RAM DJNZ R2,PP ;接收完8位數據碼和8位數據反碼,存放在22H/23H中 MOV A,22H CPL A ;對22H取反后和23H比較 CJNE A,23H,EXIT;如果不等表示接收數據發生錯誤,放棄 MOV A,22H MOV NO_OUT,A ;LCALL EEPROM_C ;清除以前的保存的碼 ;LCALL DL4737 ;LCALL EEPROM_W ;把碼存在單片機內部的EEPROM里 ;LCALL DL4737 CLR P2.2;蜂鳴器鳴響-嘀嘀嘀-的聲音,表示解碼成功 LCALL DL4737 LCALL DL4737 LCALL DL4737 SETB P2.2 ;蜂鳴器停止 lcall DL4737 EXIT: SETB EA ;允許中斷 POP PSW POP ACC ;將PSW和ACC推入堆棧保護 RETI ;退出解碼子程序 ;*******************<>********************** DISPLAY: MOV A,NO_OUT ;將NO_OUT分成個位和16位 ANL A,#0FH ;取低四位放在a_bit MOV A_BIT,A ;個位 MOV A,NO_OUT ; RR A RR A RR A RR A ;四次移動,把高四位移到低四位 ANL A,#0FH ;取高四位放在B_bit MOV B_BIT,A ;個位在b MOV DPTR,#NUMTAB ;指定查表啟始地址 MOV A,A_BIT ;取個位數 MOVC A,@A+DPTR ;查個位數的7段代碼 MOV A_NO,A MOV A,B_BIT ;取十位數 MOVC A,@A+DPTR ;查十位數的7段代碼 MOV B_NO,A DPLOP:MOV A,A_NO MOV P0,A ;送出個位的段碼到P0口 SETB P2.6 ;使段選的這個74hc573的數據能直通,送段碼到數碼管上 CLR P2.6 ;鎖存,使得74hc573的輸出不再隨輸入而變化,維持輸出的段碼不變. MOV P0,#0FDH ;開十位顯示 SETB P2.7 ;使位選的這個74hc573的數據能直通,選擇某一位數碼管有顯示 CLR P2.7 ;鎖存,使得74hc573的輸出不再隨輸入而變化,維持輸出的位碼不變. LCALL DL40 ;顯示一段時間 MOV P0,#0FFH ;關閉十位顯示,防止鬼影 SETB P2.7 ;同上 CLR P2.7 ;同上 MOV A,B_NO MOV P0,A ;送出個位的7段代碼 SETB P2.6 ;同上 CLR P2.6 ;同上 MOV P0,#0FEH ;開個位顯示 SETB P2.7 ;同上 CLR P2.7 ;同上 LCALL DL40 ;顯示一段時間 MOV P0,#0FFH ;關閉個位顯示,防止鬼影 SETB P2.7 ;同上 CLR P2.7 ;同上 RET ;**********************<<延時程序>>****************************** DL865: MOV R4,#12 ; 1.09*(2R5+4)*R4+2延時子程序1,精確延時865微秒 D1: MOV R5,#31 DJNZ R5,$ DJNZ R4,D1 RET DL4737: MOV R4,#12 ;延時子程序2,精確延時4737微秒 D2: MOV R5,#179 DJNZ R5,$ DJNZ R4,D2 RET DL1000: MOV R4,#17;延時程序3,精確延時1000微秒 D3: MOV R5,#25 DJNZ R5,$ DJNZ R4,D3 RET DL40: MOV R4,#1;延時程序4,精確延時40/17微秒 D4: MOV R5,#1 DJNZ R5,$ DJNZ R4,D4 RET ;定義段碼對應 0 1 2 3 4 5 6 7 8 9 A B C D E F NUMTAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H END
有好幾個c的啊,都是在51hei-5開發板上測試通過了的,具體你打開這里http://www.zg4o1577.cn/bbs/mcu-10-1.html
歡迎光臨 (http://www.zg4o1577.cn/bbs/) | Powered by Discuz! X3.1 |