
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。 关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。 前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。 本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。 思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。 对于具体应用,应进一步人性化。 部分头文件:
相关功能: uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。 uint8_t keycnt[keynum]; //计数器 uint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep; uint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。 // KEY ![]() void key_init(void) { uint8_t m; RCC->APB2ENR|=0x08; //enable PORTB clock GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£ GPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15 GPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£ GPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£ GPIOB->ODR&=0x0FF0; GPIOB->ODR|=0xF00F; for(m=0;m<keynum;m++){ keycnt[m]=0; keystat[m]=0; keymod[m]=0x10; } } //循环扫描,在定时中执行 void keyscan(void) { uint8_t k; for(k=0;k<keynum;k++){ keyone(k); } } //识别规则 void keyone(uint8_t nkey) { switch(nkey){ case 0: if(KEY0==KEYON){ if(keycnt[nkey]==keypress){ // keycnt[nkey]=0;//长按视为反复触发按键。 keystat[nkey]=0x02; }else{ keycnt[nkey]++; } }else{ keycnt[nkey]=0; } break; ………… } //后续动作,在定时中执行 void keydo(void) { if(keystat[0]==0x02){ keystat[0]=0; //reset key after done kset0(); //要执行的动作 } …………………… if(keystat[5]==0x02){ keystat[5]=0; //reset key begin done led_flush(2); led_flush(3); } } |