本帖最后由 wyq032 于 2011-3-20 21:56 编辑  
 
这段程序是用在一款七彩灯红外遥控解码程序里,单片机使用PIC12F629,软件模拟三路PWM输出驱动红绿蓝LED分八组共24个LED,实现单LED渐明渐暗,两LED一明一暗,七彩等九种花样.有断电记忆功能.如下是解码程序.    如何改成学习型遥控开关程序?要求一路输出延时10秒自动关断 
 
 ;--------------------------------------------------------  ;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 
;蓝LED输出端口 
  
#define 
R_LED 
gpio,2 
;红LED输出端口 
  
#define 
rem 
gpio,3 
;GP3/MCLR,定义遥控输入端seg9 
                    ;因为当按住PT2262的按键不放的时候  ;PT2262会把编码不断的送出  ;设置ENABLE位用来检测按键有没有放开过,  ;如果没有放开则不再响应            ;用于遥控型             
#define 
enable 
user_reg,0 
;接收允许位  
  
#define 
on_off 
user_reg,1 
;该位为0时,按花样选择键无效 
  
#define 
go_next 
user_reg,2 
;该位为1时,跳下一段 
  
#define 
reset 
user_reg,3 
;该位为1时,关显示   
  
#define 
unlock 
user_reg,4 
;用于配合on_off位 
 ;---------------------------------------------------------  ;定义变量  ;   
r1 
equ 
20h 
;用于d5ms子程序 
  
r2 
equ 
21h 
;用于d5ms子程序 
  
r3 
equ 
22h 
;用于d320mS子程序 
  
P_reg 
equ 
23h 
;正脉宽时间寄存器 
  
N_reg 
equ 
24h 
;负脉宽时间寄存器 
  
count1 
equ 
25h 
;计数器1 
  
count2 
equ 
26h 
;计数器2 
  
 
W_temp 
equ 
27h 
;W临时寄存器 
  
user_reg 
equ 
28h 
;用户寄存器 
  
ee_data 
equ 
29h 
;eeprom读写数据出入口 
  
ee_addr 
equ 
2ah 
;eeprom读写地址入口 
  
data_temp 
equ 
2bh 
;用于暂存从EEPROM读出的数所数据 
  
index_reg 
equ 
2ch 
;用于保存引导值 
  
data_reg 
equ 
2dh 
;用于保存从EEPROM读出的值      
                
A0_addr1 
equ 
30h 
  
A0_addr2 
equ 
31h 
  
A1_addr1 
equ 
32h 
  
A1_addr2 
equ 
33h 
  
r5 
equ 
34h 
;用于解码延时  
  
r6 
equ 
35h 
;用于解码延时  
  
addr_set1 
equ 
36h 
;用于存储比较密码       
  
addr_set2 
equ 
37h 
;用于存储比较密码  
  
output 
equ 
38h 
  
count 
equ 
39h 
;接收12位编码 
 status_temp 
equ 
3ah 
;保存status的值,用于现场保护   
ww_temp 
equ 
3bh 
;W工作寄存器,用于现场保护用 
  
A0_data1 
equ 
3ch 
;用于存储比较数据D8 
  
A0_data2 
equ 
3dh 
;用于存储比较数据D8 
  
A1_data1 
equ 
3eh 
;用于存储比较数据D11 
  
A1_data2 
equ 
3fh 
;用于存储比较数据D11 
 ;-------------------------------------------  ;定义常数  ;   
index 
equ 
00h 
;EEData数据引导地址 
                                ;-------------------------------------------------- 
  
org 0000h 
                
call init 
;调用初始化程序 
  
goto main 
               ;--------------------------------------------------  ;中断处理入口  ;TMR1溢出中断,说明按键松开时间大于等于65.536mS左右   
org 0004h 
  
MOVwf ww_temp 
;保护现场 
  
swapf status,w 
  
MOVwf status_temp 
                
bcf intcon,gie 
;关所有中断 
  
 
bcf t1con,tmr1on 
;停止TMR1 
  
bcf pir1,tmr1if 
;清TMR1中断标志位 
  
bcf enable 
;按键松开,清enable 
                
swapf status_temp,w 
  
MOVwf status 
  
swapf ww_temp,f 
  
swapf ww_temp,w 
  
 
  
return 
 ;-------------------------------------------------- 
 ;读出引导地址单元(00H)内容             
