
51黑电子论坛(网址:51hei.com)精选文章:
以前在论坛都持观望态度,今天第一次发帖,希望对大家有所帮助!因本人对汇编语言情有独钟,所以本程序用汇编语言编写,经过测试,MP3和电视机的遥控都能学习对键成功,其他遥控因为手头没有,所以不敢保证全部支持!P1口作为输出口,我分别接了8个灯做指示,如果连上8路继电器,就可红外控制8路电器的工作,虽然红外遥控受遥控距离及方向的影响用起来不够顺心,但在房间里是完全够用了的!红外接收头接P3.7脚;8个学习键是利用P3.0和P3.1轮流输出低电平与P3.2/3.3/3.4/3.5形成2*4矩阵键盘。短按按键可分别手动控制输出端;长按某键5秒左右则进入学习模式,相应输出端的指示灯亮起(学习指示灯与输出指示灯复用,其实学习模式应该是闪烁状态,但我没写这方面的程序,有需要的自己加进去!),在5秒内用遥控器对着接收头按一次遥控的一个键(随自己爱好),学习指示灯熄灭,学习成功!如果要删除遥控键,则长按按键至学习模式后不按遥控器,5秒后学习指示灯熄灭,原来学习的遥控键数据被删除,遥控器不能再控制这一路输出,有需要了再重新学习此路!下面晒几张我自制的实验板: 图片压缩了,不然发不上来!!!——板子可插红外接收头、315M无线发射/接收模块!!! (1)、插红外接收头:

(2)、背面连接线路:

(3)、插315M无线接收模块:

(4)、插315M无线发射模块:

