;**********************************************************************
; A026 SOURCE CODE *
;**********************************************************************
list p=12F508
#include <p12F508.inc>
__CONFIG _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC
;------------------------------------------------------
tus EQU 0x07 ;250uS record
tms EQU tus+1 ;40timer counter(250uSx40=10ms)
tmsl EQU tms+1 ;
tmsh EQU tmsl+1 ;4000timer counter(250uSx4000=1000mS)
ts EQU tmsh+1 ;
sf EQU ts+1 ;status flag
;b'00000000'两分钟低速
;b'00000001'一分钟低速
;b'00000010'两分钟高速
;b'00000011'一分钟高低速
;b'00000100'关机
tb EQU sf+1 ;timer0 backup
mf EQU tb+1 ;motor flag
kf EQU mf+1 ;key flag
kv EQU kf+1 ;key value
;**********************************************************************
org 0x000 ; coding begins here
movwf OSCCAL ; update register with factory cal value
;--------------------------------------------------
start
btfsc STATUS,7 ;check if io wake up
goto wkup ;yes, do wkup program
;--------------------------------------------------
power_on
nop ;no, do the next program
nop
movlw b'00001111' ;电平唤醒ON,弱上拉ON(只对输入口有效),内部指令周期,
;上升沿触发,预分频器分配给watchdog,watchdog分频
;比1:128,此时定时器分频比为1:1。
option ;开电平唤醒及配置看门狗和定时器!是否启用看门狗
;由__CONFIG或编程器配置位决定。
movlw b'00000000'
movwf GPIO ;off motor,off led
movlw b'11111001' ;gp1,gp2置为输出状态,其它保持与复位后一样的状态
;(高阻输入状态)(包括gp0为key输入状态),
;gp3永远是输入状态,gp2有可能由OPTION设置为输入状
;态(T0CKI),而不理会TRIS中设置的内容
tris GPIO ;写IO输入输出控制器
;--------------------------------------------------
movlw 0x07
movwf FSR
clram
clrf INDF
incf FSR,f ;FSR是一个5位宽寄存器,FSR<7:5>未实现,读取值为1。
movlw 0xff ;上电复位值是111xxxxx.
xorwf FSR,w
btfss STATUS,Z
goto clram ;
;--------------------------------------------------
movf GPIO,w ;在进入休眠模式之前,读取输入引脚(全为1,上拉电平)。
;当器件处于休眠模式时,引脚上的值不同于上次读该引
;脚时的状态时,就会发生唤醒。 如果发生电平变化时
;唤醒,并且没有在进入休眠模式前读引脚,即使在休眠
;模式中没有引脚发生变化,也会立即发生唤醒。
sleep
nop
;**********************************************************************
wkup
nop
nop ;wake up
movlw b'10001111' ;
option ;关电平唤醒!
settmr0
movlw b'11111001' ;gp1,gp2置为输出状态,其它保持与复位后一样的状态
;(高阻输入状态)(包括gp0为key输入状态),
;gp3永远是输入状态,gp2有可能由OPTION设置为输入状
;态(T0CKI),而不理会TRIS中设置的内容
tris GPIO ;写IO输入输出控制器
movlw .8 ;(T填充值=256-T溢出值+2)
movwf TMR0 ;timer0 restart ,basic on (256-8)uS,is (248+2)uS.
;--------------------------------------------------
movlw b'00000110'
movwf GPIO ;turn on the motor and led
clrf sf ;标识默认状态,为两分钟低速动作
bsf mf,0 ;标识电机动作乒乓状态
clrf kf
;**********************************************************************
chk_tm
movf TMR0,w ;读取TMR0时间
subwf tb,f ;得到C标志位信息
movwf tb ;将W值(即TMR0值)保存起来
btfss STATUS,C ;(tb-TMR0)>0,即C为1(无借位)时转去执行“溢出处理”
goto chk_tm ;(tb-TMR0)<0,即C为0(有借位)时转去执行“没有溢出”
movlw .8 ;保持250uS溢出率(T填充值=256-T溢出值+2)
addwf TMR0,f ;确保时间精度
;-----------------
;250uS时间到
;-----------------
movlw b'00000000' ;两分钟低速状态标识码
xorwf sf,w ;得到标志位
btfsc STATUS,Z ;是否是两分钟低速状态?
goto L2 ;执行两分钟低速状态
;--------------------------------------------------
movlw b'00000001' ;一分钟低速状态标识码
xorwf sf,w ;得到标志位
btfsc STATUS,Z ;是否是一两分钟低速状态?
goto L1 ;执行一分钟低速状态
;--------------------------------------------------
movlw b'00000010' ;两分钟高速状态标识码
xorwf sf,w ;得到标志位
btfsc STATUS,Z ;是否是两分钟高速状态?
goto H2 ;执行两分钟高速状态
;--------------------------------------------------
movlw b'00000011' ;一分钟高速状态标识码
xorwf sf,w ;得到标志位
btfsc STATUS,Z ;是否是一分钟高速状态?
goto H1 ;执行一分钟高速状态
;--------------------------------------------------
goto enter_slp ;进入睡眠状态
;**********************************************************************
L2
incf mf,f
btfss mf,0 ;监视mf电机标志位bit0的乒乓状态,每两次250uS后改变GP2输出状态
goto $+3
movlw b'00000100'
xorwf GPIO,f ;取反GP2,
;--------------------------------------------------
call chk_key
movlw b'00000010'
xorwf kf,w
btfss STATUS,Z
goto t1sL2
clrf tms
clrf tmsl
clrf tmsh
clrf ts
clrf kf
movlw b'00000010'
movwf sf ;标识下一步进入两分钟高速状态
goto H2
;-----------------------------------------------------------------
t1sL2
incf tmsl,f ;1秒钟计数(4000次)
btfsc STATUS,C ;低位运算是否有进位?
incf tmsh,f ;有,高位加1
;-----------------------------------------------------------------
movlw 0x0f ;4000次计数比对,d'4000'=h'fa0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto chk_tm ;不同,放弃比对
movlw 0xa0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行1秒钟时间到动作
goto chk_tm ;不同,放弃比对
;-----------------------------------------------------------------
incf ts,f ;秒计数器累加
clrf tmsl ;清4000次计数器低位
clrf tmsh ;清4000次计数器高位
;-----------------------------------------------------------------
movlw .120 ;准备比对时间
xorwf ts,w ;比对时间是否到120S
btfss STATUS,Z ;skpz
goto chk_tm ;没到,放弃比对
clrf tms ;120S(2分钟)到,清10ms计数器
clrf tmsl ;120S(2分钟)到,清4000次计数器低位
clrf tmsh ;120S(2分钟)到,清4000次计数器高位
clrf ts ;120S(2分钟)到,清秒计数器
clrf kf ;120S(2分钟)到,清按键标识码
movlw b'00000001' ;准备修改为一分钟低速状态标识码
movwf sf ;修改为一分钟低速状态标识码
;**********************************************************************
L1
incf mf,f
btfss mf,0 ;监视mf电机标志位bit0的乒乓状态,每两次250uS后改变GP2输出状态
goto $+3
movlw b'00000100'
xorwf GPIO,f ;取反GP2,
;-----------------------------------------------------------------
call chk_key
movlw b'00000010'
xorwf kf,w
btfss STATUS,Z
goto tmsL1
clrf tms
clrf tmsl
clrf tmsh
clrf ts
clrf kf
movlw b'00000010'
movwf sf ;标识下一步进入两分钟高速状态
goto H2
;-----------------------------------------------------------------
tmsL1
incf tmsl,f ;4000次ms计数
btfsc STATUS,C ;低位运算是否有进位?
incf tmsh,f ;有,高位加1
;-----------------------------------------------------------------
t500msL1
movlw 0x07 ;2000次(0.5s)计数比对,d'2000'=h'7d0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto t1sL1 ;不同,放弃比对
movlw 0xd0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行0.5秒钟时间到动作
goto t1sL1 ;不同,放弃比对
;-----------------------------------------------------------------
movlw b'00000010'
xorwf GPIO,f ;取反GP1,
;-----------------------------------------------------------------
t1sL1
movlw 0x0f ;4000次计数比对,d'4000'=h'fa0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto chk_tm ;不同,放弃比对
movlw 0xa0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行1秒钟时间到动作
goto chk_tm ;不同,放弃比对
;-----------------------------------------------------------------
incf ts,f ;秒计数器累加
clrf tmsl ;清4000次计数器低位
clrf tmsh ;清4000次计数器高位
;-----------------------------------------------------------------
movlw .60 ;准备比对时间
xorwf ts,w ;比对时间是否到60S
btfss STATUS,Z ;skpz
goto chk_tm ;没到,放弃比对
clrf ts ;60S(1分钟)到,清秒计数器
clrf tmsl ;60S(1分钟)到,清4000次计数器低位
clrf tmsh ;60S(1分钟)到,清4000次计数器高位
clrf ts ;60S(1分钟)到,清秒计数器
clrf kf ;60S(1分钟)到,清按键标识码
clrf GPIO ;off motor,off led
clrf sf ;修改为两分钟低速状态标识码,为下一次唤醒准备
goto enter_slp ;进入睡眠状态
;**********************************************************************
H2
movlw b'00000110'
movwf GPIO ;on motor,on led
;--------------------------------------------------
call chk_key
movlw b'00000010'
xorwf kf,w
btfss STATUS,Z
goto t1sH2
clrf tms
clrf tmsl
clrf tmsh
clrf ts
clrf kf
clrf sf ;修改为两分钟低速状态标识码,为下一次唤醒准备
goto enter_slp ;进入睡眠状态
;-----------------------------------------------------------------
t1sH2
incf tmsl,f ;4000次ms计数
btfsc STATUS,C ;低位运算是否有进位?
incf tmsh,f ;有,高位加1
;--------------------------------------------------
movlw 0x0f ;4000次计数比对,d'4000'=h'fa0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto chk_tm ;不同,放弃比对
movlw 0xa0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行1秒钟时间到动作
goto chk_tm ;不同,放弃比对
;-----------------------------------------------------------------
incf ts,f ;秒计数器累加
clrf tmsl ;清4000次计数器低位
clrf tmsh ;清4000次计数器高位
;-----------------------------------------------------------------
movlw .120 ;准备比对时间
xorwf ts,w ;比对时间是否到120S
btfss STATUS,Z ;skpz
goto chk_tm ;没到,放弃比对
clrf tms ;120S(2分钟)到,清10ms计数器
clrf tmsl ;120S(2分钟)到,清4000次计数器低位
clrf tmsh ;120S(2分钟)到,清4000次计数器高位
clrf ts ;120S(2分钟)到,清秒计数器
clrf kf ;120S(2分钟)到,清按键标识码
movlw b'00000011' ;准备修改为一分钟高速状态标识码
movwf sf ;修改为一分钟高速状态标识码
;**********************************************************************
H1
call chk_key
movlw b'00000010'
xorwf kf,w
btfss STATUS,Z
goto tmsH1
clrf tms
clrf tmsl
clrf tmsh
clrf ts
clrf kf
clrf sf ;修改为两分钟低速状态标识码,为下一次唤醒准备
goto enter_slp ;进入睡眠状态
;-----------------------------------------------------------------
tmsH1
movlw .1
addwf tmsl,f ;4000次ms计数
btfsc STATUS,C ;低位运算是否有进位?
incf tmsh,f ;有,高位加1
;--------------------------------------------------
t500msH1
movlw 0x07 ;2000次(0.5s)计数比对,d'2000'=h'7d0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto t1sH1 ;不同,放弃比对
movlw 0xd0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行0.5秒钟时间到动作
goto t1sH1 ;不同,放弃比对
;-----------------------------------------------------------------
movlw b'00000010'
xorwf GPIO,f ;取反GP1,
;-----------------------------------------------------------------
t1sH1
movlw 0x0f ;4000次计数比对,d'4000'=h'fa0'
xorwf tmsh,w ;先比对高位
btfss STATUS,Z ;是否相同?
goto chk_tm ;不同,放弃比对
movlw 0xa0 ;相同,继续比对低位
xorwf tmsl,w ;是否相同?
btfss STATUS,Z ;相同,跳过下一句,执行1秒钟时间到动作
goto chk_tm ;不同,放弃比对
;-----------------------------------------------------------------
incf ts,f ;秒计数器累加
clrf tmsl ;清4000次计数器低位
clrf tmsh ;清4000次计数器高位
;-----------------------------------------------------------------
movlw .60 ;准备比对时间
xorwf ts,w ;比对时间是否到60S
btfss STATUS,Z ;skpz
goto chk_tm ;没到,放弃比对
clrf ts ;60S(1分钟)到,清秒计数器
clrf tmsl ;60S(1分钟)到,清4000次计数器低位
clrf tmsh ;60S(1分钟)到,清4000次计数器高位
clrf ts ;60S(1分钟)到,清秒计数器
clrf kf ;60S(1分钟)到,清按键标识码
clrf GPIO ;off motor,off led
clrf sf ;修改为两分钟低速状态标识码,为下一次唤醒准备
goto enter_slp ;进入睡眠状态
;---------------------------------------------------------------------------
enter_slp
movlw b'00001111' ;电平唤醒ON,弱上拉ON(只对输入口有效),内部指令周期,
;上升沿触发,预分频器分配给watchdog,watchdog分频比1:128,
;此时定时器分频比为1:1。
option ;开电平唤醒及配置看门狗和定时器!是否启用看门狗
;由__CONFIG或编程器配置位决定。
movf GPIO,w ;在进入休眠模式之前,读取输入引脚(全为1,上拉电平)。
;当器件处于休眠模式时,引脚上的值不同于上次读该引
;脚时的状态时,就会发生唤醒。 如果发生电平变化时
;唤醒,并且没有在进入休眠模式前读引脚,即使在休眠
;模式中没有引脚发生变化,也会立即发生唤醒。
sleep
nop
;---------------------------------------------------------------------------
chk_key
movf kf,w
btfss STATUS,Z ;此前有没检测到有按键按下?
goto t20ms ;有检测到按下(kf不为0),跳至20mS计时
btfss GPIO,0 ;没检测到按下(kf为0),读取IO引脚值
goto $+3 ;再次测出有键按下
clrf kf ;无键按下(此前估计是干扰)
retlw 0
movlw b'00000001'
movwf kf ;有按键按下,标识起来。
retlw 0
t20ms
incf tms,f ;20ms计数(80次)
movlw .80 ;此前检测到有按键按下,进行80次计数比对
xorwf tms,w ;
btfss STATUS,Z ;是否相同?
retlw 0
clrf tms ;相同,20ms到,清20ms计数器
btfss GPIO,0
goto $+3 ;再次测出有键按下
clrf kf ;无键按下(此前估计是干扰)
retlw 0
movlw b'00000010'
movwf kf ;第二次测出按键按下,标识起来。
retlw 0
;---------------------------------------------------------------------------
end |
|