本人是刚学习单片机的菜鸟,也刚接触pic,现在有个任务是用pic触摸按键实现:按一下持续发送一个低电平(开灯),再按一下持续发送一个高电平关灯,求大神帮忙指导。下面是代码:
;********************************************************
;* file: 10ftouch.asm ver 1.2 *
;* auth: m. flipse *
;* date: *
;*
;* modf: T. Perme
;* date: 24 March 2008
;* desc:
;*
;* Software License Agreement
;*
;* The software supplied herewith by Microchip Technology
;* Incorporated (the "Company") is intended and supplied to you, the
;* Company? customer, for use solely and exclusively on Microchip
;* products. The software is owned by the Company and/or its supplier,
;* and is protected under applicable copyright laws. All rights are
;* reserved. Any use in violation of the foregoing restrictions may
;* subject the user to criminal sanctions under applicable laws, as
;* well as to civil liability for the breach of the terms and
;* conditions of this license.
;*
;* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
;* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
;* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
;* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
;* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;*
;********************************************************
processor pic10f206
radix dec
include <p10f206.inc>
include "Vars.inc"
gatedtime equ .33 ; time in msec that is used to measure the frequency
avdepth equ .5 ; averaging depth
; 2 ^ (n-1) x oldvalue + newvalue
; = ---------------------------------
; (2 ^ n)
; For Proximity
triplo_prx equ .20 ; difference between average and current zy
;triplo_prx equ .254 ; difference between average and current
triphi_prx equ .1 ; frequency value for a key to be detected. (512 counts) 用于检测的键的频率值。
; Smaller values have a more sensitive trip (good for proximity)
; For Touch
triplo_tch equ .70 ; difference between average and current zy 65
triphi_tch equ .0 ; frequency value for a key to be detected. (512 counts)
; Smaller values have a more sensitive trip (good for proximity)
hysteresis equ .200 ; constant that is used to lower the averagevalue
;迟滞 常用于当允许持续接触时降低平均水平
; when continuous touch is enabled
__config _intrc_osc & _wdt_on & _mclre_off & _cp_off
org .0 ; reset vector
reset
;若希望第一次不需要拔掉跳线帽,可以写成
;①屏蔽movwf osccal ②加上bcf osccal,FOSC4
movwf osccal ; calibrate internal oscillator 调整内部振荡器
;bcf osccal,FOSC4 ;bcf f,d 将f寄存器某位清零
;将osccal 的FOSC4置0
; If waking from intentional sleep, return back to post-sleep command 如果从有意的睡眠中醒来,返回到睡眠后的命令
; CWUF = 0, GPWUF = 0, TO = 0, PO = 0 STATUS BITS for wake from WDT
; movf STATUS, w
; andlw b'11111000' ; and off ALU status bits to zero
; btfsc STATUS, Z ; check if all bits are zero, branch accordingly
; goto jumpbackaftersleep ; all zero
; goto jumpinit ; non-zero
jumpbackaftersleep:
; clrwdt ; Clr wdt, resetting PO and TO to 1 in status reg
; goto wake_from_sleep
jumpinit:
call init ; init the device if starting from power-up
goto main
;********************************************************
;* Init subroutine *
;********************************************************
;{
init
movlw b'11110111'
; ||||||||_ ps0 PS2:PS1:PS0 = 111
; |||||||__ ps1 set prescaler to 1:256 预分频比设置为1:256
; ||||||___ ps2
; |||||____ psa prescaler assigned to tmr0 预分频器分配给tmr0
; ||||_____ t0se increment on high to low 电平从高到低变化时递增
; |||______ t0cs transition on t0cki 时钟源从t0cki引脚输入
; ||_______ #gppu pull-ups disabled 禁止上拉
; |________ #gpwu wake-up on pin change disabled 禁止引脚电平改变时唤醒
option
movlw b'00001011'
; ||||||||_ #cwu wake-up on comp change disabled 禁止比较器电平变化唤醒
; |||||||__ cpref pos ref is cin+ 比较器正参考源为cin+
; ||||||___ cnref neg ref is internal 0.6V reference 比较器负参考源为内部参考电压0.6V
; |||||____ cmpon comparator on 使能比较器
; ||||_____ cmpt0cs comparator output used as tmr0 clock 比较器输出用作tmr0时钟源
; |||______ pol output is inverted 比较器输出翻转
; ||_______ #couten output is placed on cout pin 比较器输出至cout引脚
; |________ cmpout -read only bit- 该位仅可读
movwf cmcon0
movlw b'11111001' ; set gp1 and gp2 as an output
tris gpio ; 当W=0时,置对应I/O口为输出;W=1,置I/O口为输入。
clrf averagehi
clrf averagelo
clrf averagefraction
clrf userflag
retlw .0 ; retlw k ; 返回时把k送去w
;}
;********************************************************
;* Delay subroutine *
;* descr: causes a timing delay in mSecs *
;* *
;* in: w - value in mSecs *
;********************************************************
;{
delay
movwf temp1
wait
movlw .249
movwf temp2
clrwdt ; instead of nop, use clrwdt to clrwdt while awake
decfsz temp2 ; all other code is much much less than 18ms (WDT timeout) when not delaying f减1,为0则跳过
goto $-2
decfsz temp1
goto wait
retlw .0
;}
;********************************************************
;* subroutine: average
;* descr:
;*
;* in: freqhi, freqlo *
;* out: averagehi,averagelo
;********************************************************
;{
average
movf averagehi,w
movwf avhitemp
movf averagelo,w
movwf avlotemp
clrf temp2 ; make a copy of the original value
call divideby2pwrn ; divide the copy by 2^n
;******
movf temp2,w
subwf averagefraction ; and subtract the result from the original
btfsc status,c
goto hopover
decf averagelo
movlw .255
xorwf averagelo,w ;把w与f作异或
btfsc status,z
decf averagehi
hopover
movf avlotemp,w
subwf averagelo
btfss status,c
decf averagehi
movf avhitemp,w
subwf averagehi ; average - 1/(2^n)
;******
movf freqhi,w
movwf avhitemp
movf freqlo,w
movwf avlotemp ; make a copy of the original value
clrf temp2
call divideby2pwrn ; divide by 2^n
movf temp2,w
addwf averagefraction
btfss status,c
goto hopover2
incf averagelo
btfsc status,z
incf averagehi
hopover2
movf avlotemp,w
addwf averagelo
btfsc status,c
incf averagehi
movf avhitemp,w
addwf averagehi
retlw .0 ;返回时将立即数送入W
divideby2pwrn
movlw avdepth
movwf temp1
shift1
bcf status,c ;将F寄存器中的某位清零
rrf avhitemp ;将F执行带进位循环右移
rrf avlotemp
rrf temp2
decfsz temp1 ;寄存器加1,为零(溢出)时跳指令
goto shift1
retlw .0
;}
;********************************************************
;* subroutine: checkdifference *
;* descr: subtracts actual value from average *
;* *
;* out: freqhi:freqlo with frequency *
;********************************************************
;{
checkdifference
movf averagehi,w
movwf differencehi
movf averagelo,w
movwf differencelo ; make a copy of the averagevalue
movf freqlo,w
subwf differencelo
btfss status,c
decf differencehi
movf freqhi,w
subwf differencehi ; averagevalue - currentvalue
btfsc status,c ; is the difference negative?
goto evaldifference ; no positive, check if it exceeds the trip point
movf freqhi,w ; yes, key is released
movwf averagehi ; average should follow actual value
movf freqlo,w
movwf averagelo
clrf differencehi
clrf differencelo
bcf userflag,keydown
retlw .0
evaldifference ;估算变化
bcf userflag,keydown
movlw triphi_tch
btfsc gpio, 3 ;F中的某位为0则跳过
movlw triphi_prx
subwf differencehi,w
btfss status,z ; are hi bytes equal? F中的某位为1则跳过
goto results
movlw triplo_tch
btfsc gpio, 3
movlw triplo_prx ; yes, compare lower bytes
subwf differencelo,w ;将f减去W
results
btfss status,c ; was the difference > trip point?
retlw .0 ; no, return
bsf userflag,keydown ; yes, set the keydown flag
retlw .0
;}
;********************************************************
;* subroutine: getfrequency *
;* descr: converts to binary coded decimal *
;* 十进制转换为二进制编码 *
;* out: freqhi:freqlo with frequency *
;********************************************************
;{
getfrequency
movlw b'11110111'
; ||||||||_ ps0 PS2:PS1:PS0 = 111
; |||||||__ ps1 set prescaler to 1:256 预分频比设置为1:256
; ||||||___ ps2
; |||||____ psa prescaler assigned to tmr0 预分频器分配给tmr0
; ||||_____ t0se increment on high to low 电平从高到低变化时递增
; |||______ t0cs transition on t0cki 时钟源从t0cki引脚输入
; ||_______ #gppu pull-ups disabled 禁止上拉
; |________ #gpwu wake-up on pin change disabled 禁止引脚电平改变时唤醒
option
movlw b'00001011'
; ||||||||_ #cwu wake-up on comp change disabled 禁止比较器电平变化唤醒
; |||||||__ cpref pos ref is cin+ 比较器正参考源为cin+
; ||||||___ cnref neg ref is internal 0.6V reference 比较器负参考源为内部参考电压0.6V
; |||||____ cmpon comparator on 使能比较器
; ||||_____ cmpt0cs comparator output used as tmr0 clock 比较器输出用作tmr0时钟源
; |||______ pol output is inverted 比较器输出翻转
; ||_______ #couten output is placed on cout pin 比较器输出至cout引脚
; |________ cmpout -read only bit- 该位仅可读
movwf cmcon0
movlw .255 ; frequency will be stored in freqhi:freqlo
movwf freqlo ; freqlo is pre-initialised here
clrf tmr0 ; clear tmr0 and the 1:256 prescaler 清零预分频器和tmr0
movlw gatedtime
call delay ; wait N mSec for scan time 等待固定时间
bcf cmcon0,cmpon ; turn off oscillator 关闭振荡器
movf tmr0,w ; high byte of value is stored in tmr0 读取tmr0
movwf freqhi ; low value is still in the prescaler
; To get the value from the prescaler (which is not directly readable),
; the clock source for tmr0 is changed to Fosc/4.
; Next the value of tmr0 is observed. The time is takes for the next
; increment is an indication of the value of the prescaler.
movlw b'11010111' ; change clock source to Fosc/4 把时钟源改为Focs/4
option
measureprescaler
incf freqlo ; was initialised to 255 and set to 0 here 初始化为255,在这里设置为0 ;寄存器加1指令
movf tmr0,w ; get the current value of tmr0 读取当前的tmr0 ;传送f寄存器的值去w
xorwf freqhi,w ; compare it with the original value of tmr0 比较tmr0初值与当前变量 ;w与f的内容作逻辑异或运算
btfsc status,z ; did tmr0 increment? tmr0是否递增 ;位测试,为0则跳指令
goto measureprescaler ; no, loop and increment freqlo
; Now freqlo ranges from 0 to 43. The next section will muliply it
; with 6 and clipped to 255, to get the lobyte of the frequency count.
bcf status,c ; clear the carry bit
rlf freqlo ; muliply by 2 带进位左移指令,并把结果存于w
rlf freqlo ,w ; and muliply by 2 again, but put the result in w 带进位左移指令,并把结果存于w
addwf freqlo ; add it to the doubled value (multiplied by 6) W和f寄存器中的值相加,结果存于目标寄存器
btfss status,c ; did it overflow (6 x 43 = 258) 位测试,为1则跳指令
goto nooverflow ; no, go on
movlw .255 ; yes, clip it to 255
movwf freqlo
nooverflow
comf freqlo ; the time for the prescaler to roll over was measured, f寄存器中的值做补码运算后,结果存于目标寄存器中
; so its value was 255 - prescaler value
; Because of the way the prescaler rollover time was measured (6 Tcy in measureprescaler),
; atleast the 2 least significant bits in freqhi:frequlo are useless.
; Therefore the final result is divided by 4.
bcf status,c ; 把c位置0
rrf freqhi ; freqhi带进位右移指令,并把结果存于w
rrf freqlo ; freqlo带进位右移指令,并把结果存于w
bcf status,c
rrf freqhi ; freqhi divide by 4
rrf freqlo ; freqlo divide by 4
bcf cmcon0, cmpon ; turn comp off to conserve power 关闭比较器
retlw .0 ; done
;}
;********************************************************
;* main *
;********************************************************
;{
main
movlw gatedtime
call delay ; wait 30mSec
movlw .49
movwf differencelo
movlw .1
movwf differencehi
call evaldifference
nop
call getfrequency
movf freqhi,w ;传送f,d=0则传给W
movwf averagehi
movf freqlo,w
movwf averagelo
call average
mainloop
; Sensing and Detection
call getfrequency
;call average
call checkdifference
; Check if Key Was Pressed
btfsc userflag, keydown ; F中的某位为0则跳过
goto react_keydown
nop
btfss userflag, keydown ; F中的某位为1则跳过
goto react_keyup
nop
; If a press was detected, output low (LED ON) else output high (LED OFF)
react_keydown:
bcf gpio, output ; turn led on
goto finish_loop
react_keyup:
bsf gpio, output ; turn led off
goto finish_loop
; Code below was left in to show possible use of sleeping and waking via WDT
; to significantly reduce power. Requires code on power up (also commented)
; in order to determine that it is a wake from sleep, not power up in order
; to resume normal operation
finish_loop:
; Sleep
; movlw b'11111011' ; Prescalar on 1:8 WDT, assign to WDT
; option
; movlw .1
; call delay ; delay for 1 ms to ensure comparator off, everything settled before sleep
; sleep ; goto sleep for ~144ms (8*18ms)
; nop ; don't pre-fetch anything unintended after sleep instruction
; Sleep Code Commented out
; Sleeping more between scans will reduce avg current
; 33ms on, 144ms off avg draw = ~70uA WDT prescale 1:8 (5.6scan per sec)
; 33ms on, 288ms off avg draw = ~50ua WDT prescale 1:16 (3.1scan per sec)
wake_from_sleep:
; movlw b'11110111' ; Return Prescalar to 1:256 assigned to TMR0
; option ; re-init option reg
; movlw b'00001011'
; movwf cmcon0 ; re-init cmcon0
; movlw b'11111001'
; tris gpio ; re-init gpio
; Sleep code commented
goto mainloop ; stay in main loop
;---------------------------------------------------------------------
end
下面是仿真图:
C:\Users\dell001\Desktop\Andy_c\1525836663(1).jpg |