打印

基于pic10f206实现电容触摸按键开关

[复制链接]
1444|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
13929718617|  楼主 | 2018-5-9 11:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人是刚学习单片机的菜鸟,也刚接触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

相关帖子

沙发
13929718617|  楼主 | 2018-5-9 11:50 | 只看该作者
上面这份源码只是实现了按下是输出低电平,松开时输出高电平,那我该如何实现按键释放还持续输出我想要的电平状态呢??

使用特权

评论回复
板凳
dirtwillfly| | 2018-5-9 14:38 | 只看该作者
汇编。。。帮不上忙,帮顶

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