今天發(fā)一個很好的學(xué)習(xí)型紅外遙控器的匯編語言程序,還可以用at24c16保存數(shù)據(jù),大家只需要在I/O定義區(qū)修改為自己的端口即可使用。
;;文件名:(紅外學(xué)習(xí)程序) ;;編寫時間:2002.04 ;;修改2002.11 增加脈寬校正,屏蔽未學(xué)習(xí)碼 ;;常數(shù)定義區(qū) ;;---------------------------------------------------------------------------------- SCIBUF EQU 14H ;串行發(fā)送緩沖區(qū)首地址 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 ;;寄存器定義區(qū) ;;---------------------------------------------------------------------------------- ;; SCICOM EQU 27H ;串行接收命令(=SCOM) SCILEN EQU 28H ;串行發(fā)送數(shù)據(jù)長度(=SLEN) CHANNEL EQU 29H SCISTEP EQU 2AH ;串行通信進(jìn)程狀態(tài)字節(jié) SCISP EQU 2BH ;串行發(fā)送數(shù)據(jù)區(qū)指針 ;; CRC EQU 2CH ;CRC校驗輸出寄存器 SCODE EQU 2DH ;CRC校驗輸入寄存器 TIP EQU 2EH SECOND EQU 2FH BUF_ST EQU 30H BUF_END EQU 5FH ;; ;;位定義區(qū) ;;---------------------------------------------------------------------------------- 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定義區(qū) ;;---------------------------------------------------------------------------------- ;IN BIT P1.4 ;紅外線接受口 BZ BIT P0.5 ;蜂鳴器輸出口 OUT BIT P1.7 ;紅外線發(fā)射口 WP BIT P0.0 ;寫保護(hù),為0時可讀寫,為1時不能寫 SDA BIT P1.3 ;模擬IIC數(shù)據(jù)傳送位 SCL BIT P1.2 ;模擬IIC時鐘控制狀態(tài)標(biāo)志 LED BIT P0.7 ;發(fā)光指示燈口 TR BIT P0.6 ;串行口接受發(fā)送控制位,為1:接收;為0:發(fā)送 ORG 0000H LJMP MAIN ORG 000BH LJMP T0SERVE ;T0中斷 ORG 0023H LJMP SINT ;串行中斷 ORG 0043H ;比較器2中斷 注意比較器中斷應(yīng)該是用于檢測紅外接收管傳送數(shù)據(jù)的 CLR TR0 注意比較器中即立即關(guān)閉定時器 篇幅有限中間省略 ;;****************************延時10微秒******************************************** DELAY: MOV R2, #5 DELAY1: MOV R3, #50 DJNZ R3, $ DJNZ R2, DELAY1 RET ;;---------------------------------------------------------------------------------- ;;名稱:SENTBYTE(字節(jié)數(shù)據(jù)傳送子程序) ;;功能:發(fā)送一個字節(jié)數(shù)據(jù)或地址給從接受器24C16 ;;輸入:A,即要發(fā)送的數(shù)據(jù)在ACC中 ;;輸出:B_ERROR,即發(fā)送數(shù)據(jù)錯誤標(biāo)志位,B_ERROR=0,發(fā)送數(shù)據(jù)正常; ;; B_ERROR=1,表示從接受器無應(yīng)答或損壞 ;;調(diào)用:無 ;;---------------------------------------------------------------------------------- ;;-------------------------------------------------------------------------- ;;名稱: W24C ;;功能: WRITE DATA TO 24C16 ;;輸入: SADD,R1,R2 ;;輸出: (無) ;;-------------------------------------------------------------------------- ;;調(diào)用: START,WBYTE,ACKN,STOP ;;-------------------------------------------------------------------------- ;;影響: A,R1,R2 ;;堆棧: 4 ;;-------------------------------------------------------------------------- ;;參數(shù)說明: ;; SADDH,SADDL:24C16 ADDRESS ;; R2:WRITE NUMBER 寫的數(shù)據(jù)的數(shù)量 ;; R1:RAM ADDRESS POINTER 所寫數(shù)據(jù)所在RAM區(qū)域的指針 ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- W24C: LCALL START ;IIC起始信號 MOV A, SADDH RL A ORL A, #0A0H LCALL WBYTE ;寫命令字節(jié) LCALL ACKN ;收應(yīng)答 MOV A, SADDL LCALL WBYTE ;寫2416的地址 LCALL ACKN ;收應(yīng)答 WD24: MOV A, @R1 INC R1 LCALL WBYTE LCALL ACKN DJNZ R2, WD24 LCALL STOP ;IIC結(jié)束信號 RET ;;-------------------------------------------------------------------------- ;;名稱: WBYTE ;;功能: WRITE ONE BYTE DATA TO 24C16 ;;輸入: A ;;輸出: (無) ;;-------------------------------------------------------------------------- ;;調(diào)用: (無) ;;-------------------------------------------------------------------------- ;;影響: A,R0 ;;堆棧: 2 ;;-------------------------------------------------------------------------- ;;參數(shù)說明: ;; A:發(fā)送數(shù)據(jù)(1字節(jié)) ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- 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 ;;輸出: (無) ;;-------------------------------------------------------------------------- ;;調(diào)用: START,WBYTE,ACKN,RBYTE,STOP ;;-------------------------------------------------------------------------- ;;影響: A,R1,R2 ;;堆棧: 4 ;;-------------------------------------------------------------------------- ;;參數(shù)說明: ;; 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 ;寫命令字節(jié) LCALL ACKN ;收應(yīng)答 MOV A, SADDL LCALL WBYTE ;地址字節(jié) LCALL ACKN ;收應(yīng)答 LCALL START MOV A, SADDH RL A ORL A, #0A1H 讀24C16 LCALL WBYTE ;讀命令字節(jié) LCALL ACKN ;收應(yīng)答 RC24: LCALL RBYTE ;讀2416 MOV @R1,A INC R1 DJNZ R2,RCX LCALL STOP ;IIC結(jié)束信號 RET RCX: LCALL ACKS ;發(fā)應(yīng)答 注意這里比較巧妙的結(jié)構(gòu)安排 SJMP RC24 ;;-------------------------------------------------------------------------- ;;名稱: RBYTE ;;功能: READ ONE BYTE DATA FROM 24C16 ;;輸入: (無) ;;輸出: A ;;-------------------------------------------------------------------------- ;;調(diào)用: (無) ;;-------------------------------------------------------------------------- ;;影響: A,R0 ;;堆棧: 2 ;;-------------------------------------------------------------------------- ;;參數(shù)說明: ;; A:接收數(shù)據(jù)(1字節(jié)) ;;-------------------------------------------------------------------------- ;;注意: ;;-------------------------------------------------------------------------- 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 ;;==================================================================== ;;接收應(yīng)答 ;;==================================================================== ACKN: SETB SDA SETB SCL NOP JB SDA, $ NOP NOP CLR SCL RET ;;==================================================================== ;;發(fā)送應(yīng)答 ;;==================================================================== ACKS: CLR SDA NOP NOP NOP SETB SCL NOP NOP NOP NOP CLR SCL RET ;;********************************************************************************** ;;名稱:START ;;描述:啟動IIC總線子程序---發(fā)送IIC起始條件 ;;********************************************************************************** START: SETB SDA ;發(fā)送起始條件的數(shù)據(jù)信號 NOP SETB SCL ;發(fā)送起始條件的時鐘信號 NOP ;起始條件建立時間大于4.7US NOP NOP NOP NOP CLR SDA ;發(fā)送起始信號 NOP ;起始條件鎖定時間大于4US NOP NOP NOP NOP CLR SCL ;鉗住IIC總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) RET ;;********************************************************************************** ;;名稱:STOP ;;描述:停止IIC總線子程序---發(fā)送IIC總線停止條件 ;;********************************************************************************** STOP: CLR SDA ;發(fā)送停止條件的數(shù)據(jù)信號 NOP SETB SCL ;發(fā)送停止條件的時鐘信號 NOP ;起始條件建立時間大于4US NOP NOP NOP NOP SETB SDA ;發(fā)送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 ;;================================================================================== ;;================================================================================== ;;串行口中斷服務(wù)子程序 ;;================================================================================== ;接收前四位命令: 1111 是接收處理正常,發(fā)送返回命令 ; 0000 是學(xué)習(xí)紅外線指令命令 ; 0001 是發(fā)送紅外線指令命令 ;接收后四位數(shù)據(jù)長度為1個字節(jié)0001 ;數(shù)據(jù)字節(jié):為學(xué)習(xí)或發(fā)送的按鍵值(就是EEPROM 的地址) ;設(shè)備類型+模塊地址是10000000 SINT: ;串行中斷服務(wù)子程序 PUSH PSW PUSH A SETB RS1 ;切換寄存器組 ; JBC RI, RINT ;RI=1,接收數(shù)據(jù),并將該位清0 JBC TI, TINT ;TI=1,發(fā)送數(shù)據(jù),并將該位清0 LJMP MAIN ;出錯返回主程序 注意這里出錯返回用的是跳轉(zhuǎn)指令 而不是中斷返回指令 ;;================================================================================== ;;串行數(shù)據(jù)發(fā)送子程序 ;;================================================================================== TINT: ;發(fā)送中斷 MOV A, SCILEN ;發(fā)送數(shù)據(jù)長度3入A JZ TINTOUT ;SLVADR=0,返回 DEC SCILEN ;SLVADR=SLVADR-1 CJNE A,#1,TINTC ;若SCILEN=1,則發(fā)送CRC校驗碼 MOV SBUF, CRC POP A POP PSW RETI TINTC: CLR TB8 ;清第9位,發(fā)送的是數(shù)據(jù) 從機只是應(yīng)答,不需要發(fā)送地址 MOV R0, #SCIBUF 為什么是緩沖區(qū)而不是指針 MOV A, @R0 MOV SBUF, A ;發(fā)送 MOV SCODE , A ;并對發(fā)送內(nèi)容進(jìn)行CRC校驗 LCALL ENCODE INC SCISP 發(fā)送緩沖區(qū)指針初始化是在哪進(jìn)行的???? POP A POP PSW RETI TINTOUT: mov a,channel channel做什么用???????? jz send1 anl channel,#7 MOV A, SCICOM 在發(fā)送的時候為什么要判命令字節(jié)???? CJNE A,#06H,SEND ;是學(xué)習(xí)紅外碼嗎? SETB I_LEARN 可見I_LEARN是學(xué)習(xí)紅外碼標(biāo)志,B_SEND是發(fā)射紅外碼標(biāo)志 CLR B_SEND SEND: CJNE A,#05H,SEND1 ;是發(fā)射紅外碼碼? SETB B_SEND CLR I_LEARN SEND1: SETB TR ;接收使能 發(fā)送完畢即啟動接收 SETB SM2 ;RB8=0,則RI不會被激活 POP A POP PSW RETI ;;================================================================================== ;;串行數(shù)據(jù)接收子程序 ;;================================================================================== RINT: JNB RB8, RVALID ;RB8=0,跳轉(zhuǎn)至數(shù)據(jù)接收 MOV A, SBUF CJNE A,SADDR, STEP0 ;接收的類型 地址不對就進(jìn)行串口初始化 CLR SM2 準(zhǔn)備接收數(shù)據(jù) MOV CRC, A ;CRC賦值(BITCNT與0的CRC校驗結(jié) ;果就是本身) MOV SCISTEP, #1 ;串行通信進(jìn)程為1 地址接收完畢 通信進(jìn)程加1 POP ACC POP PSW RETI ;;================================================================================== ;;接收數(shù)據(jù) ;;================================================================================== RVALID: MOV DPTR, #TBSTEP MOV A, SCISTEP ANL A, #03 RL A JMP @A+DPTR 注意這條基址加變址間接轉(zhuǎn)移指令 TBSTEP: AJMP STEP0 ;出錯,串行口初始化 AJMP STEP1 ;接收命令長度字節(jié) AJMP STEP2 ;接收數(shù)據(jù) AJMP STEP3 ;接收CRC校驗碼,處理信息 ;;================================================================================== ;;串行口初始化 ;;================================================================================== STEP0: ;串行中斷設(shè)置復(fù)位 MOV TMOD, #21H ;設(shè)置定時器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 ;;================================================================================== ;;獲得(串行命令+長度)字節(jié) ;;================================================================================== STEP1: ;接收命令長度字節(jié) MOV A, SBUF PUSH A 在堆棧中保存A ANL A, #0FH CJNE A,#1,STEP0 轉(zhuǎn)移之后沒有出棧指令是否會導(dǎo)致堆棧混亂?? MOV SCILEN, A ;取SLEN(BYTE2 4:0);后四位數(shù)據(jù)長度 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 ;調(diào)用CRC校驗子程序 INC SCISTEP MOV SCISP, #SCIBUF ;發(fā)送數(shù)據(jù)緩沖區(qū)的指針 注意這里初始化數(shù)據(jù)緩沖區(qū)指針 POP A POP PSW RETI ;;================================================================================== ;;接收數(shù)據(jù) ;;================================================================================== STEP2: ;接收數(shù)據(jù) MOV A, SBUF MOV CHANNEL, A 注意接收的數(shù)據(jù)放在CHANNEL中 MOV SCODE, A LCALL ENCODE INC SCISP ;接收緩沖區(qū)指針加1 接收的數(shù)據(jù)似乎沒有放入緩沖區(qū) INC SCISTEP ;等于0,進(jìn)程號加1后出中斷 POP A POP PSW RETI ;;================================================================================== ;;接收CRC校驗碼 ;;================================================================================== STEP3: ;接收CRC校驗碼 MOV A, SBUF CJNE A,CRC,STEP0 ;接收錯誤則復(fù)位 MOV SCIBUF, #0E0H 這是做什么??????? ;******************發(fā)送應(yīng)答信號***************************************************** CLR TR ;發(fā)送應(yīng)答使能 LCALL DELAY ;DELAY MOV SBUF, SADDR ;接收(類型+地址)=設(shè)定(類型+地址) 注意接收完之后要發(fā)送應(yīng)答 MOV CRC, SADDR ;(類型+地址)回送 MOV SCILEN, #02H ;發(fā)送數(shù)據(jù)長度為2個 STEP3RET: POP A POP PSW RETI