今天发一个很好的学习型红外遥控器的汇编语言程序,还可以用at24c16保存数据,大家只需要在I/O定义区修改为自己的端口即可使用。
;;文件名:(红外学习程序) ;;编写时间:2002.04 ;;修改2002.11 增加脉宽校正,屏蔽未学习码 ;;常数定义区 ;;---------------------------------------------------------------------------------- SCIBUF EQU 14H ;串行发送缓冲区首地址 R_TH0 EQU 03H R_TL0 EQU 04H SP_TREG EQU 05H N_TREG EQU 06H SP_START EQU 07H SP_END EQU 0BH LP EQU 0DH SADDH EQU 0EH ;24C16地址 SADDL EQU 0FH ;24C16地址 TREG0L EQU 60H TREG0H EQU 61H LENTH EQU 61H TREG1H EQU 62H TREG1L EQU 63H TREG2H EQU 64H TREG2L EQU 65H TREG3H EQU 66H TREG3L EQU 67H TREG4H EQU 68H TREG4L EQU 69H TREG5H EQU 6AH TREG5L EQU 6BH TREG6H EQU 6CH TREG6L EQU 6DH TREG7H EQU 6EH TREG7L EQU 6FH ;;寄存器定义区 ;;---------------------------------------------------------------------------------- ;; SCICOM EQU 27H ;串行接收命令(=SCOM) SCILEN EQU 28H ;串行发送数据长度(=SLEN) CHANNEL EQU 29H SCISTEP EQU 2AH ;串行通信进程状态字节 SCISP EQU 2BH ;串行发送数据区指针 ;; CRC EQU 2CH ;CRC校验输出寄存器 SCODE EQU 2DH ;CRC校验输入寄存器 TIP EQU 2EH SECOND EQU 2FH BUF_ST EQU 30H BUF_END EQU 5FH ;; ;;位定义区 ;;---------------------------------------------------------------------------------- B_TURN BIT 0H B_LFAIL BIT 1H B_LEARN BIT 2H I_LEARN BIT 3H ;I_SEND BIT 4H B_SDEND BIT 5H B_SEND BIT 6H ;;I/O定义区 ;;---------------------------------------------------------------------------------- ;IN BIT P1.4 ;红外线接受口 BZ BIT P0.5 ;蜂鸣器输出口 OUT BIT P1.7 ;红外线发射口 WP BIT P0.0 ;写保护,为0时可读写,为1时不能写 SDA BIT P1.3 ;模拟IIC数据传送位 SCL BIT P1.2 ;模拟IIC时钟控制状态标志 LED BIT P0.7 ;发光指示灯口 TR BIT P0.6 ;串行口接受发送控制位,为1:接收;为0:发送 ORG 0000H LJMP MAIN ORG 000BH LJMP T0SERVE ;T0中断 ORG 0023H LJMP SINT ;串行中断 ORG 0043H ;比较器2中断 注意比较器中断应该是用于检测红外接收管传送数据的 CLR TR0 注意比较器中即立即关闭定时器 篇幅有限中间省略 ;;****************************延时10微秒******************************************** DELAY: MOV R2, #5 DELAY1: MOV R3, #50 DJNZ R3, $ DJNZ R2, DELAY1 RET ;;---------------------------------------------------------------------------------- ;;名称:SENTBYTE(字节数据传送子程序) ;;功能:发送一个字节数据或地址给从接受器24C16 ;;输入:A,即要发送的数据在ACC中 ;;输出:B_ERROR,即发送数据错误标志位,B_ERROR=0,发送数据正常; ;; B_ERROR=1,表示从接受器无应答或损坏 ;;调用:无 ;;---------------------------------------------------------------------------------- ;;-------------------------------------------------------------------------- ;;名称: W24C ;;功能: WRITE DATA TO 24C16 ;;输入: SADD,R1,R2 ;;输出: (无) ;;-------------------------------------------------------------------------- ;;调用: START,WBYTE,ACKN,STOP ;;-------------------------------------------------------------------------- ;;影响: A,R1,R2 ;;堆栈: 4 ;;-------------------------------------------------------------------------- ;;参数说明: ;; SADDH,SADDL:24C16 ADDRESS ;; R2:WRITE NUMBER 写的数据的数量 ;; R1:RAM ADDRESS POINTER 所写数据所在RAM区域的指针 ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- W24C: LCALL START ;IIC起始信号 MOV A, SADDH RL A ORL A, #0A0H LCALL WBYTE ;写命令字节 LCALL ACKN ;收应答 MOV A, SADDL LCALL WBYTE ;写2416的地址 LCALL ACKN ;收应答 WD24: MOV A, @R1 INC R1 LCALL WBYTE LCALL ACKN DJNZ R2, WD24 LCALL STOP ;IIC结束信号 RET ;;-------------------------------------------------------------------------- ;;名称: WBYTE ;;功能: WRITE ONE BYTE DATA TO 24C16 ;;输入: A ;;输出: (无) ;;-------------------------------------------------------------------------- ;;调用: (无) ;;-------------------------------------------------------------------------- ;;影响: A,R0 ;;堆栈: 2 ;;-------------------------------------------------------------------------- ;;参数说明: ;; A:发送数据(1字节) ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- WBYTE: MOV R0,#8 XWB1: RLC A NOP NOP MOV SDA,C NOP SETB SCL NOP NOP NOP NOP NOP CLR SCL DJNZ R0,XWB1 RET ;;-------------------------------------------------------------------------- ;;名称: R24C ;;功能: READ DATA FROM 24C16 ;;输入: SADD,R1,R2 ;;输出: (无) ;;-------------------------------------------------------------------------- ;;调用: START,WBYTE,ACKN,RBYTE,STOP ;;-------------------------------------------------------------------------- ;;影响: A,R1,R2 ;;堆栈: 4 ;;-------------------------------------------------------------------------- ;;参数说明: ;; SADD:24C16 ADDRESS ;; R2:WRITE NUMBER ;; R1:RAM ADDRESS POINTER ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- R24C: LCALL START ;IIC起始信号 MOV A, SADDH SADDH是个什么样的地址???????? RL A ORL A, #0A0H LCALL WBYTE ;写命令字节 LCALL ACKN ;收应答 MOV A, SADDL LCALL WBYTE ;地址字节 LCALL ACKN ;收应答 LCALL START MOV A, SADDH RL A ORL A, #0A1H 读24C16 LCALL WBYTE ;读命令字节 LCALL ACKN ;收应答 RC24: LCALL RBYTE ;读2416 MOV @R1,A INC R1 DJNZ R2,RCX LCALL STOP ;IIC结束信号 RET RCX: LCALL ACKS ;发应答 注意这里比较巧妙的结构安排 SJMP RC24 ;;-------------------------------------------------------------------------- ;;名称: RBYTE ;;功能: READ ONE BYTE DATA FROM 24C16 ;;输入: (无) ;;输出: A ;;-------------------------------------------------------------------------- ;;调用: (无) ;;-------------------------------------------------------------------------- ;;影响: A,R0 ;;堆栈: 2 ;;-------------------------------------------------------------------------- ;;参数说明: ;; A:接收数据(1字节) ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- RBYTE: SETB SDA MOV R0, #8 XRB1: SETB SCL NOP NOP NOP MOV C, SDA CLR SCL RLC A NOP NOP DJNZ R0, XRB1 RET ;;==================================================================== ;;接收应答 ;;==================================================================== ACKN: SETB SDA SETB SCL NOP JB SDA, $ NOP NOP CLR SCL RET ;;==================================================================== ;;发送应答 ;;==================================================================== ACKS: CLR SDA NOP NOP NOP SETB SCL NOP NOP NOP NOP CLR SCL RET ;;********************************************************************************** ;;名称:START ;;描述:启动IIC总线子程序---发送IIC起始条件 ;;********************************************************************************** START: SETB SDA ;发送起始条件的数据信号 NOP SETB SCL ;发送起始条件的时钟信号 NOP ;起始条件建立时间大于4.7US NOP NOP NOP NOP CLR SDA ;发送起始信号 NOP ;起始条件锁定时间大于4US NOP NOP NOP NOP CLR SCL ;钳住IIC总线,准备发送或接收数据 RET ;;********************************************************************************** ;;名称:STOP ;;描述:停止IIC总线子程序---发送IIC总线停止条件 ;;********************************************************************************** STOP: CLR SDA ;发送停止条件的数据信号 NOP SETB SCL ;发送停止条件的时钟信号 NOP ;起始条件建立时间大于4US NOP NOP NOP NOP SETB SDA ;发送IIC总线停止信号 NOP NOP NOP NOP RET ;;================================================================================== GETADDR: MOV A,#70H 注意模块类型地址是70 MOV C,P1.5 MOV ACC.3,C MOV C,P1.6 MOV ACC.2,C MOV C,P1.7 MOV ACC.1,C MOV C,P0.0 MOV ACC.0,C MOV SADDR,A RET ;;================================================================================== ;;================================================================================== ;;串行口中断服务子程序 ;;================================================================================== ;接收前四位命令: 1111 是接收处理正常,发送返回命令 ; 0000 是学习红外线指令命令 ; 0001 是发送红外线指令命令 ;接收后四位数据长度为1个字节0001 ;数据字节:为学习或发送的按键值(就是EEPROM 的地址) ;设备类型+模块地址是10000000 SINT: ;串行中断服务子程序 PUSH PSW PUSH A SETB RS1 ;切换寄存器组 ; JBC RI, RINT ;RI=1,接收数据,并将该位清0 JBC TI, TINT ;TI=1,发送数据,并将该位清0 LJMP MAIN ;出错返回主程序 注意这里出错返回用的是跳转指令 而不是中断返回指令 ;;================================================================================== ;;串行数据发送子程序 ;;================================================================================== TINT: ;发送中断 MOV A, SCILEN ;发送数据长度3入A JZ TINTOUT ;SLVADR=0,返回 DEC SCILEN ;SLVADR=SLVADR-1 CJNE A,#1,TINTC ;若SCILEN=1,则发送CRC校验码 MOV SBUF, CRC POP A POP PSW RETI TINTC: CLR TB8 ;清第9位,发送的是数据 从机只是应答,不需要发送地址 MOV R0, #SCIBUF 为什么是缓冲区而不是指针 MOV A, @R0 MOV SBUF, A ;发送 MOV SCODE , A ;并对发送内容进行CRC校验 LCALL ENCODE INC SCISP 发送缓冲区指针初始化是在哪进行的???? POP A POP PSW RETI TINTOUT: mov a,channel channel做什么用???????? jz send1 anl channel,#7 MOV A, SCICOM 在发送的时候为什么要判命令字节???? CJNE A,#06H,SEND ;是学习红外码吗? SETB I_LEARN 可见I_LEARN是学习红外码标志,B_SEND是发射红外码标志 CLR B_SEND SEND: CJNE A,#05H,SEND1 ;是发射红外码码? SETB B_SEND CLR I_LEARN SEND1: SETB TR ;接收使能 发送完毕即启动接收 SETB SM2 ;RB8=0,则RI不会被激活 POP A POP PSW RETI ;;================================================================================== ;;串行数据接收子程序 ;;================================================================================== RINT: JNB RB8, RVALID ;RB8=0,跳转至数据接收 MOV A, SBUF CJNE A,SADDR, STEP0 ;接收的类型 地址不对就进行串口初始化 CLR SM2 准备接收数据 MOV CRC, A ;CRC赋值(BITCNT与0的CRC校验结 ;果就是本身) MOV SCISTEP, #1 ;串行通信进程为1 地址接收完毕 通信进程加1 POP ACC POP PSW RETI ;;================================================================================== ;;接收数据 ;;================================================================================== RVALID: MOV DPTR, #TBSTEP MOV A, SCISTEP ANL A, #03 RL A JMP @A+DPTR 注意这条基址加变址间接转移指令 TBSTEP: AJMP STEP0 ;出错,串行口初始化 AJMP STEP1 ;接收命令长度字节 AJMP STEP2 ;接收数据 AJMP STEP3 ;接收CRC校验码,处理信息 ;;================================================================================== ;;串行口初始化 ;;================================================================================== STEP0: ;串行中断设置复位 MOV TMOD, #21H ;设置定时器0和1为方式2,定时控制方式,以运行控制位TR0,TR1启动定时器 注意这里串口初始化包括初始化定时器、串口配置以及 MOV TH1, #0FAH MOV TL1, #0FAH ;波特率为4800 MOV SCON, #0F0H ;串口工作方式3,多机通信控制,允许接收 SETB SM2 MOV SADEN, #0FFH SETB TR1 ;启动T1定时 POP A POP PSW RETI ;;================================================================================== ;;获得(串行命令+长度)字节 ;;================================================================================== STEP1: ;接收命令长度字节 MOV A, SBUF PUSH A 在堆栈中保存A ANL A, #0FH CJNE A,#1,STEP0 转移之后没有出栈指令是否会导致堆栈混乱?? MOV SCILEN, A ;取SLEN(BYTE2 4:0);后四位数据长度 A不为1则初始化串口是什么意思呢????? POP A ;SLEN=0 MOV SCODE, A ;CRC校验 ANL A, #0F0H ;取SCOM 前四位命令 SWAP A ;高低四位交换 RR A MOV SCICOM, A ;SUBADR(2:0) LCALL ENCODE ;调用CRC校验子程序 INC SCISTEP MOV SCISP, #SCIBUF ;发送数据缓冲区的指针 注意这里初始化数据缓冲区指针 POP A POP PSW RETI ;;================================================================================== ;;接收数据 ;;================================================================================== STEP2: ;接收数据 MOV A, SBUF MOV CHANNEL, A 注意接收的数据放在CHANNEL中 MOV SCODE, A LCALL ENCODE INC SCISP ;接收缓冲区指针加1 接收的数据似乎没有放入缓冲区 INC SCISTEP ;等于0,进程号加1后出中断 POP A POP PSW RETI ;;================================================================================== ;;接收CRC校验码 ;;================================================================================== STEP3: ;接收CRC校验码 MOV A, SBUF CJNE A,CRC,STEP0 ;接收错误则复位 MOV SCIBUF, #0E0H 这是做什么??????? ;******************发送应答信号***************************************************** CLR TR ;发送应答使能 LCALL DELAY ;DELAY MOV SBUF, SADDR ;接收(类型+地址)=设定(类型+地址) 注意接收完之后要发送应答 MOV CRC, SADDR ;(类型+地址)回送 MOV SCILEN, #02H ;发送数据长度为2个 STEP3RET: POP A POP PSW RETI