PIC單片機按鍵檢測,單雙擊、長短按識別

硬件PIC16F883芯片,10個按鍵,4位數碼管。 oop

【芯片引腳】 code

 

【數碼管鏈接】PORTC鏈接數碼管的8段LED,PORTA<3:0>鏈接數碼管的4個共陰極(控制選通位)。 io

【按鍵鏈接】 class

 

按鍵掃描程序在上一篇博文裏面有說明,如今仍是使用上面的掃面方式(代碼都是同樣的)。用記錄按鍵按下和彈起的時間判斷是否是長按和雙擊。TMR1設置,1:4分頻、1:8預分頻,計數週期爲8uS。TMR1溢出一次時間爲0.524288 S keypress記錄TMR1溢出的次數。keypress大於等於2就跳出檢測,認爲他是長按(時間爲1.048576S)。keypress<1 且keyrelease <1 ,再次按下的keypress<1就認爲是雙擊。以下圖: 變量

KP按鍵按下,KR按鍵彈起。 cli

【實現代碼】 配置

#include<p16f883.inc>

 

__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

 

udata_shr

counter res 1 ;計數個位

counter0 res 1 ;計數十位

counter1 res 1 ;掃描按鍵變量

counter2 res 1 ;延時程序微調參數

key_state res 1 ;按鍵狀態

keynum res 1 ;按鍵標號

swap res 1 ;確認按鍵轉換值

keypress res 1

keypressbak res 1

keyrelease res 1

LED1 res 1

LED2 res 1

LED3 res 1

LED4 res 1

    UDATA

counter3 res 1

counter4 res 1

sign res 1

 

reset code 0x0000

pagesel start

goto start

 

;int_vector code 0x0004

code

start

banksel ANSEL ;設置PORTA爲數字模式

clrf ANSEL

banksel ANSELH ;設置PORTB爲數字模式

clrf ANSELH

banksel TRISB ;設置PORTB爲輸入模式

movlw b'11111111'

movwf TRISB

banksel WPUB ;設置PORTB弱上拉

movlw b'11111111'

movwf WPUB

banksel OPTION_REG

movlw b'01000101' ;TMR0 64分頻

movwf OPTION_REG

banksel T1CON

movlw b'10010001' ;打開TMR1,設置1:8預分頻,內部時鐘源1:4分頻

movwf T1CON

banksel TRISA ;設置PORTA<3:0>爲輸出,接數碼管的共陰極

movlw b'11110000'

movwf TRISA

banksel PORTA

clrf PORTA

banksel TRISC

movlw b'00000000' ;設置PORTC爲輸出,接8段數碼管

movwf TRISC

clrf counter1

 

loop

movlw HIGH Table1

movwf PCLATH

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

movf counter1,0

call Table1

banksel PORTB

movwf PORTB

movf PORTB,0

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

 

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto case1

 

incf counter1,1

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

movf counter1,0

call Table1

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto case2

 

incf counter1,1

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

movf counter1,0

call Table1

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto case3

 

incf counter1,1

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

movf counter1,0

call Table1

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto case4

goto continue

 

case1

btfsc key_state,4

goto key2

movlw d'1'

movwf keynum

call DealKeyPress

goto continue

key2

btfsc key_state,2

goto key3

movlw d'2'

movwf keynum

call DealKeyPress

goto continue

key3

btfsc key_state,1

goto key4

movlw d'3'

movwf keynum

call DealKeyPress

goto continue

key4

btfsc key_state,0

goto continue

movlw d'4'

movwf keynum

call DealKeyPress

goto continue

 

 

 

 

case2

;-------------------------------------------------

;下面代碼實現K10\K8\K5的按鍵處理

btfsc key_state,2

goto key8

movlw d'10'

movwf keynum

call DealKeyPress

goto continue

;------------------------------------

;處理K8

key8

btfsc key_state,1

goto key5

movlw d'8'

movwf keynum

call DealKeyPress

goto continue

;------------------------------------

;處理K5

key5

btfsc key_state,0

goto case3

movlw d'5'

movwf keynum

call DealKeyPress

goto continue

 

case3

;----------------------------------

;處理K6/K9

btfsc key_state,1

goto key6

movlw d'9'

movwf keynum

call DealKeyPress

goto continue

key6

btfsc key_state,0

goto case4

movlw d'6'

movwf keynum

call DealKeyPress

goto continue

case4

;-----------------------------------------

;處理K7

btfsc key_state,0

goto continue

movlw d'7'

movwf keynum

call DealKeyPress

 

continue

call display

clrf counter1

goto loop

 

 