main 
MOVlw index 
;送引导地址中转 
  
MOVwf ee_addr 
                
call ee_data_rd 
;调用读EEPROM程序             
  
MOVf ee_data,w 
;读出引导地址内容 
                
MOVwf index_reg 
;保存引导地址内容 
  
MOVwf ee_addr 
;送待读出内容地址 
                
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 
| 说明                ;-----+-----+------------------  ; 30H | 32H | 接收的8位地址编码   ;-----+-----+------------------  ; 31H | 33H | 接收的4位数据编码  ;-----+-----+------------------  ; 36H | 37H | 设定的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,无接收到信号,返回 
  
goto 
remote0 
  
bcf 
go_next 
;没按键,清0 
  
bcf 
reset 
;没按键,清0 
  
bcf 
unlock 
                                remote_end 
return 
;没有按键,反回  ;--------------------------------------------------------          
remote0 
btfss enable 
;rem为0,但enable为1,按键没放开,返回  
  
goto 
incept 
;接收12位编码 
               ;重新设定TMR1 
  
bcf t1con,tmr1on 
;停止TMR1 
  
clrf tmr1h 
;ffff为65.536mS 
  
clrf tmr1l 
  
bsf t1con,tmr1on 
;重启动TMR1 
                
bcf reset 
;按键没松开,解码取消,清0 
  
bcf go_next 
;按键没松开,解码取消,清0 
  
bcf unlock 
                
goto remote_end 
;按键没有放开,返回 
 ;清除上次解码内容  ;接收12位编码  ;   
incept 
MOVlw .12 
  
MOVwf count 
 ;解码  ;先找出接收到的开头,即16mS左右的高电平  ;设置高电平时间为15~17mS  ;  ;检测和等待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内接收到的低电平   
MOVlw .4  
  
MOVwf r5 
  
remote4 
MOVlw .100 
  
MOVwf r6 
                    ;15mS到17mS内接收到下降沿,则跳去解码,否则返回   
remote5 
btfss rem 
  
goto remote6 
  
decfsz r6,f 
  
goto remote5 
  
decfsz r5,f 
  
 
goto remote4 
 ;超出17mS,接收错误,返回   
bcf enable 
  
goto remote_end 
                   ;等待1200uS后,采集接收信号   
remote6 
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 A0_addr2,f 
  
rlf A0_addr1,f 
                ;等待第二个下降沿  ;加入了限时判断,防止死循环。  ;  ; 
btfss rem 
;rem为0,一直执行  ; 
goto $-1   
MOVlw .255 
  
MOVwf r5 
  
btfsc rem 
;rem为0,一直执行 
  
goto $+4 
  
 
decfsz r5,f 
  
goto $-3 
  
goto remote8 
;超时,跳到错误处理 
                                  ; 
btfsc rem 
;rem为1,一直执行   ; 
goto $-1   
MOVlw .255 
  
MOVwf r5 
  
btfss rem 
 
;rem为1,一直执行  
  
goto $+4 
  
decfsz r5,f 
  
goto $-3 
  
goto remote8 
;超时,跳到错误处理  
                             ;等待1200uS后采集接收信号                                 
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 
    ;等待第二个码值的下降沿  ;加入了限时判断,防止死循环。  ;  ; 
btfss rem 
;rem为0,一直执行  ; 
goto $-1   
MOVlw .255 
  
MOVwf r5 
  
btfsc rem 
;rem为0,一直执行 
  
goto $+4 
  
decfsz r5,f 
  
goto $-3 
  
goto remote8 
;超时,跳到错误处理 
                                  ; 
btfsc rem 
;rem为1,一直执行   ; 
goto $-1   
MOVlw .255 
  
MOVwf r5 
  
btfss rem 
;rem为1,一直执行  
  
goto $+4 
  
decfsz r5,f 
  
goto $-3 
  
goto remote8 
;超时,跳到错误处理  
                                   
decfsz count,f 
  
goto remote6 
;连续接收12位 
  
goto decode 
;接收完12位编码,跳到解码  
 ;开始解码  ;把接收的编码左移4位,将8位密码放在同一字节上   
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位数据编码由高4位移到低4位上   
swapf A0_addr2,f 
  
swapf A1_addr2,f 
                    ;比较密码 
 
  
