這段程序是用在一款七彩燈紅外遙控解碼程序里,單片機(jī)使用PIC12F629,軟件模擬三路PWM輸出驅(qū)動(dòng)紅綠藍(lán)LED分八組共24個(gè)LED,實(shí)現(xiàn)單LED漸明漸暗,兩LED一明一暗,七彩等九種花樣.有斷電記憶功能.如下是解碼程序.
;--------------------------------------------------------
;filename: 24LED_Remote.asm
; cpu: PIC12f629
; clock: 4 MHz for INTRC
; date: 2006/02/25
; writer: aLin
; IC type: PT2262IR
; Rosc: 470K
;--------------------------------------------------------
list p=pic12f629
#i nclude"p12f629.inc"
#define B_LED gpio,0 ;綠LED輸出端口
#define G_LED gpio,1 ;藍(lán)LED輸出端口
#define R_LED gpio,2 ;紅LED輸出端口
#define rem gpio,3 ;GP3/MCLR,定義遙控輸入端seg9
;因?yàn)楫?dāng)按住PT2262的按鍵不放的時(shí)候
;PT2262會(huì)把編碼不斷的送出
;設(shè)置ENABLE位用來(lái)檢測(cè)按鍵有沒(méi)有放開過(guò),
;如果沒(méi)有放開則不再響應(yīng)
;用于遙控型
#define enable user_reg,0 ;接收允許位
#define on_off user_reg,1 ;該位為0時(shí),按花樣選擇鍵無(wú)效
#define go_next user_reg,2 ;該位為1時(shí),跳下一段
#define reset user_reg,3 ;該位為1時(shí),關(guān)顯示
#define unlock user_reg,4 ;用于配合on_off位
;---------------------------------------------------------
;定義變量
;
r1 equ 20h ;用于d5ms子程序
r2 equ 21h ;用于d5ms子程序
r3 equ 22h ;用于d320mS子程序
P_reg equ 23h ;正脈寬時(shí)間寄存器
N_reg equ 24h ;負(fù)脈寬時(shí)間寄存器
count1 equ 25h ;計(jì)數(shù)器1
count2 equ 26h ;計(jì)數(shù)器2
W_temp equ 27h ;W臨時(shí)寄存器
user_reg equ 28h ;用戶寄存器
ee_data equ 29h ;eeprom讀寫數(shù)據(jù)出入口
ee_addr equ 2ah ;eeprom讀寫地址入口
data_temp equ 2bh ;用于暫存從EEPROM讀出的數(shù)所數(shù)據(jù)
index_reg equ 2ch ;用于保存引導(dǎo)值
data_reg equ 2dh ;用于保存從EEPROM讀出的值
A0_addr1 equ 30h
A0_addr2 equ 31h
A1_addr1 equ 32h
A1_addr2 equ 33h
r5 equ 34h ;用于解碼延時(shí)
r6 equ 35h ;用于解碼延時(shí)
addr_set1 equ 36h ;用于存儲(chǔ)比較密碼
addr_set2 equ 37h ;用于存儲(chǔ)比較密碼
output equ 38h
count equ 39h ;接收12位編碼
status_temp equ 3ah ;保存status的值,用于現(xiàn)場(chǎng)保護(hù)
ww_temp equ 3bh ;W工作寄存器,用于現(xiàn)場(chǎng)保護(hù)用
A0_data1 equ 3ch ;用于存儲(chǔ)比較數(shù)據(jù)D8
A0_data2 equ 3dh ;用于存儲(chǔ)比較數(shù)據(jù)D8
A1_data1 equ 3eh ;用于存儲(chǔ)比較數(shù)據(jù)D11
A1_data2 equ 3fh ;用于存儲(chǔ)比較數(shù)據(jù)D11
;-------------------------------------------
;定義常數(shù)
;
index equ 00h ;EEData數(shù)據(jù)引導(dǎo)地址
;--------------------------------------------------
org 0000h
call init ;調(diào)用初始化程序
goto main
;--------------------------------------------------
;中斷處理入口
;TMR1溢出中斷,說(shuō)明按鍵松開時(shí)間大于等于65.536mS左右
org 0004h
MOVwf ww_temp ;保護(hù)現(xiàn)場(chǎng)
swapf status,w
MOVwf status_temp
bcf intcon,gie ;關(guān)所有中斷
bcf t1con,tmr1on ;停止TMR1
bcf pir1,tmr1if ;清TMR1中斷標(biāo)志位
bcf enable ;按鍵松開,清e(cuò)nable
swapf status_temp,w
MOVwf status
swapf ww_temp,f
swapf ww_temp,w
return
;--------------------------------------------------
;讀出引導(dǎo)地址單元(00H)內(nèi)容
main
MOVlw index ;送引導(dǎo)地址中轉(zhuǎn)
MOVwf ee_addr
call ee_data_rd ;調(diào)用讀EEPROM程序
MOVf ee_data,w ;讀出引導(dǎo)地址內(nèi)容
MOVwf index_reg ;保存引導(dǎo)地址內(nèi)容
MOVwf ee_addr ;送待讀出內(nèi)容地址
call ee_data_rd
MOVf ee_data,w
MOVwf data_reg ;保存讀出
MOVf data_reg,w
addlw jumper_tab
MOVwf pcl
jumper_tab goto start ;跳到開始0段
goto seg1 ;跳到第1段
goto seg2 ;跳到第2段
goto seg3 ;跳到第3段
goto seg4 ;跳到第4段
goto seg5 ;跳到第5段
goto seg6 ;跳到第6段
goto seg7 ;跳到第7段
goto seg8 ;跳到第8段
;------------------------------------------------
如下略....
;-----------------------------------------------
;
;解碼程序
;
;---------------------------------------------------------
; A0 | A1 | 說(shuō)明
;-----+-----+------------------
; 30H | 32H | 接收的8位地址編碼
;-----+-----+------------------
; 31H | 33H | 接收的4位數(shù)據(jù)編碼
;-----+-----+------------------
; 36H | 37H | 設(shè)定的8位地址密碼
;------------------------------
;
; A0_addr1 equ 30h
; A0_addr2 equ 31h
; A1_addr1 equ 32h
; A1_addr2 equ 33h
;
;其中以30H,0和32H,0為例
;懸空: 30H,0=1,32H,0=0
;1: 30H,0=0,32H,0=0
;0: 30H,0=1,32H,0=1
;38H: 輸出控制
;---------------------------------------------------------
;
;解碼子程序
check_sw btfss rem ;rem為1,無(wú)接收到信號(hào),返回
goto remote0
bcf go_next ;沒(méi)按鍵,清0
bcf reset ;沒(méi)按鍵,清0
bcf unlock
remote_end return ;沒(méi)有按鍵,反回
;--------------------------------------------------------
remote0 btfss enable ;rem為0,但enable為1,按鍵沒(méi)放開,返回
goto incept ;接收12位編碼
;重新設(shè)定TMR1
bcf t1con,tmr1on ;停止TMR1
clrf tmr1h ;ffff為65.536mS
clrf tmr1l
bsf t1con,tmr1on ;重啟動(dòng)TMR1
bcf reset ;按鍵沒(méi)松開,解碼取消,清0
bcf go_next ;按鍵沒(méi)松開,解碼取消,清0
bcf unlock
goto remote_end ;按鍵沒(méi)有放開,返回
;清除上次解碼內(nèi)容
;接收12位編碼
;
incept
MOVlw .12
MOVwf count
;解碼
;先找出接收到的開頭,即16mS左右的高電平
;設(shè)置高電平時(shí)間為15~17mS
;
;檢測(cè)和等待15mS的高電平
;
remote1
MOVlw .30
MOVwf r5
remote2
MOVlw .100
MOVwf r6
remote3 btfss rem
goto remote1
decfsz r6,f
goto remote3
decfsz r5,f
goto remote2
;等待在2mS內(nèi)接收到的低電平
MOVlw .4
MOVwf r5
remote4
MOVlw .100
MOVwf r6
;15mS到17mS內(nèi)接收到下降沿,則跳去解碼,否則返回
remote5 btfss rem
goto remote6
decfsz r6,f
goto remote5
decfsz r5,f
goto remote4
;超出17mS,接收錯(cuò)誤,返回
bcf enable
goto remote_end
;等待1200uS后,采集接收信號(hào)
remote6
MOVlw .200
MOVwf r5
decfsz r5,f
goto $-1
MOVlw .200
MOVwf r5
decfsz r5,f
goto $-1
;采集接收信號(hào),并記錄
btfss rem ;如果rem為1,則c置1,否則清0
clrc
btfsc rem
setc ;rem為1,c置1
rlf A0_addr2,f
rlf A0_addr1,f
;等待第二個(gè)下降沿
;加入了限時(shí)判斷,防止死循環(huán)。
;
; btfss rem ;rem為0,一直執(zhí)行
; goto $-1
MOVlw .255
MOVwf r5
btfsc rem ;rem為0,一直執(zhí)行
goto $+4
decfsz r5,f
goto $-3
goto remote8 ;超時(shí),跳到錯(cuò)誤處理
; btfsc rem ;rem為1,一直執(zhí)行
; goto $-1
MOVlw .255
MOVwf r5
btfss rem ;rem為1,一直執(zhí)行
goto $+4
decfsz r5,f
goto $-3
goto remote8 ;超時(shí),跳到錯(cuò)誤處理
;等待1200uS后采集接收信號(hào)
MOVlw .200
MOVwf r5
decfsz r5,f
goto $-1
MOVlw .200
MOVwf r5
decfsz r5,f
goto $-1
btfss rem ;如果rem為1,則c置1,否則清0
clrc
btfsc rem
setc ;rem為1,c置1
rlf A1_addr2,f
rlf A1_addr1,f
;等待第二個(gè)碼值的下降沿
;加入了限時(shí)判斷,防止死循環(huán)。
;
; btfss rem ;rem為0,一直執(zhí)行
; goto $-1
MOVlw .255
MOVwf r5
btfsc rem ;rem為0,一直執(zhí)行
goto $+4
decfsz r5,f
goto $-3
goto remote8 ;超時(shí),跳到錯(cuò)誤處理
; btfsc rem ;rem為1,一直執(zhí)行
; goto $-1
MOVlw .255
MOVwf r5
btfss rem ;rem為1,一直執(zhí)行
goto $+4
decfsz r5,f
goto $-3
goto remote8 ;超時(shí),跳到錯(cuò)誤處理
decfsz count,f
goto remote6 ;連續(xù)接收12位
goto decode ;接收完12位編碼,跳到解碼
;開始解碼
;把接收的編碼左移4位,將8位密碼放在同一字節(jié)上
decode
MOVlw .4
MOVwf count
remote7 clrc
rlf A0_addr2,f
rlf A0_addr1,f
clrc
rlf A1_addr2,f
rlf A1_addr1,f
decfsz count,f
goto remote7
;把4位數(shù)據(jù)編碼由高4位移到低4位上
swapf A0_addr2,f
swapf A1_addr2,f
;比較密碼
MOVf A0_addr1,w
xorwf addr_set1,w
skpz
goto remote8 ;跳到接收錯(cuò)誤處理
MOVf A1_addr1,w
xorwf addr_set2,w
skpz
goto remote8 ;跳到接收錯(cuò)誤處理
;接收正確處理
;每次按鍵都一次響應(yīng)
;按鍵為PT2262IR pin10(D8) 和 pin13(D11)
;以下只識(shí)別D8、D11,對(duì)數(shù)據(jù)理D9、D10不作處理
;
;懸空: A0=1 , A1=0
; 1: A0=0 , A1=0
; 0: A0=1 , A1=1
;
;檢查鍵值D8,ON/OFF鍵
MOVf A0_addr2,w
andlw 0fh
xorwf A0_data1,w
skpz
goto D11 ;不是只有鍵值D8按下,檢查鍵值D11,
;即D8沒(méi)有按下或D8按下同時(shí)還有其它按鍵按下
MOVf A1_addr2,w
andlw 0fh
xorwf A1_data1,w
skpz
goto D11 ;不是只有鍵值D8按下,檢查鍵值D11
;即D8沒(méi)有按下或D8按下同時(shí)還有其它按鍵按下
;是鍵值D8按下,開始處理
;on/off處理,按下on/off鍵假如on,
;再按下就是off,然后再按下又是off。
MOVlw b'00000010' ;取反user_reg的on_off位
xorwf user_reg,f
btfss on_off ;on_off位為0,reset置1,返回時(shí)關(guān)顯示
goto clr_rst
bsf unlock ;on_off位為1,置unlock為1,返回時(shí)開顯示
goto back
;檢查鍵值D11,NEXT鍵。
D11 btfss on_off ;on_off為0,當(dāng)前已關(guān)顯示,按鍵NEXT無(wú)效
goto back ;返回
MOVf A0_addr2,w
andlw 0fh
xorwf A0_data2,w
skpz
goto back ;也不是只有鍵值D11按下,返回
;即D11沒(méi)有按下或D11按下同時(shí)還有其它按鍵按下
MOVf A1_addr2,w
andlw 0fh
xorwf A1_data2,w
skpz
goto back ;也不是只有鍵值D11按下,返回
;即D11沒(méi)有按下或D11按下同時(shí)還有其它按鍵按下
;是鍵值D11按下,開始處理
bsf go_next ;跳下一段
bcf reset
goto back
clr_rst bsf reset
bcf go_next
goto back
back bcf t1con,tmr1on ;停止TMR1
clrf tmr1h
clrf tmr1l
bsf t1con,tmr1on ;啟動(dòng)TMR1
bsf enable ;置1,防止開關(guān)按住不放,不斷響應(yīng)。
work_end retfie ;返回并開中斷
;接收錯(cuò)誤處理
remote8 bcf enable
bcf go_next ;密碼錯(cuò)誤,取消解碼,清0
bcf reset ;密碼錯(cuò)誤,取消解碼,清0
bcf unlock
bsf enable ;雖接收錯(cuò)誤,但都是有按鍵按下
;重新設(shè)定TMR1
bcf t1con,tmr1on ;停止TMR1
clrf tmr1h ;ffff為65.536mS
clrf tmr1l
bsf t1con,tmr1on ;重啟動(dòng)TMR1
retfie ;返回并開中斷
;-------------------------------------------
;初始化程序
init bsf status,rp0 ;選擇bank1
call 3ffh
MOVwf osccal
MOVlw b'00001000' ;GP0/1/2為輸出
MOVwf trisio ;GP3為輸入
clrf ioc ;關(guān)閉所有電平變化中斷
bsf pie1,tmr1ie ;開TMR1中斷
bcf status,rp0 ;選擇bank0
bcf intcon,gie ;關(guān)所有中斷
bsf intcon,peie ;開外設(shè)中斷
bcf t1con,tmr1on ;停止TMR1
clrf gpio ;輸出清0
MOVlw 07h
MOVwf cmcon ;設(shè)置GP0/1/2為IO
bcf enable ;頭次上電,初始化enable、reset、go_next
bcf reset
bcf go_next
;編碼地址設(shè)定為:A0~A7為懸空(A0=1,A1=0)
MOVlw b'11111111' ;A0
MOVwf addr_set1
MOVlw b'00000000' ;A1
MOVwf addr_set2
;D8設(shè)置1(A0=0,A1=0),D9、D10懸空(A0=1,A1=0)
;D11設(shè)置0(A0=1,A1=1),該狀態(tài)為只有D8按下。D8為ON/OFF鍵。
MOVlw b'00001110' ;A0
MOVwf A0_data1
MOVlw b'00001000' ;A1
MOVwf A1_data1
;D11設(shè)置1(A0=0,A1=0),,D9、D10懸空(A0=1,A1=0)
;D8設(shè)置0(A0=1,A1=1),該狀態(tài)為只有D11按下。D11為NEXT鍵。
MOVlw b'00000111' ;A0
MOVwf A0_data2
MOVlw b'00000001' ;A1
MOVwf A1_data2
return