STMCU小助手
发布时间:2022-2-5 23:00
|
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。 关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。 前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。 本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。 思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。 对于具体应用,应进一步人性化。 部分头文件:
相关功能: uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。7 E# l1 K4 g& B+ m: x8 w uint8_t keycnt[keynum]; //计数器7 R. ^9 z1 `2 g# V l/ j2 B+ F uint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;# R: J4 l4 W8 I/ k a: u+ ?+ u6 h uint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。 // KEY B12,PB13,PB14,PB15void key_init(void) {9 j1 E6 Z' L+ g8 Y7 \" b uint8_t m; `! w {; _7 Q/ _/ `$ ^: Y6 w4 `6 F$ P RCC->APB2ENR|=0x08; //enable PORTB clock GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£% j' j' i, w& B* f; H GPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15( e! m$ r5 K. k0 u GPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£ GPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£ GPIOB->ODR&=0x0FF0;" b) E4 P _ U1 e& P/ E- I GPIOB->ODR|=0xF00F; 7 o2 O1 c9 Y5 L H4 V5 u; P for(m=0;m<keynum;m++){ keycnt[m]=0;. {: l6 s# z% i, J keystat[m]=0;( R6 ]8 \/ t; n/ Z, P keymod[m]=0x10; }, S, |; G6 G% S* i! j } //循环扫描,在定时中执行 void keyscan(void)& E3 Q! t `2 I$ K9 m6 t4 Z {- B- q$ a P3 `$ }4 t9 |, w uint8_t k; for(k=0;k<keynum;k++){ keyone(k); }5 G- I/ z8 Q% y5 z4 k1 r } //识别规则 void keyone(uint8_t nkey)/ x* e7 C: L9 j# `- G {" S& A' Z9 D( M switch(nkey){- _$ Y4 B, v2 G0 k3 ?& x; y* J case 0: if(KEY0==KEYON){ if(keycnt[nkey]==keypress){8 G N! ?- n, i, ^ // keycnt[nkey]=0;//长按视为反复触发按键。 keystat[nkey]=0x02;, g$ ]; b' X4 M+ \7 b8 w! | }else{ keycnt[nkey]++;6 }: t4 p9 X7 Y2 P$ m$ }* f } }else{9 ~' k6 {& @ _ keycnt[nkey]=0;: G4 O/ C8 C& t4 z }- e1 T ~) k2 P+ `1 w5 F break; ………… } //后续动作,在定时中执行 4 ` f7 P' g4 s' Wvoid keydo(void)' d4 [ e1 l3 ? {3 }* c$ q B5 r) [, r- F* o$ p4 [ if(keystat[0]==0x02){0 R+ E, p7 b1 N1 a6 J keystat[0]=0; //reset key after done kset0(); //要执行的动作 } Z M, p1 {- q2 F6 { …………………… }. ?" H+ l! L) Y; T+ ]$ E& o if(keystat[5]==0x02){2 R& V- V; V/ ~8 Y) K keystat[5]=0; //reset key begin done led_flush(2); led_flush(3); }+ ^2 T) g) h; @. E. _, A } |
实战经验 | 基于STM32G0B1的全桥移相+同步整流PWM解决方案
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
【福利三:逢7发帖赢大礼】8、基于STM32G070板子的Ymodem串口协议IAP Bootloader开发
【福利三:逢7发帖赢大礼】7、基于STM32G070板子TF卡的FATFS移植
【福利三:逢7发帖赢大礼】6、基于STM32G070板子spiflash的FATFS移植
【福利三:逢7发帖赢大礼】5、基于STM32G070板子IRDA红外遥控接收解码
【福利三:逢7发帖赢大礼】4、基于STM32G070板子SPI flash 移植SFUD库
【福利三:逢7发帖赢大礼】基于STM32G070板子的uart shell移植设计
【福利三:逢7发帖赢大礼】3、基于STM32G070板子的YModem串口协议通信
【福利三:逢7发帖赢大礼】2、基于STM32G070板子的OLED移植U8G2库
微信公众号
手机版