MOVf A0_addr1,w 
  
xorwf addr_set1,w 
  
skpz 
  
goto remote8 
;跳到接收错误处理  
                     
MOVf A1_addr1,w 
  
xorwf addr_set2,w 
  
skpz 
  
 
goto remote8 
;跳到接收错误处理 
 ;接收正确处理                                     ;每次按键都一次响应  ;按键为PT2262IR pin10(D8) 和 pin13(D11)  ;以下只识别D8、D11,对数据理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没有按下或D8按下同时还有其它按键按下 
  
MOVf A1_addr2,w 
  
andlw 0fh 
  
xorwf A1_data1,w 
  
skpz 
  
goto D11 
;不是只有键值D8按下,检查键值D11 
  
;即D8没有按下或D8按下同时还有其它按键按下 
 ;是键值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,返回时关显示 
  
goto clr_rst 
  
bsf unlock 
;on_off位为1,置unlock为1,返回时开显示 
  
goto back 
    ;检查键值D11,NEXT键。     
D11 
btfss on_off 
;on_off为0,当前已关显示,按键NEXT无效 
  
goto back 
;返回 
                        
MOVf A0_addr2,w 
  
andlw 0fh 
  
xorwf A0_data2,w 
  
skpz 
  
goto back 
;也不是只有键值D11按下,返回 
  
;即D11没有按下或D11按下同时还有其它按键按下 
  
MOVf A1_addr2,w 
  
andlw 0fh 
  
xorwf A1_data2,w 
  
skpz 
  
goto back 
;也不是只有键值D11按下,返回 
  
;即D11没有按下或D11按下同时还有其它按键按下 
               ;是键值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 
;启动TMR1 
  
bsf enable 
;置1,防止开关按住不放,不断响应。 
  
 
  
work_end 
retfie 
;返回并开中断 
               ;接收错误处理                    
remote8 
bcf enable 
                
bcf go_next 
;密码错误,取消解码,清0 
  
bcf reset 
;密码错误,取消解码,清0 
  
bcf unlock 
  
 
  
bsf enable 
;虽接收错误,但都是有按键按下 
               ;重新设定TMR1 
  
bcf t1con,tmr1on 
;停止TMR1 
  
clrf tmr1h 
;ffff为65.536mS 
  
clrf tmr1l 
  
bsf t1con,tmr1on 
;重启动TMR1 
  
retfie 
 
;返回并开中断             
                                                         ;-------------------------------------------  ;初始化程序   
init 
bsf status,rp0 
;选择bank1 
  
call 3ffh 
  
MOVwf osccal 
  
MOVlw b’00001000’ 
;GP0/1/2为输出 
  
MOVwf trisio 
;GP3为输入  
  
clrf ioc 
;关闭所有电平变化中断 
  
bsf pie1,tmr1ie 
;开TMR1中断 
                
bcf status,rp0 
;选择bank0 
  
bcf intcon,gie 
;关所有中断 
  
bsf intcon,peie 
;开外设中断  
  
bcf t1con,tmr1on 
;停止TMR1 
                
clrf gpio 
;输出清0 
  
MOVlw 07h 
  
MOVwf cmcon 
;设置GP0/1/2为IO 
                
bcf enable 
;头次上电,初始化enable、reset、go_next 
  
bcf reset 
  
bcf go_next 
               ;编码地址设定为:A0~A7为悬空(A0=1,A1=0) 
  
MOVlw b’11111111’ 
;A0 
  
MOVwf addr_set1 
  
MOVlw b’00000000’ 
;A1 
  
MOVwf addr_set2 
               ;D8设置1(A0=0,A1=0),D9、D10悬空(A0=1,A1=0)  ;D11设置0(A0=1,A1=1),该状态为只有D8按下。D8为ON/OFF键。   
MOVlw b’00001110’ 
;A0 
  
MOVwf A0_data1 
  
MOVlw b’00001000’ 
;A1 
  
MOVwf A1_data1 
               ;D11设置1(A0=0,A1=0),,D9、D10悬空(A0=1,A1=0)  ;D8设置0(A0=1,A1=1),该状态为只有D11按下。D11为NEXT键。   
MOVlw b’00000111’ 
;A0 
  
MOVwf A0_data2 
  
MOVlw b’00000001’ 
;A1 
  
MOVwf A1_data2
  |