;-----------------------------------

;按鍵去抖,約8mS

delay

movlw d'4'

movwf counter2

LOOP2

banksel TMR0

clrf TMR0

LOOP1

banksel INTCON

btfss INTCON,T0IF

goto LOOP1

bcf INTCON,T0IF

decfsz counter2,1

goto LOOP2

return

 

delay2

incfsz counter3,1

goto delay2

return

 

;--------------------------------

;按鍵處理程序

;

DealKeyPress

clrf LED1

clrf LED2

clrf LED3

clrf LED4

call delay

 

banksel TMR1H

clrf TMR1H

banksel TMR1L

clrf TMR1L

clrf keypress

presstime

banksel PIR1

btfss PIR1,TMR1IF

goto next

bcf PIR1,TMR1IF

incf keypress

movlw d'2'

subwf keypress,0

banksel STATUS

btfsc STATUS,C

goto longpress

next

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto presstime


call delay

 

banksel TMR1H

clrf TMR1H

banksel TMR1L

clrf TMR1L

clrf keyrelease

releasetime

banksel PIR1

btfss PIR1,TMR1IF

goto next1

bcf PIR1,TMR1IF

incf keyrelease

movlw d'1'

subwf keyrelease,0

banksel STATUS

btfsc STATUS,C

goto click

next1

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto over

goto releasetime

over

call delay

banksel TMR1H

clrf TMR1H

banksel TMR1L

clrf TMR1L

clrf keypress

presstime1

banksel PIR1

btfss PIR1,TMR1IF

goto next2

bcf PIR1,TMR1IF

incf keypress

movlw d'1'

subwf keypress,0

banksel STATUS

btfsc STATUS,C

goto click

next2

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

banksel PORTB

movwf PORTB

movf PORTB,0 ;讀取I/O狀態

movwf key_state

movlw b'11001000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto presstime1

movf keynum,0                    ;雙擊

movwf LED1

movlw d'10'

movwf LED2

incf counter

goto back

longpress                         ;長按

movf keynum,0

movwf LED2

movlw d'10'

movwf LED1

goto back

click                         ;單擊

movf keynum,0

movwf LED1

movwf LED2

 

back

call CountNum

return

 

;----------------------------

;按鍵計數

;

 

CountNum

movlw d'9'

subwf counter,0

banksel STATUS

btfsc STATUS,C

goto add

incf counter

goto over1

add

incf counter0

clrf counter

movlw d'10'

subwf counter0,0

banksel STATUS

btfsc STATUS,C

goto clear

goto over1

clear

clrf counter0

over1

movf counter,0

movwf LED4

movf counter0,0

movwf LED3

return

 

 

 

 

;--------------------------------

;顯示數碼管

;

display

 

banksel PORTA

movlw b'11111110'

movwf PORTA

movf LED1,0

call Table3

banksel PORTC

movwf PORTC

call delay2

 

banksel PORTA

movlw b'11111101'

movwf PORTA

movf LED2,0

call Table3

banksel PORTC

movwf PORTC

call delay2

 

banksel PORTA

movlw b'11111011'

movwf PORTA

movf LED3,0

call Table3

banksel PORTC

movwf PORTC

call delay2

 

banksel PORTA

movlw b'11110111'

movwf PORTA

movf LED4,0

call Table3

banksel PORTC

movwf PORTC

call delay2

return

;----------------------

;Table真值表

;

Table1 ;PORTB、TRISB掃描配置信息

    ADDWF   PCL,f

    RETLW   B'11111111' 

    RETLW   B'11101111'

    RETLW   B'11111011'

    RETLW   B'11111101'

     

Table3 ;PORTC設置,數碼管真值表

    ADDWF   PCL,f

; RETLW B'01001001' ;三條橫線

    RETLW   B'10111111' ;0

    RETLW   B'00000110' ;1

    RETLW   B'01011011' ;2

    RETLW   B'01001111' ;3

    RETLW   B'01100110' ;4

    RETLW   B'01101101' ;5

    RETLW   B'01111101' ;6

    RETLW   B'00000111' ;7

    RETLW   B'01111111' ;8

    RETLW   B'01101111' ;9

RETLW B'00000000' ;黑屏

end

長按效果——三、4位數碼管計數一直加,1位數碼管熄滅,2位數碼管顯示按鍵編號; 硬件

雙擊效果——三、4位數碼管計數增長2,2位數碼管熄滅,1位數碼管顯示按鍵編號; 程序

單擊效果——一、2數碼管顯示按鍵編號,三、4位數碼管計數增長1。 im

相關文章
相關標籤/搜索