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

倾然丶 夕夏残阳落幕 提交于 2020-12-23 19:25:01

控制芯片:PIC16F883

引脚图:

按键连接图:

 

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

我在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>引脚。该方法先检测按键7、8、9、10,调整配置后检测按键5、1、2,再调整配置检测按键3、4,最后调整配置检测按键6。

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

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

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

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

由于我的按键编号与上图连接图不一致,图中的K7、K8、K9、K10分别对应我的K1、K2、K3、K4(按下数码管会显示1、2、3、4),K2、K4、K6分别对应我的K5、K6、K7(按下会显示5、6、7),K1、K3分别对应我的K8、K9(按下分别显示8、9),K5对应我的K10(这个由于数码管只设置1-9,K10按下会显示7是吴显示)。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!