这段程序是用在一款七彩灯红外遥控解码程序里,单片机使用PIC12F629,软件模拟三路PWM输出驱动红绿蓝LED分八组共24个LED,实现单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 ;蓝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 return |
|