你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】stm32按键识别

[复制链接]
STMCU小助手 发布时间:2022-2-5 23:00
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。
关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。
前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。
本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。
思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。
对于具体应用,应进一步人性化。
部分头文件:
  1. // KEY:PB12,PB13,PB14,PB15;PB3,PB4( f' n9 @7 [) c) m
  2. // KEY On:0 ; KEY Off:1 低电平触发4 u7 H/ N+ p9 }) s- C/ l
  3. ! h8 {! u2 ?* y0 A
  4. #ifndef __MINIKEY_6 \% R2 \, X/ t3 P* M# o
  5. 7 k, g- H( T* h, d, |
  6. #define __MINIKEY_
    - @0 Q( u3 I% T9 [: x# y

  7. 3 q7 X* X; c% D' T& }
  8. #include "stdint.h"
    ! q, t6 c* o- l7 K- `1 h
  9. #include "miniled.h"
    5 y' J5 ^$ M4 o
  10. #include "miniusart.h"8 r4 g" g+ k* o7 G
  11. #include "minirtc.h": H9 J+ V: X+ a
  12. 0 h0 c& \- ~; b& c: U) J) t6 P
  13. #define keynum 6 //On Board KEY NUMBER& L! A" w6 A7 }/ P

  14. 6 b4 Z+ E3 Y% U6 Y. @( a
  15. #define KEY0 (GPIOB->IDR&0x1000) //PB12
    % z% M3 b8 [  |; ~' [+ ]
  16. #define KEY1 (GPIOB->IDR&0x2000) //PB13,
    . v( F9 V% F& d) e
  17. #define KEY2 (GPIOB->IDR&0x4000) //PB14/ ~6 y* V: M0 P% Z# @% w
  18. #define KEY3 (GPIOB->IDR&0x8000) //PB15
    ; U1 c, [* ~1 l* B
  19. #define KEY4 (GPIOB->IDR&0x0001) //PB07 a8 `! f- w8 y& Q" V0 I; j! T# W
  20. #define KEY5 (GPIOB->IDR&0x0002) //PB17 {4 ]) b) r2 w2 o
  21. #define KEYON 0  q% y6 p  g: p# {9 m' B
  22. #define KEYOFF 1+ F1 i9 C9 j: o* y2 |7 R0 O1 M
  23. #define KEYPRESS 0x02  //单击7 `9 T( f/ z9 F# C" Y# C$ {

  24. 3 d' A" v! b; ]$ {
  25. #endif
复制代码

" Q& |# y; l; C2 k! I' l
相关功能:
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,则为启动相应功能。
// KEYB12,PB13,PB14,PB15
void key_init(void)
; y' G: ]8 j1 F' w  S{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
& f0 o* n( Y' @, BGPIOB->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¡£
4 L7 o( ^1 I; G7 CGPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
7 _1 ~' D! ]5 k' FGPIOB->ODR&=0x0FF0;" b) E4 P  _  U1 e& P/ E- I
GPIOB->ODR|=0xF00F;
# S5 h9 K2 q% x7 o2 O1 c9 Y5 L  H4 V5 u; P
for(m=0;m<keynum;m++){
  J' X3 E$ f/ Okeycnt[m]=0;. {: l6 s# z% i, J
keystat[m]=0;( R6 ]8 \/ t; n/ Z, P
keymod[m]=0x10;
3 n5 P2 D2 R1 M% z1 y}, S, |; G6 G% S* i! j
}
//循环扫描,在定时中执行
) s  z+ B  p# tvoid keyscan(void)& E3 Q! t  `2 I$ K9 m6 t4 Z
{- B- q$ a  P3 `$ }4 t9 |, w
    uint8_t k;
9 K2 m% c9 G0 Z1 m: ]8 _    for(k=0;k<keynum;k++){
( q) l* h& r% Q$ R        keyone(k);
1 e( v( {, O6 E% `/ U2 I5 o    }5 G- I/ z8 Q% y5 z4 k1 r
}
//识别规则
: L6 a+ Y# \+ t3 \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:
+ i* V; W) {) g+ r: fif(KEY0==KEYON){
+ W+ Q* K2 P% K/ W+ S: I    if(keycnt[nkey]==keypress){8 G  N! ?- n, i, ^
     //   keycnt[nkey]=0;//长按视为反复触发按键。
6 q2 f  M) U3 ^+ H  q        keystat[nkey]=0x02;, g$ ]; b' X4 M+ \7 b8 w! |
        }else{
8 |$ A- Y) U0 w$ d# f3 W        keycnt[nkey]++;6 }: t4 p9 X7 Y2 P$ m$ }* f
        }
: r) Q- y* k9 `5 D+ H2 d0 V! ?* T# R}else{9 ~' k6 {& @  _
     keycnt[nkey]=0;: G4 O/ C8 C& t4 z
}- e1 T  ~) k2 P+ `1 w5 F
break;
…………
}
//后续动作,在定时中执行
0 V# G3 Y3 ]; Z4 ]0 M# ?void 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
: l  e5 `1 H( ]( r9 ?; nkset0();  //要执行的动作
8 o9 R) m- f7 q+ P& Y" e}  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
- _' C( W+ G4 ?, \led_flush(2);
( n# [: b6 \- Q' _9 v2 |9 W# n( \led_flush(3);
/ }' m/ Q0 K% W5 e2 d+ b1 J}+ ^2 T) g) h; @. E. _, A
}
4 `  f7 P' g4 s' W
赞 收藏 评论0 发布时间:2022-2-5 23:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版