分享

学习型红外遥控8路输出端—巧妙利用家里的旧遥控器

 zsok 2016-01-16



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
;-----------------------

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多