专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

学习型红外遥控器汇编源代码

作者:佚名   来源:本站原创   点击数:  更新时间:2010年08月13日   【字体:

  今天发一个很好的学习型红外遥控器的汇编语言程序,还可以用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
关闭窗口

相关文章