今天發一個很好的學習型紅外遙控器的匯編語言程序,還可以用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