程序更新...: 因之前发布的程序还存在小Bug,正好今天有空,就把最新的程序贴上来吧!此次更新主要解决以下问题:按某个键后5S内再按另外一个键会误判断进入第二个键的学习模式...(在按键扫描部分加了一些处理动作) 好了,不多说,看程序吧:
;;;STC12C2052/STC12C56**学习型红外遥控8路继电器 ;;;内部RC振荡器约6MHz;;; ;;;写EEPROM数据不能调公共的'写',所以每1路的学习模式里 ;;;都要重复写一堆相同的程序,感觉有点浪费空间了,郁闷ing... ;;;修改日期2015/10/10;;;
;---------------------- ISP_DATA EQU 0E2H ;定义EEPROM相关寄存器 ISP_ADDRH EQU 0E3H ;此类寄存器地址需参考所用单片机的手册来设置 ISP_ADDRL EQU 0E4H ;STC12C2052和56**系列的地址是E2H~E7H ISP_CMD EQU 0E5H ISP_TRIG EQU 0E6H ISP_CONTR EQU 0E7H
;---------------------- AUXR EQU 08EH ;定时器1T/12T时钟模式控制 IRCOM EQU 20H ;RAM中接收到的键值起始存放地址(20H-23H) Z EQU 00H ;长按标志位 X EQU 01H ;接收完成标志位 D EQU 02H ;学习模式标志位 IRIN EQU P3.7 ;红外接收头 K1 EQU P3.2 ;学习键 (P3.0与P3.1轮流输出0) K2 EQU P3.3 ;学习键 (实现2*4矩阵键盘) K3 EQU P3.4 ;学习键 K4 EQU P3.5 ;学习键 LED8 EQU P1.0 ;OUT8 LED7 EQU P1.1 ;OUT7 LED6 EQU P1.2 ;OUT6 LED5 EQU P1.3 ;OUT5 LED4 EQU P1.4 ;OUT4 LED3 EQU P1.5 ;OUT3 LED2 EQU P1.6 ;OUT2 LED1 EQU P1.7 ;OUT1
;---------------------- ORG 0000H LJMP START ;跳初始化 ORG 000BH LJMP T0INT ;T0中断服务子程序入口 ORG 0030H
;---------------------- START: MOV SP,#5FH MOV R0,#20H LP0: MOV @R0,#00H ;20H-43H清零 INC R0 CJNE R0,#44H,LP0 MOV P3,#0FFH ;P3口置1 MOV AUXR,00H ;T0/12T时钟模式 MOV TMOD,#01H ;定时器工作模式1(16位) SETB EA ;开总中断EA SETB ET0 ;开T0中断ET0 CLR Z CLR X CLR D
;----------------------- MAIN: ;主程序 ACALL IR_IN ACALL KEYP30 ;矩阵键盘扫描 ACALL KEYP31 ;矩阵键盘扫描 AJMP MAIN
;----------------------- ;(红外接收译码) ;----------------------- IR_IN: JNB IRIN,I2 ;等待 IR 信号出现,IRIN=0则跳到I2 AJMP IEND ;如果没有接收到红外信号则先跳出
I2: MOV R1,#30 I20: ACALL DEL DJNZ R1,I20 ;延时去抖动 JB IRIN,IR_IN ;确认IR信号,去抖动后IRIN仍为0则往下执行 I21: JB IRIN,I3 ;持续4.5mS的低电平,等IRIN为1后跳到I3 AJMP I21 ;此处循环等待高电平的到来
I3: MOV R0,#IRCOM MOV R3,#0 ;8位计数器清0 LL: JNB IRIN,I4 ;持续4.5mS的高电平,等IRIN为0后跳到I4 AJMP LL ;此处循环等待低电平的到来 ;;;;;以上I1-I3程序完成引导码的确认(4.5mS低电平+4.5mS高电平);;;;;
I4: JB IRIN,I5 ;持续0.565mS的低电平,等IRIN为1后跳到I5 AJMP I4 ;此处循环等待高电平的到来
I5: MOV R2,#0 ;高电平到来后开始0.14mS计一次数 L1: ACALL DEL JB IRIN, N1 ;IRIN为1则跳N1继续计数
MOV A,#8 ;计算高电平长度 CLR C ;减前清进/借位c SUBB A,R2 ;以R2的值判断此位的高/低(R2<8为0;r2>8为1) ;计数值<> MOV A,@R0 RRC A MOV @R0,A ;将接收到的一位存入对应的键值缓存区 INC R3 ;处理完一位 CJNE R3,#8,LL ;需收集8位 MOV R3,#0 ;收集到1字节 INC R0 ;需收集4字节 CJNE R0,#24H,LL ;用户码+用户码+操作码+操作反码
SETB X ;接收完成标志位置1 JB D,IEND ;如果D=1说明是学习模式跳过键值对比 AJMP DK ;跳到键值对比区
N1: INC R2 ;0.14mS R2加一次 CJNE R2,#30,L1 ;0.14ms 计数过长则时间到自动离开 IEND: RET
;----------------------- ; DELAY_0.14MS(以12M晶振/12T计算) ;----------------------- DEL: ;IR解码使用(1+2+128+2+4+4=141uS=0.14mS) MOV R5,#3 ;内部约6M/1T,3次;;;12M/1T,6次 DEL0: MOV R6,#2 ;1uS DEL1: MOV R7,#32 ;1uS*2次=2uS DJNZ R7,$ ;32*2uS*2次=128uS nop ;1uS*2次=2uS DJNZ R6,DEL1 ;2uS*2次=4uS DJNZ R5,DEL0 ;(1T单片机) RET ;2uS+(acall的)2uS=4uS
;----------------------- DK: MOV R0,#24H ;内部键值起始存放地址 MOV DPTR,#00H ;第1扇区起始地址 MOV R1,#4 ;读4个字节 DP1: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP1 ;循环读完4字节
MOV DPTR,#200H ;第2扇区起始地址 MOV R1,#4 ;读4个字节 DP2: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP2 ;循环读完4字节
MOV DPTR,#400H ;第3扇区起始地址 MOV R1,#4 ;读4个字节 DP3: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP3 ;循环读完4字节
MOV DPTR,#600H ;第4扇区起始地址 MOV R1,#4 ;读4个字节 DP4: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP4 ;循环读完4字节
MOV DPTR,#800H ;第5扇区起始地址 MOV R1,#4 ;读4个字节 DP5: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP5 ;循环读完4字节
MOV DPTR,#0A00H ;第6扇区起始地址 MOV R1,#4 ;读4个字节 DP6: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP6 ;循环读完4字节
MOV DPTR,#0C00H ;第7扇区起始地址 MOV R1,#4 ;读4个字节 DP7: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP7 ;循环读完4字节
MOV DPTR,#0E00H ;第8扇区起始地址 MOV R1,#4 ;读4个字节 DP8: ACALL EEPROMR ;读一字节 MOV @R0,A ;读出的数据存到相应地址 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,DP8 ;循环读完4字节
MOV A,20H ;接收到的用户码 CJNE A,24H,D1 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,25H,D1 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,26H,D1 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,27H,D1 ;与内部存放的对比 CPL LED1 ;都相同,则取反输出1状态
D1: MOV A,20H ;接收到的用户码 CJNE A,28H,D2 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,29H,D2 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,2AH,D2 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,2BH,D2 ;与内部存放的对比 CPL LED2 ;都相同,则取反输出2状态
D2: MOV A,20H ;接收到的用户码 CJNE A,2CH,D3 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,2DH,D3 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,2EH,D3 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,2FH,D3 ;与内部存放的对比 CPL LED3 ;都相同,则取反输出3状态
D3: MOV A,20H ;接收到的用户码 CJNE A,30H,D4 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,31H,D4 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,32H,D4 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,33H,D4 ;与内部存放的对比 CPL LED4 ;都相同,则取反输出4状态
D4: MOV A,20H ;接收到的用户码 CJNE A,34H,D5 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,35H,D5 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,36H,D5 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,37H,D5 ;与内部存放的对比 CPL LED5 ;都相同,则取反输出5状态
D5: MOV A,20H ;接收到的用户码 CJNE A,38H,D6 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,39H,D6 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,3AH,D6 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,3BH,D6 ;与内部存放的对比 CPL LED6 ;都相同,则取反输出6状态
D6: MOV A,20H ;接收到的用户码 CJNE A,3CH,D7 ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,3DH,D7 ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,3EH,D7 ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,3FH,D7 ;与内部存放的对比 CPL LED7 ;都相同,则取反输出7状态
D7: MOV A,20H ;接收到的用户码 CJNE A,40H,DEND ;与内部存放的对比 MOV A,21H ;接收到的用户反码 CJNE A,41H,DEND ;与内部存放的对比 MOV A,22H ;接收到的操作码 CJNE A,42H,DEND ;与内部存放的对比 MOV A,23H ;接收到的操作反码 CJNE A,43H,DEND ;与内部存放的对比 CPL LED8 ;都相同,则取反输出8状态 DEND: RET
;----------------------- KEYP30:CLR P3.0 ;P3.0与P3.1轮流输出0,实现矩阵键盘
KEY1: JB K1,KEY3 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K1,KEY3 ACALL OPEN_T0 ;打开T0计时判断长按 XH1: JBC Z,XUEXI1 ;长按跳转到学习1,并清零长按标志 JNB K1,XH1 CPL LED1 ;OUT1状态取反 RET XUEXI1: ;学习1 MOV DPTR,#00H ;第1扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#07FH ;LED1 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ1: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND1 ;5S后没接收到新数据则退出 JNB X,DZ1 ;接收完成标志为0则循环等待 ;写EEPROM数据不能调公共的'写',所以只能每次 ;学习模式里都有一堆程序重复写,浪费空间了!!! MOV DPTR,#00H ;第1扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP1: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP1 ;循环写完4字节 XEND1: CLR D ;退出学习模式 SETB LED1 ;关灯 RET ;退出
KEY3: JB K2,KEY5 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K2,KEY5 ACALL OPEN_T0 ;打开T0计时判断长按 XH3: JBC Z,XUEXI3 ;长按跳转到学习3,并清零长按标志 JNB K2,XH3 CPL LED3 ;OUT3状态取反 RET XUEXI3: ;学习3 MOV DPTR,#400H ;第3扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0DFH ;LED3 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ3: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND3 ;5S后没接收到新数据则退出 JNB X,DZ3 ;接收完成标志为0则循环等待
MOV DPTR,#400H ;第3扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP3: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP3 ;循环写完4字节 XEND3: CLR D ;退出学习模式 SETB LED3 ;关灯 RET ;退出
KEY5: JB K3,KEY7 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K3,KEY7 ACALL OPEN_T0 ;打开T0计时判断长按 XH5: JBC Z,XUEXI5 ;长按跳转到学习5,并清零长按标志 JNB K3,XH5 CPL LED5 ;OUT5状态取反 RET XUEXI5: ;学习5 MOV DPTR,#800H ;第5扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0F7H ;LED5 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ5: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND5 ;5S后没接收到新数据则退出 JNB X,DZ5 ;接收完成标志为0则循环等待
MOV DPTR,#800H ;第5扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP5: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP5 ;循环写完4字节 XEND5: CLR D ;退出学习模式 SETB LED5 ;关灯 RET ;退出
KEY7: JB K4,KP30OUT CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K4,KP30OUT ACALL OPEN_T0 ;打开T0计时判断长按 XH7: JBC Z,XUEXI7 ;长按跳转到学习7,并清零长按标志 JNB K4,XH7 CPL LED7 ;OUT7状态取反 RET XUEXI7: ;学习7 MOV DPTR,#0C00H ;第7扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0FDH ;LED7 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ7: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND7 ;5S后没接收到新数据则退出 JNB X,DZ7 ;接收完成标志为0则循环等待
MOV DPTR,#0C00H ;第7扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP7: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP7 ;循环写完4字节 XEND7: CLR D ;退出学习模式 SETB LED7 ;关灯 RET ;退出
KP30OUT: SETB P3.0 RET
;----------------------- KEYP31:CLR P3.1 ;P3.0与P3.1轮流输出0,实现矩阵键盘
KEY2: JB K1,KEY4 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K1,KEY4 ACALL OPEN_T0 ;打开T0计时判断长按 XH2: JBC Z,XUEXI2 ;长按跳转到学习2,并清零长按标志 JNB K1,XH2 CPL LED2 ;OUT2状态取反 RET XUEXI2: ;学习2 MOV DPTR,#200H ;第2扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0BFH ;LED2 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ2: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND2 ;5S后没接收到新数据则退出 JNB X,DZ2 ;接收完成标志为0则循环等待
MOV DPTR,#200H ;第2扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP2: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP2 ;循环写完4字节 XEND2: CLR D ;退出学习模式 SETB LED2 ;关灯 RET ;退出
KEY4: JB K2,KEY6 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K2,KEY6 ACALL OPEN_T0 ;打开T0计时判断长按 XH4: JBC Z,XUEXI4 ;长按跳转到学习4,并清零长按标志 JNB K2,XH4 CPL LED4 ;OUT4状态取反 RET XUEXI4: ;学习4 MOV DPTR,#600H ;第4扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0EFH ;LED4 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ4: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND4 ;5S后没接收到新数据则退出 JNB X,DZ4 ;接收完成标志为0则循环等待
MOV DPTR,#600H ;第4扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP4: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP4 ;循环写完4字节 XEND4: CLR D ;退出学习模式 SETB LED4 ;关灯 RET ;退出
KEY6: JB K3,KEY8 CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K3,KEY8 ACALL OPEN_T0 ;打开T0计时判断长按 XH6: JBC Z,XUEXI6 ;长按跳转到学习6,并清零长按标志 JNB K3,XH6 CPL LED6 ;OUT6状态取反 RET XUEXI6: ;学习6 MOV DPTR,#0A00H ;第6扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0FBH ;LED6 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ6: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND6 ;5S后没接收到新数据则退出 JNB X,DZ6 ;接收完成标志为0则循环等待
MOV DPTR,#0A00H ;第6扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP6: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP6 ;循环写完4字节 XEND6: CLR D ;退出学习模式 SETB LED6 ;关灯 RET ;退出
KEY8: JB K4,KP31OUT CLR TR0;这两句是为了防止在快速连按按键 (2015/10/10修改) MOV 45H,#0;或快速切换按键时,误判断进入学习模式 ACALL DELAY30MS ;延时去抖动 JB K4,KP31OUT ACALL OPEN_T0 ;打开T0计时判断长按 XH8: JBC Z,XUEXI8 ;长按跳转到学习8,并清零长按标志 JNB K4,XH8 CPL LED8 ;OUT8状态取反 RET XUEXI8: ;学习8 MOV DPTR,#0E00H ;第8扇区 ACALL PDSQ ;读数判断扇区是否为空 MOV P1,#0FEH ;LED8 SETB D ;学习模式标志位置1 ACALL OPEN_T0 ;开T0进行等待计时 DZ8: ACALL IR_IN ;在5S内循环调用红外接收程序 JBC z,XEND8 ;5S后没接收到新数据则退出 JNB X,DZ8 ;接收完成标志为0则循环等待
MOV DPTR,#0E00H ;第8扇区起始地址;存入新键值 MOV R0,#20H ;RAM中接收到的键值起始存放地址 MOV R1,#4 ;写4个字节 LP8: MOV A,@R0 ACALL EEPROMW ;写一字节 INC R0 ;内存地址加一 INC DPTR ;地址指针加一 DJNZ R1,LP8 ;循环写完4字节 XEND8: CLR D ;退出学习模式 SETB LED8 ;关灯 RET ;退出
KP31OUT: SETB P3.1 RET
;----------------------- DELAY30MS: ;6M/1T模式延时约30mS MOV R7,#6 DL1: MOV R6,#100 DL0: MOV R5,#150 DJNZ R5,$ DJNZ R6,DL0 DJNZ R7,DL1 RET
;----------------------- OPEN_T0: ;打开T0计时 MOV TH0,#3CH ;定时器0初值 MOV TL0,#0B0H ;内部约6MHz(100ms) CLR Z ;清长按标志 CLR X ;接收完成标志位清零 SETB TR0 ;打开T0 RET
;----------------------- T0INT: ;T0中断(判断长按) MOV TH0,#3CH ;重装初值 MOV TL0,#0B0H ;内部约6MHz(100ms) INC 45H ;中断计数约100ms一次 MOV A,45H CJNE A,#30,TOUT1 ;100ms*30=3s MOV 45H,#0 ;中断计数满30清零 SETB Z ;长按标志位置1 CLR TR0 ;关闭T0 TOUT1: RETI
;----------------------- PDSQ: ACALL EEPROMR ;读1个字节判断扇区是否为空 CJNE A,#0FFH,ERASE;扇区不为空则擦除扇区 RET
;----------------------- ;EEPROM相关操作 ;----------------------- ERASE:;擦除 MOV ISP_ADDRH,DPH ;送高地址 MOV ISP_ADDRL,DPL ;送低地址 MOV ISP_CONTR,#83H ;允许ISP/IAP操作(6~12MHz) MOV ISP_CMD,#03H ;扇区擦除 ACALL ISPCF ;触发IAP ACALL ISP_DISABLE ;禁止ISP/IAP操作 RET ;---------------------- EEPROMW:;写 MOV ISP_DATA,A ;ACC里是要写入的数据 MOV ISP_ADDRH,DPH ;送高地址 MOV ISP_ADDRL,DPL ;送低地址 MOV ISP_CONTR,#83H ;允许ISP/IAP操作(6~12MHz) MOV ISP_CMD,#02H ;送写命令 ACALL ISPCF ;触发IAP ACALL ISP_DISABLE ;禁止ISP/IAP操作 RET ;---------------------- EEPROMR: ;读 MOV ISP_ADDRH,DPH ;送高地址 MOV ISP_ADDRL,DPL ;送低地址 MOV ISP_CONTR,#83H ;允许ISP/IAP操作(6~12MHz) MOV ISP_CMD,#01H ;送读命令 ACALL ISPCF ;触发IAP MOV A,ISP_DATA ;读出的数据放到ACC ACALL ISP_DISABLE ;禁止ISP/IAP操作 RET ;---------------------- ISPCF: ;触发ISP/IAP MOV ISP_TRIG, #46H ;以MCU型号来定;STC12C2052(46H/0B9H) MOV ISP_TRIG, #0B9H ;11F和15F系列相同(5AH/0A5H) NOP RET ;---------------------- ISP_DISABLE: ;禁止ISP/IAP操作(出于安全考虑才要) MOV ISP_CONTR,#00H MOV ISP_CMD,#00H MOV ISP_TRIG,#00H MOV ISP_ADDRH,#0FFH MOV ISP_ADDRL,#0FFH RET ;-----------------------
|