本帖最后由 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
|