PIC单片机 按键检测识别
目录
- 按键和PIC单片机
- 一、按键
- 二、按键的物理连接与检测
- 三、PIC16F18854单片机
- 按键检测及显示实验
- 按键排布
- 预期效果
- 总体流程
- 中断服务程序
- PIC汇编程序
按键和PIC单片机
一、按键
按键是嵌入式系统基本的人机交互手段,其使用步骤包括:检测连通、消抖、行为判断
二、按键的物理连接与检测
简单按键
缺点:占用端口引脚太多,一个按键就占一个引脚。
行列扫描按键
行为input,列为output
每个列依次接地,同时其他列高阻态(建议不用逻辑1,防止短路),观察哪一/些行为0,就能锁定到被按下的按键
有多个按键同时被按下时,程序可能会错误判断按键,不可信
上面这种对比简单按键并没有优势,还是太占用引脚
行列扫描的扩展
全扫描
行列之间两两一个,行行、列列间也是两两一个。
简单按键+全扫描
要求7~10与1~6不能同时检测,因为两组之间彼此干扰。因此必须先检测7~中有没有按下,没有的话再检测1~6。检测到有一个按下后就结束,不能检测多个同时按下的情况,不准确。
三、PIC16F18854单片机
按键检测及显示实验
按键排布
简单按键+全扫描,四根线对应连接到PIC单片机的4个引脚,最后一根接地。
预期效果
4位数码管显示按键编号、行为、按动次数
总体流程
数码管片选与段选各自维护一个查找表,在主程序中循环对数码管进行片选、段选、延时,其中段选时按照显示缓冲区内容执行。定时器中断周期设置为5ms,中断服务程序提供:连通检测、消抖、状态转换、显示驱动服务。其中关键部分是中断服务程序的设计。
中断服务程序
中断服务程序分为4个模块,模块间充分解耦,其间只有个别变量在整个流程中进行传递,其他大部分变量都是各个模块自身的局部变量。
1、连通检测
step1:单片机4个引脚弱上拉,依次检查4个引脚有无0电平,即7~10号按键有无按下,若无则进入step2。
step2:4个引脚两两间有6个按键,依次检测一遍,若只有1对为连通则说明仅一个按键按下,若有多对连通则为多按键被按下。
最后将检测到的连通状态cur_key传入消抖模块。
代码流程图:
2、消抖模块
检测连通检测模块传入的cur_key与上次传入的是否相同,若连着两次相同则认为不是抖动,继续传入状态转换模块;若不同,则认为是抖动造成的,把上次的key传入状态转换模块。本质是要求同一按键连按10ms才认为是按下而不是抖动。
代码流程图:
3、状态转换
状态转换模块功能是,根据消抖模块传入的cur_key来改变当前状态tatus,并且把相对应事件event和cur_key一起传入给后面的显示驱动模块。“输入——状态改变——输出”的运行逻辑正是一个状态机。
| CLICK | init(single) | wait | press(press) | click | init(single) |
| WAIT | init(single) | wait | init(single) | double(double) | click(single) |
| PRESS | init(press_up) | init(press_up) | - | same(press) | init(press_up) |
| INIT | init | init | - | click | click |
| DOUBLE | init | init | - | double | init |
代码流程图:
4、显示驱动
根据状态转换模块传来的event和cur_key调制主程序段选时使用的显示缓存区,从而在数码管显示按键状态和相应信息。
代码流程图:
PIC汇编程序
#include <xc.inc>psect intentry, class=CODE, delta=2psect reset_vec, class=CODE, delta=2psect eeprom_data,class=EEDATA,delta=2,space=3,noexecpsect powerup, class=CODE, delta=2psect cinit,class=CODE,delta=2psect functab,class=ENTRY,delta=2psect idloc,class=IDLOC,delta=2,noexecglobal _main, reset_vecpsect config, class=CONFIG, delta=2 #ifndef BOOTLOADERdw 0xDFECdw 0xF7FFdw 0xFFBFdw 0xEFFEdw 0xFFFF #endifpsect reset_vec reset_vec:ljmp _main;GLOBAL VARIABLESpsect CommonVar, class=COMMON, space=1, delta=1 ;main dis_cache: ds 4 delay1: ds 1 delay2: ds 1 ;debounce last_result: ds 1 count: ds 1 ;status_trans action: ds 1 state: ds 1 event: ds 1 wait_count: ds 1 click_count: ds 1 last_key: ds 1 ;connection_check index: ds 1 ;global cur_key: ds 1psect udata i: ds 1 j: ds 1 led_select: ds 1 workplace2: ds 1 dis_last_key: ds 1 dis_count: ds 2 swap: ds 1 press_count:ds 1;STATIC TABLEpsect Table, class=CODE, delta=2 event_table: MOVWF PCL IRP event,1,0,3,0,1,1,0,1,2,1,4,4,0,3,4RETLW event ENDMaction_table: MOVWF PCL IRP row_click,0b1111,0b101,0b1010,0b0,0b1111RETLW row_click ENDM IRP row_wait,0b1111,0b101,0b1111,0b10100,0b0RETLW row_wait ENDM IRP row_press,0b1111,0b1111,0xff,0b1010,0b1111RETLW row_press ENDM IRP row_init,0b1111,0b1111,0xff,0b0,0b0RETLW row_init ENDM IRP row_double,0b1111,0b1111,0xff,0b10100,0b1111RETLW row_double ENDMseq_table:ADDWF PCL,f IRP seq_num,0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111,0b01110111RETLW seq_num ENDMcode_table:MOVWF PCL IRP code_num,0b00000111,0b00001011,0b00001101,0b00001110RETLW code_num ENDMkey_table: ADDWF PCL,F IRP key_num,5,1,2,3,4,6RETLW key_num ENDM;INTERRUPT SERVICEpsect intentry intentry:;clear the signal bitBANKSEL PIR0BCF PIR0,5;init the TMR0 offsetBANKSEL TMR0L;MOCLW 0xfec0cMOVLW 0xecMOVWF TMR0HMOVLW 0x78MOVWF TMR0Lconnection_check:CLRF cur_keyBANKSEL iMOVLW 1MOVWF iCLRF indexBANKSEL TRISBMOVLW 0x0fMOVWF TRISBBANKSEL WPUBMOVLW 0x0fMOVWF WPUB jedge_i_16:BANKSEL iBTFSS i,4GOTO i_unequ_16GOTO i_equ_16i_unequ_16:BANKSEL iMOVF i, WBANKSEL PORTBANDWF PORTB, WBANKSEL workplace2MOVWF workplace2MOVF workplace2,fBTFSS STATUS,2 GOTO branch1_portb_unequ_0GOTO branch1_portb_equ_0i_equ_16:MOVF cur_key, fBTFSS STATUS,2GOTO trunk_curkey_unequ_0GOTO trunk_curkey_equ_0branch1_portb_equ_0:MOVF cur_key,fBTFSS STATUS,2GOTO branch1_curkey_unequ_0GOTO branch1_curkey_equ_0branch1_portb_unequ_0:BANKSEL iLSLF i, fINCF index,fGOTO jedge_i_16branch1_curkey_unequ_0:MOVLW 255MOVWF cur_keyGOTO trunk_curkey_unequ_0branch1_curkey_equ_0:MOVLW 7ADDWF index, WMOVWF cur_keyGOTO branch1_portb_unequ_0trunk_curkey_unequ_0:GOTO debouncetrunk_curkey_equ_0:BANKSEL iMOVLW 1MOVWF iMOVLW 2MOVWF jCLRF index jedge_i_8:BTFSS i, 3GOTO i_unequ_8GOTO i_equ_8i_unequ_8:MOVF j, wBTFSS j, 4GOTO j_unequ_16GOTO j_equ_16i_equ_8:GOTO trunk_curkey_unequ_0j_unequ_16:BANKSEL jCOMF j, WBANKSEL TRISBMOVWF TRISBBANKSEL WPUBMOVWF WPUBBANKSEL PORTBMOVWF PORTBBANKSEL iMOVF i, WBANKSEL PORTBANDWF PORTB, WBANKSEL workplace2MOVWF workplace2MOVF workplace2,FBTFSS STATUS,2 GOTO branch2_portb_unequ_0GOTO branch2_portb_equ_0j_equ_16:BANKSEL iLSLF i, fLSLF i, WMOVWF jGOTO jedge_i_8branch2_portb_equ_0:MOVF cur_key,F BTFSS STATUS,2 GOTO branch2_curkey_unequ_0GOTO branch2_curkey_equ_0branch2_portb_unequ_0:LSLF j, fINCF index, fGOTO i_unequ_8branch2_curkey_equ_0:;cur_key = key_table[index]MOVLW HIGH(key_table)MOVWF PCLATH MOVF index,WCALL key_tableMOVWF cur_keyGOTO j_equ_16branch2_curkey_unequ_0:MOVLW 255MOVWF cur_keyGOTO i_equ_8debounce:MOVF last_result, WXORWF cur_key, WBTFSC STATUS, 2GOTO deb_continue ;no shakeINCF count ;shakeMOVLW 2XORWF count, WBTFSS STATUS, 2GOTO deb_ignore ;not equMOVF cur_key, W;equMOVWF last_resultGOTO deb_continuedeb_ignore:MOVF last_result, WMOVWF cur_keyGOTO transferdeb_continue:CLRF countGOTO transfertransfer: ;key valueMULTI EQU 0xFFNOKEY EQU 0 ;action indexMULTIKEY EQU 0UP EQU 1TIMEOUT EQU 2SAME EQU 3OTHER EQU 4 ;state valueCLICK EQU 0WAIT EQU 5PRESS EQU 10INIT EQU 15DOUBLE EQU 20 ;constUPCOUNT EQU 60PRESSCOUNT EQU 100PRESSADD EQU 100 trans_judge_action:MOVLW MULTIXORWF cur_key, wBTFSC STATUS, 2GOTO action_multi ;multiMOVLW NOKEY ;continueXORWF cur_key, wBTFSC STATUS, 2GOTO action_up_timeout ;upMOVF last_key, w ;downXORWF cur_key, wBTFSC STATUS, 2GOTO action_same_timeout ;sameGOTO action_other ;other ; action_multi:MOVLW MULTIKEYGOTO do_transfer action_up_timeout:MOVLW WAITXORWF state, wBTFSS STATUS, 2GOTO action_up ;not waitINCF wait_count ;waitingMOVLW UPCOUNTXORWF wait_count, wBTFSS STATUS, 2GOTO action_upGOTO action_timeoutaction_up:MOVLW UPGOTO do_transfer action_same_timeout:MOVLW CLICKXORWF state, wBTFSS STATUS, 2GOTO action_sameINCF click_countMOVLW PRESSCOUNTXORWF click_count, wBTFSS STATUS, 2GOTO action_sameGOTO action_timeout action_same:MOVLW SAMEGOTO do_transfer action_timeout:MOVLW TIMEOUTGOTO do_transfer action_other:MOVLW OTHERGOTO do_transferdo_transfer:MOVWF actionCLRF eventMOVF state, waddlw 1ADDWF action, fMOVLW INIT+1SUBWF action, wBTFSC STATUS, 0GOTO change_state ;no carry -> state+action+1>=INIT+1movlp high(event_table)MOVLW low(event_table)ADDWF action, wBTFSC STATUS, 0INCF PCLATHCALL event_table ;get next stateMOVWF event change_state:movlp high(action_table)MOVLW low(action_table)ADDWF action, wBTFSC STATUS, 0INCF PCLATHCALL action_table ;get next stateMOVWF stateclear_count_judge:MOVF event, fBTFSC STATUS, 2GOTO transfer_final ;event == 0clear_count:CLRF wait_countCLRF click_counttransfer_final:banksel swapMOVF last_key, wMOVWF swapMOVWF cur_key, wBTFSS STATUS, 2MOVWF last_keyMOVF swap, wMOVWF cur_keydisplay:MOVF event, fBTFSC STATUS, 2RETFIEbanksel dis_last_keyMOVF dis_last_key, WXORWF cur_key, WBTFSC STATUS, 2GOTO display_judge_event display_change:banksel dis_countCLRF dis_countCLRF dis_count+1MOVF cur_key, Wbanksel dis_last_keyMOVWF dis_last_key display_judge_event:banksel dis_countMOVLW 3SUBWF event, WBTFSS STATUS, 0GOTO event_1_2 ;if carry -> event<3MOVLW 3XORWF event, WBTFSC STATUS, 2GOTO event_3GOTO display_finalevent_1_2:MOVF event,WADDWF dis_count, FGOTO display_final event_3:INCF press_countMOVLW PRESSADDXORWF press_count, WBTFSC STATUS, 2GOTO event_3_add_countGOTO display_finalevent_3_add_count:INCF dis_countCLRF press_countdisplay_final:MOVF cur_key, WMOVWF dis_cacheMOVF event,WMOVWF dis_cache+1MOVLW 10SUBWF dis_count, WBTFSS STATUS, 0GOTO display_count ;if carry display_count_carry:INCF dis_count+1MOVLW 10SUBWF dis_count, FSUBWF dis_count+1, WBTFSC STATUS, 0CLRF dis_count+1 ;if no carry display_count:MOVF dis_count, WMOVWF dis_cache+3MOVF dis_count+1, WMOVWF dis_cache+2RETFIE;MAIN FUNCTION psect main,class=CODE,delta=2 ; PIC10/12/16 global _main _main:;Timer0 configuration BANKSEL T0CON0 MOVLW 0b00010000;set Timer0 in 16bit mode,post:1:8 MOVWF T0CON0 BANKSEL T0CON1 MOVLW 01000000;FOCS/4,synchronized to FOSC/4,pre:1:1 MOVWF T0CON1 BANKSEL TMR0L MOVLW 0xfe MOVWF TMR0H MOVLW 0x0c MOVWF TMR0L;init the TMR0 offset;interrupt configuration BANKSEL PIR0 BCF PIR0,5;clear the timer signal bit banksel INTCON BSF INTCON,0;INT enable BSF INTCON,7;global enable banksel PIE0 BSF PIE0,5;timer0_interrupt enable;start timing BANKSEL T0CON0 BSF T0CON0,7; enable Timer0;init PORTA / PORTB / PORTC BANKSEL PORTA CLRF PORTA ;Init PORTA BANKSEL LATA ;Data Latch CLRF LATA BANKSEL ANSELA CLRF ANSELA ;digital I/O BANKSEL TRISA CLRF TRISABANKSEL LATB ;Data Latch CLRF LATB BANKSEL ANSELB CLRF ANSELB ;digital I/OBANKSEL PORTC BANKSEL PORTC CLRF PORTC ;Init PORTC BANKSEL LATC ;Data Latch CLRF LATC BANKSEL ANSELC CLRF ANSELC ;digital I/O BANKSEL TRISC CLRF TRISC;init variables CLRF dis_cache CLRF dis_cache + 1 CLRF dis_cache + 2 CLRF dis_cache + 3 CLRF last_result CLRF count CLRF action MOVLW 15 MOVWF state CLRF wait_count CLRF click_count CLRF last_key CLRF index CLRF cur_key BANKSEL led_select CLRF led_select CLRF i CLRF j CLRF dis_last_key CLRF dis_count CLRF swap CLRF press_count CLRF workplace2;MAIN LOOP: ;code_sel MOVLW HIGH(code_table) MOVWF PCLATH MOVLW LOW(code_table) BANKSEL led_select ADDWF led_select, W BTFSS STATUS, 0 GOTO CALL_TABLE INCF PCLATH CALL_TABLE: ADDLW 1 CALL code_table BANKSEL PORTA MOVWF PORTA;seq_sel MOVLW HIGH(seq_table) MOVWF PCLATH ;w = dis_cache + offset MOVLW high(dis_cache) MOVWF FSR0H MOVLW low(dis_cache) BANKSEL led_select ADDWF led_select, w MOVWF FSR0L MOVF INDF0, w ;seq_table[dis_cache + offset] CALL seq_table MOVWF PORTC ;led_select = (led_select + 1) mod 4 BANKSEL led_select INCF led_select,f MOVLW 0b11 ANDWF led_select,f;delay MOVLW 2 MOVWF delay2 DELAY1: MOVLW 0xff MOVWF delay1 DECFSZ delay1,f GOTO $-1 DECFSZ delay2,f GOTO DELAY1;end seq_select CLRF PORTCGOTO LOOPend reset_vec总结
以上是生活随笔为你收集整理的PIC单片机 按键检测识别的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 基于socket的线上聊天框
- 下一篇: PIC单片机 电容式触摸检测