微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 2051单片机仿PT2272软件解码程序

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top