PIC16F883实现按键行列扫描,准确识别按键,数码管显示按键编号

控制芯片:PIC16F883 oop

引脚图: code

按键链接图: io

 

四位数码管链接:四个共阴极分别链接PORTA<3:0>,8段数码管分别链接PORTC<7:0>,PORTB<4,2:0>分别链接按键的四个I/O引脚。 class

我在PORTC上链接了数码管,按键进行编号。按键时数码管会显示对应的编号。 变量

简单说明: 原理

我是改变PORTB引脚的设置(TRISB,PORTB),写了后马上读取PORTB引脚的值,检查链接按键的引脚——值为0的引脚有按键按下。好比上图,PORTB<4,2,1,0>引脚全设置为输入时,读取PORTB寄存器的值。若我按下了S7,PORTB4就是0值(同理S8\S9\S10)。咱们微机原理老师强调必定先检测S7\S8\S9\S10。我没试过先检测其余按键的状况,是按照老师的提示作的。下次更改设置:PORTB4设为输出低电位(0),其余三个引脚都设置为输入。读取PORTB<2,1,0>引脚的值,S5\S1\S2中某一按键被按下就能够在PORTB<2,1,0>对应的引脚检测到。就这样扫描全部按键,有按键按下就会调用按键处理程序。 配置

实现代码以下: 程序

#include<p16f883.inc>

udata_shr

counter res 1 ;延时计数

counter0 res 1 ;延时计数

counter1 res 1 ;扫描按键变量

counter2 res 1 ;延时程序微调参数

key_state res 1 ;按键状态

keynum res 1 ;按键标号

swap res 1 ;确认按键转换值

keydown res 1

keyup 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 WPUB ;设置PORTB弱上拉

movlw b'11111111'

movwf WPUB

banksel OPTION_REG

movlw b'01000101' ;TMR0 64分频

movwf OPTION_REG

banksel TRISA ;设置PORTA<3:0>为输出,接数码管的共阴极

movlw b'11110000'

movwf TRISA

banksel PORTA

clrf PORTA

banksel TRISC

movlw b'00000000' ;设置PORTC为输出,接8段数码管

movwf TRISC



loop

banksel TRISB

movf counter1,0

call Table1

movwf TRISB

banksel PORTB

movwf PORTB

movf PORTB,0

movwf key_state

movlw b'11101000'

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

clrf counter1

goto loop







delay ;按键去抖,约8mS

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



DealKeyPress

call delay

movf counter1,0

call Table1

banksel TRISB

movwf TRISB

banksel PORTB

movwf PORTB

movf PORTB,0 ;读取I/O状态

movwf key_state

movlw b'11101000'

iorwf key_state,1

movf counter1,0

call Table1

xorwf key_state,0

movwf swap

comf swap,1

incfsz swap,1

goto continue



movf keynum,0

call Table3

banksel PORTC

movwf PORTC

clrf keynum

return



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

end

我用逻辑与运算屏蔽掉PORTB<7,6,4>号引脚。仅检查PORTB<4,2,1,0>引脚。该方法先检测按键七、八、九、10,调整配置后检测按键五、一、2,再调整配置检测按键三、4,最后调整配置检测按键6。 方法

1)PORTB<4,2,1,0>设置为输入,而后读取并检测这四个角 im

2)PORTB4设置为输出低电平0,PORTB<2,1,0>设置为输入,而后检测二、一、0引脚电平(为0则有按键按下)

3)PORTB2设置为输出低电平,其余三个脚设置为输入,仅检测一、0引脚电平

4)PORTB1设置为输出低电平,其余三个角设置为输入,仅检测0引脚电平

因为个人按键编号与上图链接图不一致,图中的K七、K八、K九、K10分别对应个人K一、K二、K三、K4(按下数码管会显示一、二、三、4),K二、K四、K6分别对应个人K五、K六、K7(按下会显示五、六、7),K一、K3分别对应个人K八、K9(按下分别显示八、9),K5对应个人K10(这个因为数码管只设置1-9,K10按下会显示7是吴显示)。

相关文章
相关标签/搜索