
刚写了一个关于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) {8 F& N. \% G3 ^" I; q# F2 Z9 N uint8_t m; RCC->APB2ENR|=0x08; //enable PORTB clock9 H/ W# n U3 D. ?: ]9 @ 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++){8 {! i- b& l/ I keycnt[m]=0; keystat[m]=0;( _+ D$ j3 c! O* A keymod[m]=0x10;, e0 }; K- ]1 t6 K F% T } } //循环扫描,在定时中执行 void keyscan(void)/ j, @) ]" j( H) d/ u { uint8_t k;" M( l( H5 v, f: w$ G- A0 g for(k=0;k<keynum;k++){ keyone(k);3 t3 G7 r/ _' l' S5 u } } //识别规则 void keyone(uint8_t nkey)2 ]" ^4 O1 R7 a { switch(nkey){ case 0:) l7 k' Z3 P4 I( w$ S, j- g if(KEY0==KEYON){ if(keycnt[nkey]==keypress){7 u: N/ r8 s" @: g) v2 N // keycnt[nkey]=0;//长按视为反复触发按键。 keystat[nkey]=0x02;" E- c8 c+ B$ s' \ }else{ keycnt[nkey]++; }8 [" Z8 ?5 Q1 a1 `* Y+ l2 |1 G }else{ keycnt[nkey]=0;% F$ b+ g0 g& m a! a0 R }/ y3 S7 x& p" r7 A9 W& b. d break; ………… } //后续动作,在定时中执行: x' l. e; k2 D+ V A" o' m void keydo(void) {8 f1 J4 P" b4 k+ |5 Q9 ]0 v if(keystat[0]==0x02){" T7 P% v' N; a" V( }1 v+ \9 S keystat[0]=0; //reset key after done9 d. J- v# S. H" R kset0(); //要执行的动作 }1 X+ x/ o3 y7 f3 q3 G. D ……………………3 w) ?! E' j1 V. @* f* z if(keystat[5]==0x02){ keystat[5]=0; //reset key begin done4 q% h! \& z: u; P led_flush(2); led_flush(3); } } |