本程序是用51單片機來軟件解碼pt2262編碼,是一個無線服務呼叫器的代碼已經成功的在產品的應用,有LED顯示.
并有原理圖與pcb文件以及完整的代碼提供下載:
http://www.raoushi.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.1
SIGPIN 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 ;蜂鳴器運行期間=1
EEEMPTY BIT 79H ;EEPROM空標志
BELLON BIT 7AH ;通知蜂鳴器鳴響
CODEOK BIT 7BH ;收到的編碼正確
TMK250 BIT 7CH ;250us標志,每250us置位一次
SIGING BIT 7DH ;手機發射信號正在持續=1,無信號=0
LEDHIGH BIT 7EH ;顯示器亮度標志=0:正常;=1:高亮
TOUTMK BIT 7FH ;顯示器降低亮度時間已到=1
RBUF81 DATA 20H ;后8位第一次采樣結果A4-A11
RBUF82 DATA 21H ;后8位第二次采樣結果A4-A11
RBUF44 DATA 22H ;前4位第12次采樣結果A0-A3
SIGPOT DATA 23H ;接收引腳上次電平,直接保存P3口全部內容
SIGMSK EQU 04H ;SIG----P3.2
TCNTL DATA 24H ;定時計數器(4ms時基)
TCNTH DATA 25H
TMX16 DATA 26H ;16*250=4000us=4ms
BELLTM DATA 27H ;鳴響時間
DBUF0 DATA 28H ;個位顯示緩沖區
DBUF1 DATA 29H ;十位
DBUF2 DATA 2AH ;百位
EEPTRL DATA 2BH ;EEPROM當前位置指針
EEPTRH DATA 2CH
EEPOL DATA 2DH ;保存清除指針
EEPOH DATA 2EH ;
RES2F DATA 2FH ;使用其中的標志位
EEBUF DATA 30H ;30-37H, I2C緩沖區
BELLCNT DATA 38H ;鳴響次數計數器(3/2/1)
BELLTMK DATA 39H
CODEL DATA 40H ;接收到編碼低位
CODEH DATA 41H ; 高位
CODELK DATA 42H ;保存上一個編碼
CODEHK DATA 43H ;
CODE1L DATA 44H
CODE1H DATA 45H
; =========================================================================================
; =========================================================================================
ORG 0000H
LJMP START
; =========================================================================================
; 250us進入一次,每16次(4ms)切換一次顯示位
; =========================================================================================
ORG 000BH ;定時器0中斷入口,獨占 R7
TM0SUB: SETB TMK250
TM0_4MS:DJNZ TMX16, TM0_E
MOV TMX16, #10H
JNB BELLSW, TM0_CLY
DJNZ BELLTM, TM0_CLY
SETB BELLON
TM0_CLY:JB TOUTMK, TM0_0 ;每4ms執行一次
DJNZ TCNTL, TM0_0
DJNZ TCNTH, TM0_0
SETB TOUTMK
TM0_0: CJNE R7, #0, TM0_1 ;當前顯示位
CLR U2E
MOV P1, DBUF0
INC R7
SETB U0E
RETI
TM0_1: CJNE R7, #1, TM0_2
CLR U0E
MOV P1, DBUF1
INC R7
SETB U1E
RETI
TM0_2: CLR U1E
MOV P1, DBUF2
MOV R7, #0
SETB U2E
RETI
TM0_E: RETI
; =========================================================================================
; =========================================================================================
START: MOV P1, #00H ;關閉顯示器,正常亮度
CLR BELLON
CLR BELL
ACALL EECHK ;檢查EEPROM,確定指針,提取其中最后一個歷史記錄號碼
ACALL TOBUF
MOV TMX16, #10H ;中斷計數寄存器置初始值16
SETB TOUTMK ;延遲定時器處于停止狀態
CLR U0E
CLR U1E
CLR U2E
MOV R7, #00H ;從第一位開始顯示
MOV TMOD, #12H ;TIMER0, MODE 2, TIMER1, MODE 1
MOV TL0, #06H
MOV TH0, #06H ;時間=250us
SETB TR0
SETB ET0
SETB EA
MOV A, #6-1 ;開機時蜂鳴器自動鳴響
ACALL BELL_S
MOV BELLTM, #BELONT-20
ACALL LEDOFF
CLR LEDHIGH ;關閉高亮度
MOV SIGPOT, #00H ;假設開始時接收引腳=0
CLR SIGING
SETB F0
;=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
MAIN: JNB BELLSW, MAIN_S0
ACALL BELL_M
MAIN_S0:JNB LEDHIGH, MAIN_00 ;顯示器普通亮度,不檢查標志
JNB TOUTMK, MAIN_0
ACALL LEDOFF ;顯示器回到正常亮度
CLR LEDHIGH
JB EEEMPTY, MAIN_0 ;沒有尚未確認的編碼
AJMP MAIN_01
MAIN_00:JB EEEMPTY, MAIN_0 ;沒有尚未確認的編碼
JNB TOUTMK, MAIN_0
MOV A, #2-1
ACALL BELL_S ;鳴響
MAIN_01:MOV TCNTL, #LOW(5000/4) ;高亮度持續3000ms=3s后恢復
MOV TCNTH, #HIGH(5000/4)
CLR TOUTMK
MOV BELLTM, #30
MAIN_0: MOV A, P3 ;監視SIG引腳電平變化
XCH A, SIGPOT
XRL A, SIGPOT
ANL A, #SIGMSK
JZ MAIN ;A=0表示引腳電平無變化
SETB F0
ACALL GETCOD ;開始接收,出錯后直接返回
JC MAIN ;接收代碼無效,舍棄。
ACALL FIND
JC MAIN ;C=1,表示代碼無效,什么也不發生
MOV CODE1L, CODEL
MOV CODE1H, CODEH
CLR F0
ACALL GETCOD ;開始接收,出錯后直接返回
SETB F0
JC MAIN ;接收代碼無效,舍棄。
ACALL FIND
JC MAIN ;C=1,表示代碼無效,什么也不發生
MOV B, A
MOV A, CODE1L
XRL A, CODEL
JNZ MAIN_0D
MOV A, CODE1H
XRL A, CODEH
JZ MAIN_0C
MAIN_0D:MOV CODE1L, CODEL
MOV CODE1H, CODEH
CLR F0
ACALL GETCOD ;開始接收,出錯后直接返回
SETB F0
JC MAIN ;接收代碼無效,舍棄。
ACALL FIND
JC MAIN ;C=1,表示代碼無效,什么也不發生
MOV B, A
MOV A, CODE1L
XRL A, CODEL
JNZ MAIN_E
MOV A, CODE1H
XRL A, CODEH
JNZ MAIN_E
MAIN_0C:MOV A, B
JNZ MAIN_1 ;A=1:主控手機,轉去退棧
MOV BELLCNT, #4-1
MOV A, CODEL
XRL A, CODELK
JNZ MAIN_0A
MOV A, CODEH
XRL A, CODEHK
JZ MAIN_0B
;這里可以進行編碼過濾=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
MAIN_0A:MOV BELLCNT, #6-1
ACALL EEPUSH ;其他手機,轉去保存、顯示
ACALL TOBUF
MAIN_0B:SETB TOUTMK
MOV TCNTL, #LOW(3000/4) ;高亮度持續3000ms=3s后恢復
MOV TCNTH, #HIGH(3000/4)
CLR TOUTMK
SETB LEDHIGH ;顯示器進入高亮狀態
MOV A, BELLCNT
ACALL BELL_S ;鳴響
MOV BELLTM, #BELONT
AJMP MAIN
MAIN_1: MOV A, CODEL ;核對手機號碼
XRL A, #MYCLRL
JNZ MAIN_E
MOV A, CODEH
XRL A, #MYCLRH
JNZ MAIN_E
ACALL EEPOP ;執行退棧操作
MAIN_E: AJMP MAIN
; =========================================================================================
; 主程序結束
; =========================================================================================
BELL_S: MOV BELLCNT, A
SETB BELLSW
SETB BELL
RET
; =========================================================================================
BELL_M: JBC BELLON, BELLM
RET
BELLM: MOV A, BELLCNT
BELLM0: JNB ACC.0, BELLM1
MOV BELLTM, #BELOFT ;A.0=1,正在鳴響,應該關閉
CLR BELL
AJMP BELLM9
BELLM1: MOV BELLTM, #BELONT ;靜音狀態,應該打開
SETB BELL
BELLM9: DJNZ BELLCNT, BELLME
CLR BELLSW
CLR BELL
BELLME: RET
; =========================================================================================
LEDOFF: ANL DBUF0, #0FEH
ANL DBUF1, #0FEH
ANL DBUF2, #0FEH
RET
; =========================================================================================
; =========================================================================================
TM1SET: CLR TR1 ;1,ACALL=2
CLR TF1 ;1
MOV TL1, DPL ;2
MOV TH1, DPH ;2
SETB TR1 ;1
RET ;2, TOTAL=2+1+1+2+2+1+2=11us
; =========================================================================================
; 接收代碼,收到兩個相同的編碼即認可。
; 發射結束后接收下一個。
; =========================================================================================
GETCOD: NOP
GETC_S: MOV DPTR, #65535-50000 ;在50ms內搜索至少持續4ms的低電平 [***]
ACALL TM1SET
GETC_S0:MOV R6, #16 ;16*250us=4000us=4ms
GETC_S1:CLR TMK250
GETC_S2:JB TF1, GETC_E ;這里超時認為目前無發射器工作,或上次發射已結束。
JB SIGPIN, GETC_S0
JNB TMK250, GETC_S2
DJNZ R6, GETC_S1
MOV R5, #4*2 ;首先接收A0-A3,共4位,8個采樣點
MOV DPTR, #65535-8000 ;在接下來的8ms內必須出現上升沿 [***]
ACALL TM1SET
GETC_0: JB TF1, GETC_E ;這里超時認為目前無發射器工作,或上次發射已結束。
JNB SIGPIN, GETC_0
; JB SIGING, GETC_F ;上次發射尚未結束,直接返回,不接收編碼。
; AJMP GETC_20
JNB SIGING, GETC_20 ;上次發射尚未結束,直接返回,不接收編碼。
JNB F0, GETC_20
AJMP GETC_F
GETC_1P:MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現低電平 [***]
ACALL TM1SET
GETC_1: JB TF1, GETC_F ;超時
JB SIGPIN, GETC_1
MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現上升沿 [***]
ACALL TM1SET
GETC_2: JB TF1, GETC_F ;超時
JNB SIGPIN, GETC_2
GETC_20:MOV DPTR, #65535-500+11+2 ;固定延遲500us后采樣
ACALL TM1SET
JNB TF1, $
MOV C, SIGPIN ;采樣接收信號
MOV A, RBUF44
RLC A
MOV RBUF44, A
DJNZ 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 TM1SET
GETC_3: JB TF1, GETC_F ;超時
JB SIGPIN, GETC_3
MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現上升沿 [***]
ACALL TM1SET
GETC_4: JB TF1, GETC_F ;超時
JNB SIGPIN, GETC_4
GETC_40:MOV DPTR, #65535-500+11+2 ;固定延遲500us后采樣
ACALL TM1SET
JNB TF1, $
MOV C, SIGPIN ;采樣接收信號
MOV A, @R0
RLC A
MOV @R0, A
XRL 00H, #RBUF81 ;在RBUF81和RBUF82之間切換
XRL 00H, #RBUF82
DJNZ R5, GETC_3P ;循環接收8個數據位,進行16次采樣
SETB SIGING
CLR C
RET
GETC_E: CLR SIGING
GETC_F: SETB C
RET
; =========================================================================================
; =========================================================================================
FIND: MOV A, RBUF44 ;分析代碼
CJNE A, #MYA0_3, FIND_E
MOV R4, RBUF81
MOV R5, RBUF82
MOV R6, #7
MOV R0, #00H
MOV R1, #00H
FIND_L: MOV A, R0 ;結果乘以 3
CLR C
RLC A
MOV B, A
MOV A, R1
RLC A
XCH A, B
ADD A, R0
MOV R0, A
MOV A, B
ADDC A, R1
MOV R1, A ;結果乘以 3 結束
MOV A, R4
RLC A
MOV R4, A ;D7-->C
MOV A, R5
RL A
MOV R5, A
ANL A, #01H ;D7-->A.0
ADDC A, R0 ;A.0+C+R0
MOV R0, A
MOV A, R1
ADDC A, #00H
MOV R1, A
DJNZ R6, FIND_L ;確定A4-A10的編碼結果
CLR A
MOV C, RBUF81.0 ;分析代碼,確定是否主控手機
MOV ACC.0, C
MOV C, RBUF82.0
ADDC A, #00H ;A=(0,1,2)。A=0:非主控手機;A=1:主控手機;A=2:無效手機
JB ACC.1, FIND_E ;A=2!
MOV CODEL, R0
MOV CODEH, R1
CLR C
RET ;A=0/1
FIND_E: SETB C
RET
; =========================================================================================
; =========================================================================================
EECHK: MOV EEPTRL, #00H ;0000H記錄不用,因為0000H用于判斷EEPROM是否空
MOV EEPTRH, #00H
MOV EEBUF, #00H
MOV EEBUF+1, #00H
EECHK0: MOV CODEL, EEBUF ;放到編碼緩沖區
MOV CODEH, EEBUF+1
ANL CODEH, #0FH
MOV DPL, EEPTRL ;讀取棧底的兩個字節
MOV DPH, EEPTRH
INC DPTR
INC DPTR ;指向下一個記錄,但是暫時不修改指針
MOV A, DPH
ADD A, #HIGH(65536-EESIZE) ;???
JC EECHK9 ;已經檢查完所有記錄空間。
MOV EEPOL, DPL
MOV EEPOH, DPH ;暫時保存在這里
MOV R0, #EEBUF
MOV B, #02H
ACALL I2CD_R
MOV A, EEBUF+1
ANL A, #0F0H
XRL A, #PWDF
JNZ EECHK9
MOV EEPTRL, EEPOL
MOV EEPTRH, EEPOH
AJMP EECHK0
EECHK9: CLR EEEMPTY ;假設非空
MOV A, EEPTRL
ORL A, EEPTRH
JNZ EECHKE
SETB EEEMPTY ;聲明EEPROM空
EECHKE: RET
; =========================================================================================
; =========================================================================================
EEPUSH: MOV EEBUF, CODEL ;寫入EEPROM棧,采用實棧頂
MOV EEBUF+1, CODEH
ORL EEBUF+1, #PWDF ;標志,50H
MOV DPL, EEPTRL
MOV DPH, EEPTRH
INC DPTR ;每個記錄進入,指針加 2
INC DPTR
MOV A, DPH ;進行堆棧溢出檢查
ADD A, #HIGH(65536-EESIZE)
JC EEPUSHE
ANL DPL, #0FEH
MOV EEPTRL, DPL
MOV EEPTRH, DPH
MOV R0, #EEBUF
MOV B, #02H
ACALL I2CD_W
CLR EEEMPTY ;聲明EEPROM非空
EEPUSHE:RET
; =========================================================================================
; =========================================================================================
EEPOP: MOV A, EEPTRL ;EEPROM退出操作
ORL A, EEPTRH
JZ EEPOPB
EEPOP0: MOV EEPOL, EEPTRL
MOV EEPOH, EEPTRH
CLR C ;指針減 2,指向上一個數據
MOV A, EEPTRL
SUBB A, #02H
MOV EEPTRL, A
MOV A, EEPTRH
SUBB A, #00H
MOV EEPTRH, A ;指針已經更新
MOV A, EEPTRL ;檢查退出一個記錄后,堆棧是否變空?
ORL A, EEPTRH
JNZ EEPOP1
MOV CODEL, A
MOV CODEH, A
SETB EEEMPTY ;聲明EEPROM空
AJMP EEPOP9
EEPOP1: MOV DPL, EEPTRL ;讀取棧頂記錄
MOV DPH, EEPTRH
MOV R0, #EEBUF
MOV B, #02H
ACALL I2CD_R
MOV CODEL, EEBUF ;放到編碼緩沖區
MOV CODEH, EEBUF+1
ANL CODEH, #0FH ;屏蔽掉標志
EEPOP9: MOV EEBUF, #00H ;清除剛才已經退棧的記錄
MOV EEBUF+1, #00H
MOV DPL, EEPOL
MOV DPH, EEPOH
MOV R0, #EEBUF
MOV B, #02H
ACALL I2CD_W
ACALL TOBUF ;送到顯示緩沖區
ACALL LEDOFF
EEPOPB: MOV A, #2-1
ACALL BELL_S ;鳴響
; MOV BELLTM, #30
EEPOPE: RET
; =========================================================================================
; =========================================================================================
TOBUF: MOV A, CODEL ;填寫顯示緩沖區
MOV B, CODEH ;/100
MOV R2, #00H
TOBUF_0:CLR C
SUBB A, #100
XCH A, B
SUBB A, #00H
XCH A, B
JC TOBUF_8
INC R2
AJMP TOBUF_0
TOBUF_8:ADD A, #100
MOV B, #10
DIV AB
MOV DPTR, #FONT
MOVC A, @A+DPTR
MOV DBUF1, A
MOV A, B
MOVC A, @A+DPTR
MOV DBUF0, A
MOV A, R2
MOVC A, @A+DPTR
MOV DBUF2, A
MOV CODELK, CODEL
MOV CODEHK, CODEH
RET
; =========================================================================================
; =========================================================================================
DELAY: PUSH ACC ;延遲時間=A*10ms
MOV A, #20
DLY1: PUSH ACC
MOV A, #250
DJNZ ACC, $ ;500us
POP ACC
DJNZ ACC, DLY1
POP ACC
DJNZ ACC, DELAY
RET
;======= 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_BG
MOV A, #10100000B ;寫命令
ACALL I2C_O
JC I2CD_WE ;C=1, 未收到 ACK 位,出錯,不再繼續處理,直接返回
MOV A, DPH
ACALL I2C_O
JC I2CD_WE
MOV A, DPL
ACALL I2C_O
JC I2CD_WE
I2CD_WL:MOV A, @R0
ACALL I2C_O
JC I2CD_WE
INC R0
DJNZ B, I2CD_WL
ACALL I2C_ED
CLR C
RET
I2CD_WE:ACALL I2C_ED
SETB C
RET
; =========================================================================================
; 從 EEPROM 讀入幾個字節
; 入口:DPTR 要讀的存儲單元地址。
; R0 指向要讀緩沖區在RAM的首地址。
; B 讀入字節個數。
; 出口:讀到的內容在緩沖區中,如果 C=1,說明讀出錯。
I2CD_R: ACALL I2C_BG
MOV A, #10100000B ;先發送[寫]命令
ACALL I2C_O
JC I2CD_RE ;C=1, 未收到 ACK 位,出錯,不再繼續處理,直接返回
MOV A, DPH ;發送地址低位
ACALL I2C_O
JC I2CD_RE
MOV A, DPL ;發送地址低位
ACALL I2C_O
JC I2CD_RE
ACALL I2C_BG
MOV A, #10100001B ;發送讀命令
ACALL I2C_O
JC I2CD_RE
I2CD_IB:MOV DPL, #08H ;取得一個字節
SETB SDA
I2CD_IL:SETB SCL ;SCL=1
NOP
MOV C, SDA ;MCU 采樣 SDA,送到 C 中
RLC A ;C->ACC.0
CLR SCL ;SCL=0
DJNZ DPL, I2CD_IL ;得到的一個字節在 ACC 中
MOV @R0, A
INC R0
MOV A, B
XRL A, #01H
JZ I2CD_GO
CLR SDA
NOP
I2CD_GO:SETB SCL
NOP
CLR SCL
DJNZ B, I2CD_IB ;取得不止一個字節
ACALL I2C_ED
CLR C
RET
I2CD_RE:ACALL I2C_ED
SETB C
RET
; =========================================================================================
;向 IIC 總線發送一個字節
I2C_O: PUSH B
MOV B, #08H
I2C_OLP:RLC A ;ACC.7 -> C
MOV SDA, C
SETB SCL ;SCL=1
NOP
CLR SCL ;SCL=0
DJNZ B, I2C_OLP
SETB SDA ;準備接收 ACK 位
SETB SCL ;SCL=1, [SDA=1]
NOP
MOV C, SDA
CLR SCL
POP B
RET ;C=1, 未收到 ACK 位,出錯, C=0, 收到 ACK 位,正常
; =========================================================================================
I2C_BG: SETB SCL ;確保SCL=HIGH
CLR SDA ;向 IIC 總線發送開始位
NOP
CLR SCL
RET
; =========================================================================================
I2C_ED: CLR SDA
SETB SCL
NOP
SETB 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
