2051单片机仿PT2272软件解码程序
时间:09-14
来源:互联网
点击:
本程序是用51单片机来软件解码pt2262编码,是一个无线服务呼叫器的代码已经成功的在产品的应用,有LED显示.
并有原理图与pcb文件以及完整的代码提供下载:
http://www.51hei.com/ziliao/file/37724122PT2272.rar
; =========================================================; ================================================================; PT2272 模拟解码器(接收来自射频解码模块的2262格式串行数据流); 管理三位数码管显示器; 利用AT24C32实现堆栈式掉电缓存保护,通过特殊的清除发射器清除堆栈; 显示器具有两级亮度变化; 具有蜂鸣器,新的编码收到后,蜂鸣器鸣响2/3次,显示器高亮,三秒后正常;; CPU: AT89C2051@12MHz;; COPYRIGHT yanggt@163.net SEP 9, 2004; ===============================================================; ===================================================================EESIZE EQU 32768 ;EEPROM容量(32768/16384/8192/4096/2048/1024/512)PWDF EQU 50H ;EEPROM中用于标识历史记录有效MYA0_3 EQU 00010101B ;有效识别码,不匹配则不响应MYCLRL EQU 00H ;主控手机编码值(目前为 0000H)MYCLRH EQU 00H ;根据A4-A11计算得到(00 D7 D6 D5 D4 D3 D2 D1)(D0)BELONT EQU 40 ;声音鸣响时间BELOFT EQU 20 ;静音时间SCL BIT P3.0 ;AT24C32(4K字节)SDA BIT P3.1SIGPIN BIT P3.2 ;接收信号入口BELL BIT P3.3 ;蜂鸣器控制VSEL BIT P1.0 ;LED亮度选择,H=高亮度U0E BIT P3.5 ;个位LED位选U1E BIT P3.4 ;十位LED位选U2E BIT P3.7 ;百位LED位选BELLSW BIT 78H ;蜂鸣器运行期间=1EEEMPTY BIT 79H ;EEPROM空标志BELLON BIT 7AH ;通知蜂鸣器鸣响CODEOK BIT 7BH ;收到的编码正确TMK250 BIT 7CH ;250us标志,每250us置位一次SIGING BIT 7DH ;手机发射信号正在持续=1,无信号=0LEDHIGH BIT 7EH ;显示器亮度标志=0:正常;=1:高亮TOUTMK BIT 7FH ;显示器降低亮度时间已到=1RBUF81 DATA 20H ;后8位第一次采样结果A4-A11RBUF82 DATA 21H ;后8位第二次采样结果A4-A11RBUF44 DATA 22H ;前4位第12次采样结果A0-A3SIGPOT DATA 23H ;接收引脚上次电平,直接保存P3口全部内容SIGMSK EQU 04H ;SIG----P3.2TCNTL DATA 24H ;定时计数器(4ms时基)TCNTH DATA 25HTMX16 DATA 26H ;16*250=4000us=4msBELLTM DATA 27H ;鸣响时间DBUF0 DATA 28H ;个位显示缓冲区DBUF1 DATA 29H ;十位DBUF2 DATA 2AH ;百位EEPTRL DATA 2BH ;EEPROM当前位置指针EEPTRH DATA 2CHEEPOL DATA 2DH ;保存清除指针EEPOH DATA 2EH ;RES2F DATA 2FH ;使用其中的标志位EEBUF DATA 30H ;30-37H, I2C缓冲区BELLCNT DATA 38H ;鸣响次数计数器(3/2/1)BELLTMK DATA 39HCODEL DATA 40H ;接收到编码低位CODEH DATA 41H ; 高位CODELK DATA 42H ;保存上一个编码CODEHK DATA 43H ;CODE1L DATA 44HCODE1H DATA 45H; =======================================================; =============================================================ORG 0000HLJMP START; ===================================================================; 250us进入一次,每16次(4ms)切换一次显示位; ==================================================================ORG 000BH ;定时器0中断入口,独占 R7TM0SUB: SETB TMK250TM0_4MS:DJNZ TMX16, TM0_EMOV TMX16, #10HJNB BELLSW, TM0_CLYDJNZ BELLTM, TM0_CLYSETB BELLONTM0_CLY:JB TOUTMK, TM0_0 ;每4ms执行一次DJNZ TCNTL, TM0_0DJNZ TCNTH, TM0_0SETB TOUTMKTM0_0: CJNE R7, #0, TM0_1 ;当前显示位CLR U2EMOV P1, DBUF0INC R7SETB U0ERETITM0_1: CJNE R7, #1, TM0_2CLR U0EMOV P1, DBUF1INC R7SETB U1ERETITM0_2: CLR U1EMOV P1, DBUF2MOV R7, #0SETB U2ERETITM0_E: RETI; ===============================================================; =======================================================START: MOV P1, #00H ;关闭显示器,正常亮度CLR BELLONCLR BELLACALL EECHK ;检查EEPROM,确定指针,提取其中最后一个历史记录号码ACALL TOBUFMOV TMX16, #10H ;中断计数寄存器置初始值16SETB TOUTMK ;延迟定时器处于停止状态CLR U0ECLR U1ECLR U2EMOV R7, #00H ;从第一位开始显示MOV TMOD, #12H ;TIMER0, MODE 2, TIMER1, MODE 1MOV TL0, #06HMOV TH0, #06H ;时间=250usSETB TR0SETB ET0SETB EAMOV A, #6-1 ;开机时蜂鸣器自动鸣响ACALL BELL_SMOV BELLTM, #BELONT-20ACALL LEDOFFCLR LEDHIGH ;关闭高亮度MOV SIGPOT, #00H ;假设开始时接收引脚=0CLR SIGINGSETB F0;=--=--=--=--=--=--=--=--=--=--==--=--=--=--=--=--MAIN: JNB BELLSW, MAIN_S0ACALL BELL_MMAIN_S0:JNB LEDHIGH, MAIN_00 ;显示器普通亮度,不检查标志JNB TOUTMK, MAIN_0ACALL LEDOFF ;显示器回到正常亮度CLR LEDHIGHJB EEEMPTY, MAIN_0 ;没有尚未确认的编码AJMP MAIN_01MAIN_00:JB EEEMPTY, MAIN_0 ;没有尚未确认的编码JNB TOUTMK, MAIN_0MOV A, #2-1ACALL BELL_S ;鸣响MAIN_01:MOV TCNTL, #LOW(5000/4) ;高亮度持续3000ms=3s后恢复MOV TCNTH, #HIGH(5000/4)CLR TOUTMKMOV BELLTM, #30MAIN_0: MOV A, P3 ;监视SIG引脚电平变化XCH A, SIGPOTXRL A, SIGPOTANL A, #SIGMSKJZ MAIN ;A=0表示引脚电平无变化SETB F0ACALL GETCOD ;开始接收,出错后直接返回JC MAIN ;接收代码无效,舍弃。ACALL FINDJC MAIN ;C=1,表示代码无效,什么也不发生MOV CODE1L, CODELMOV CODE1H, CODEHCLR F0ACALL GETCOD ;开始接收,出错后直接返回SETB F0JC MAIN ;接收代码无效,舍弃。ACALL FINDJC MAIN ;C=1,表示代码无效,什么也不发生MOV B, AMOV A, CODE1LXRL A, CODELJNZ MAIN_0DMOV A, CODE1HXRL A, CODEHJZ MAIN_0CMAIN_0D:MOV CODE1L, CODELMOV CODE1H, CODEHCLR F0ACALL GETCOD ;开始接收,出错后直接返回SETB F0JC MAIN ;接收代码无效,舍弃。ACALL FINDJC MAIN ;C=1,表示代码无效,什么也不发生MOV B, AMOV A, CODE1LXRL A, CODELJNZ MAIN_EMOV A, CODE1HXRL A, CODEHJNZ MAIN_EMAIN_0C:MOV A, BJNZ MAIN_1 ;A=1:主控手机,转去退栈MOV BELLCNT, #4-1MOV A, CODELXRL A, CODELKJNZ MAIN_0AMOV A, CODEHXRL A, CODEHKJZ MAIN_0B;这里可以进行编码过滤=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-MAIN_0A:MOV BELLCNT, #6-1ACALL EEPUSH ;其他手机,转去保存、显示ACALL TOBUFMAIN_0B:SETB TOUTMKMOV TCNTL, #LOW(3000/4) ;高亮度持续3000ms=3s后恢复MOV TCNTH, #HIGH(3000/4)CLR TOUTMKSETB LEDHIGH ;显示器进入高亮状态MOV A, BELLCNTACALL BELL_S ;鸣响MOV BELLTM, #BELONTAJMP MAINMAIN_1: MOV A, CODEL ;核对手机号码XRL A, #MYCLRLJNZ MAIN_EMOV A, CODEHXRL A, #MYCLRHJNZ MAIN_EACALL EEPOP ;执行退栈操作MAIN_E: AJMP MAIN; =============================================================; 主程序结束; ============================================================BELL_S: MOV BELLCNT, ASETB BELLSWSETB BELLRET; ===============================================================BELL_M: JBC BELLON, BELLMRETBELLM: MOV A, BELLCNTBELLM0: JNB ACC.0, BELLM1MOV BELLTM, #BELOFT ;A.0=1,正在鸣响,应该关闭CLR BELLAJMP BELLM9BELLM1: MOV BELLTM, #BELONT ;静音状态,应该打开SETB BELLBELLM9: DJNZ BELLCNT, BELLMECLR BELLSWCLR BELLBELLME: RET; ===================================================================LEDOFF: ANL DBUF0, #0FEHANL DBUF1, #0FEHANL DBUF2, #0FEHRET; ================================================================; ============================================================TM1SET: CLR TR1 ;1,ACALL=2CLR TF1 ;1MOV TL1, DPL ;2MOV TH1, DPH ;2SETB TR1 ;1RET ;2, TOTAL=2+1+1+2+2+1+2=11us; =====================================================================; 接收代码,收到两个相同的编码即认可。; 发射结束后接收下一个。; =============================================================GETCOD: NOPGETC_S: MOV DPTR, #65535-50000 ;在50ms内搜索至少持续4ms的低电平 [***]ACALL TM1SETGETC_S0:MOV R6, #16 ;16*250us=4000us=4msGETC_S1:CLR TMK250GETC_S2:JB TF1, GETC_E ;这里超时认为目前无发射器工作,或上次发射已结束。JB SIGPIN, GETC_S0JNB TMK250, GETC_S2DJNZ R6, GETC_S1MOV R5, #4*2 ;首先接收A0-A3,共4位,8个采样点MOV DPTR, #65535-8000 ;在接下来的8ms内必须出现上升沿 [***]ACALL TM1SETGETC_0: JB TF1, GETC_E ;这里超时认为目前无发射器工作,或上次发射已结束。JNB SIGPIN, GETC_0; JB SIGING, GETC_F ;上次发射尚未结束,直接返回,不接收编码。; AJMP GETC_20JNB SIGING, GETC_20 ;上次发射尚未结束,直接返回,不接收编码。JNB F0, GETC_20AJMP GETC_FGETC_1P:MOV DPTR, #65535-1250+11+2 ;在接下来的1250us内必须出现低电平 [***]ACALL TM1SETGETC_1: JB TF1, GETC_F ;超时JB SIGPIN, GETC_1MOV DPTR, #65535-1250+11+2 ;在接下来的1250us内必须出现上升沿 [***]ACALL TM1SETGETC_2: JB TF1, GETC_F ;超时JNB SIGPIN, GETC_2GETC_20:MOV DPTR, #65535-500+11+2 ;固定延迟500us后采样ACALL TM1SETJNB TF1, $MOV C, SIGPIN ;采样接收信号MOV A, RBUF44RLC AMOV RBUF44, ADJNZ R5, GETC_1P ;循环接收4个数据位,进行8次采样MOV R5, #8*2 ;接收A4-A11,共8个数据位,16个采样点MOV R0, #RBUF81 ;RBUF81存放第一次采样值GETC_3P:MOV DPTR, #65535-1250+11+2 ;在接下来的1250us内必须出现低电平 [***]ACALL TM1SETGETC_3: JB TF1, GETC_F ;超时JB SIGPIN, GETC_3MOV DPTR, #65535-1250+11+2 ;在接下来的1250us内必须出现上升沿 [***]ACALL TM1SETGETC_4: JB TF1, GETC_F ;超时JNB SIGPIN, GETC_4GETC_40:MOV DPTR, #65535-500+11+2 ;固定延迟500us后采样ACALL TM1SETJNB TF1, $MOV C, SIGPIN ;采样接收信号MOV A, @R0RLC AMOV @R0, AXRL 00H, #RBUF81 ;在RBUF81和RBUF82之间切换XRL 00H, #RBUF82DJNZ R5, GETC_3P ;循环接收8个数据位,进行16次采样SETB SIGINGCLR CRETGETC_E: CLR SIGINGGETC_F: SETB CRET; ===========================================================; ===============================================================FIND: MOV A, RBUF44 ;分析代码CJNE A, #MYA0_3, FIND_EMOV R4, RBUF81MOV R5, RBUF82MOV R6, #7MOV R0, #00HMOV R1, #00HFIND_L: MOV A, R0 ;结果乘以 3CLR CRLC AMOV B, AMOV A, R1RLC AXCH A, BADD A, R0MOV R0, AMOV A, BADDC A, R1MOV R1, A ;结果乘以 3 结束MOV A, R4RLC AMOV R4, A ;D7-->CMOV A, R5RL AMOV R5, AANL A, #01H ;D7-->A.0ADDC A, R0 ;A.0+C+R0MOV R0, AMOV A, R1ADDC A, #00HMOV R1, ADJNZ R6, FIND_L ;确定A4-A10的编码结果CLR AMOV C, RBUF81.0 ;分析代码,确定是否主控手机MOV ACC.0, CMOV C, RBUF82.0ADDC A, #00H ;A=(0,1,2)。A=0:非主控手机;A=1:主控手机;A=2:无效手机JB ACC.1, FIND_E ;A=2!MOV CODEL, R0MOV CODEH, R1CLR CRET ;A=0/1FIND_E: SETB CRET; ===============================================================; ======================================================================EECHK: MOV EEPTRL, #00H ;0000H记录不用,因为0000H用于判断EEPROM是否空MOV EEPTRH, #00HMOV EEBUF, #00HMOV EEBUF+1, #00HEECHK0: MOV CODEL, EEBUF ;放到编码缓冲区MOV CODEH, EEBUF+1ANL CODEH, #0FHMOV DPL, EEPTRL ;读取栈底的两个字节MOV DPH, EEPTRHINC DPTRINC DPTR ;指向下一个记录,但是暂时不修改指针MOV A, DPHADD A, #HIGH(65536-EESIZE) ;???JC EECHK9 ;已经检查完所有记录空间。MOV EEPOL, DPLMOV EEPOH, DPH ;暂时保存在这里MOV R0, #EEBUFMOV B, #02HACALL I2CD_RMOV A, EEBUF+1ANL A, #0F0HXRL A, #PWDFJNZ EECHK9MOV EEPTRL, EEPOLMOV EEPTRH, EEPOHAJMP EECHK0EECHK9: CLR EEEMPTY ;假设非空MOV A, EEPTRLORL A, EEPTRHJNZ EECHKESETB EEEMPTY ;声明EEPROM空EECHKE: RET; =======================================================================; =============================================================EEPUSH: MOV EEBUF, CODEL ;写入EEPROM栈,采用实栈顶MOV EEBUF+1, CODEHORL EEBUF+1, #PWDF ;标志,50HMOV DPL, EEPTRLMOV DPH, EEPTRHINC DPTR ;每个记录进入,指针加 2INC DPTRMOV A, DPH ;进行堆栈溢出检查ADD A, #HIGH(65536-EESIZE)JC EEPUSHEANL DPL, #0FEHMOV EEPTRL, DPLMOV EEPTRH, DPHMOV R0, #EEBUFMOV B, #02HACALL I2CD_WCLR EEEMPTY ;声明EEPROM非空EEPUSHE:RET; ============================================================; ================================================================EEPOP: MOV A, EEPTRL ;EEPROM退出操作ORL A, EEPTRHJZ EEPOPBEEPOP0: MOV EEPOL, EEPTRLMOV EEPOH, EEPTRHCLR C ;指针减 2,指向上一个数据MOV A, EEPTRLSUBB A, #02HMOV EEPTRL, AMOV A, EEPTRHSUBB A, #00HMOV EEPTRH, A ;指针已经更新MOV A, EEPTRL ;检查退出一个记录后,堆栈是否变空?ORL A, EEPTRHJNZ EEPOP1MOV CODEL, AMOV CODEH, ASETB EEEMPTY ;声明EEPROM空AJMP EEPOP9EEPOP1: MOV DPL, EEPTRL ;读取栈顶记录MOV DPH, EEPTRHMOV R0, #EEBUFMOV B, #02HACALL I2CD_RMOV CODEL, EEBUF ;放到编码缓冲区MOV CODEH, EEBUF+1ANL CODEH, #0FH ;屏蔽掉标志EEPOP9: MOV EEBUF, #00H ;清除刚才已经退栈的记录MOV EEBUF+1, #00HMOV DPL, EEPOLMOV DPH, EEPOHMOV R0, #EEBUFMOV B, #02HACALL I2CD_WACALL TOBUF ;送到显示缓冲区ACALL LEDOFFEEPOPB: MOV A, #2-1ACALL BELL_S ;鸣响; MOV BELLTM, #30EEPOPE: RET; ======================================================; =====================================================================TOBUF: MOV A, CODEL ;填写显示缓冲区MOV B, CODEH ;/100MOV R2, #00HTOBUF_0:CLR CSUBB A, #100XCH A, BSUBB A, #00HXCH A, BJC TOBUF_8INC R2AJMP TOBUF_0TOBUF_8:ADD A, #100MOV B, #10div ABMOV DPTR, #FONTMOVC A, @A+DPTRMOV DBUF1, AMOV A, BMOVC A, @A+DPTRMOV DBUF0, AMOV A, R2MOVC A, @A+DPTRMOV DBUF2, AMOV CODELK, CODELMOV CODEHK, CODEHRET; =================================================================; ===========================================================DELAY: PUSH ACC ;延迟时间=A*10msMOV A, #20DLY1: PUSH ACCMOV A, #250DJNZ ACC, $ ;500usPOP ACCDJNZ ACC, DLY1POP ACCDJNZ ACC, DELAYRET;======= I2C 子程序 =========================================; I2CD_W, I2CD_R ;LAYER 1; I2C_O, I2C_I ;LAYER 2; I2C_BG, I2C_ED ;LAYER 3;==========================================================; 向存储器写入几个字节,最多8个字节。; 入口:DPTR 要写的EEPROM存储单元地址。; R0 指向要写入字节在RAM的首地址。; B 写入字节个数。; 出口:如果 C=1,说明写出错。I2CD_W: ACALL I2C_BGMOV A, #10100000B ;写命令ACALL I2C_OJC I2CD_WE ;C=1, 未收到 ACK 位,出错,不再继续处理,直接返回MOV A, DPHACALL I2C_OJC I2CD_WEMOV A, DPLACALL I2C_OJC I2CD_WEI2CD_WL:MOV A, @R0ACALL I2C_OJC I2CD_WEINC R0DJNZ B, I2CD_WLACALL I2C_EDCLR CRETI2CD_WE:ACALL I2C_EDSETB CRET; ========================================================; 从 EEPROM 读入几个字节; 入口:DPTR 要读的存储单元地址。; R0 指向要读缓冲区在RAM的首地址。; B 读入字节个数。; 出口:读到的内容在缓冲区中,如果 C=1,说明读出错。I2CD_R: ACALL I2C_BGMOV A, #10100000B ;先发送[写]命令ACALL I2C_OJC I2CD_RE ;C=1, 未收到 ACK 位,出错,不再继续处理,直接返回MOV A, DPH ;发送地址低位ACALL I2C_OJC I2CD_REMOV A, DPL ;发送地址低位ACALL I2C_OJC I2CD_REACALL I2C_BGMOV A, #10100001B ;发送读命令ACALL I2C_OJC I2CD_REI2CD_IB:MOV DPL, #08H ;取得一个字节SETB SDAI2CD_IL:SETB SCL ;SCL=1NOPMOV C, SDA ;MCU 采样 SDA,送到 C 中RLC A ;C->ACC.0CLR SCL ;SCL=0DJNZ DPL, I2CD_IL ;得到的一个字节在 ACC 中MOV @R0, AINC R0MOV A, BXRL A, #01HJZ I2CD_GOCLR SDANOPI2CD_GO:SETB SCLNOPCLR SCLDJNZ B, I2CD_IB ;取得不止一个字节ACALL I2C_EDCLR CRETI2CD_RE:ACALL I2C_EDSETB CRET; =================================================================;向 IIC 总线发送一个字节I2C_O: PUSH BMOV B, #08HI2C_OLP:RLC A ;ACC.7 -> CMOV SDA, CSETB SCL ;SCL=1NOPCLR SCL ;SCL=0DJNZ B, I2C_OLPSETB SDA ;准备接收 ACK 位SETB SCL ;SCL=1, [SDA=1]NOPMOV C, SDACLR SCLPOP BRET ;C=1, 未收到 ACK 位,出错, C=0, 收到 ACK 位,正常; =====================================================I2C_BG: SETB SCL ;确保SCL=HIGHCLR SDA ;向 IIC 总线发送开始位NOPCLR SCLRET; =========================================================================================I2C_ED: CLR SDASETB SCLNOPSETB SDA ;向 IIC 总线发送停止位RET; ================================================================;最好显示000-999=1000个,否则容易造成误解,这里显示全部2187个,0-9,A-F,H,L,P,U,Y; ==============================================================FONT: DB 0FDH ;"0"DB 061H ;"1"DB 0DBH ;"2"DB 0F3H ;"3"DB 067H ;"4"DB 0B7H ;"5"DB 0BFH ;"6"DB 0E1H ;"7"DB 0FFH ;"8"DB 0F7H ;"9"DB 0EFH ;"A"DB 03FH ;"B"DB 09DH ;"C"DB 07BH ;"D"DB 09FH ;"E"DB 08FH ;"F"DB 06FH ;"H"DB 071H ;"J"DB 01DH ;"L"DB 0CFH ;"P"DB 07DH ;"U"DB 077H ;"Y"; ==================================================END
- 基于单片机通用引脚的软件UART设计(10-16)
- 基于ATmega162的智能仪器设计(08-18)
- AT89S51与AT89C2051单片机引脚介绍(12-03)
- 用89C2051控制的简易拨号报警器(12-03)
- 利用2051单片机烧录24C02,04,08,16(11-30)
- AT89C2051单片机超声波测距系统硬件原理(11-30)