;*************************************************************** 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.51hei.com/bbs/mcu-10-1.html
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |