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

【经验分享】stm32按键识别

[复制链接]
STMCU小助手 发布时间:2022-2-5 23:00
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。
关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。
前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。
本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。
思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。
对于具体应用,应进一步人性化。
部分头文件:
  1. // KEY:PB12,PB13,PB14,PB15;PB3,PB4
    " y7 x7 A- B- ]& m
  2. // KEY On:0 ; KEY Off:1 低电平触发
    3 g& ]  r+ ?+ @! o
  3. $ m5 A6 ]* x/ c2 J3 U6 `
  4. #ifndef __MINIKEY_
    5 ?8 ?3 l& x  i2 g
  5. + |8 Y( {5 B% P4 B* ~$ o
  6. #define __MINIKEY_
    ) G/ D8 s1 q$ m3 a
  7.   [7 n8 P9 l# d$ p, N. Q
  8. #include "stdint.h"
    9 l( I+ n5 L8 L
  9. #include "miniled.h"/ l$ C& H  f0 U# M
  10. #include "miniusart.h"
    2 x$ z* X) j! ]: I. b" v
  11. #include "minirtc.h"
    0 ]3 S* x+ T% g4 j* G  q

  12. ; L, G9 L2 X) d: Q& ]
  13. #define keynum 6 //On Board KEY NUMBER5 D* x- \3 k$ ^, u7 W! l! ~

  14.   _2 e! f" `- S' P  n, S
  15. #define KEY0 (GPIOB->IDR&0x1000) //PB12
    9 }2 M$ `4 Q6 z
  16. #define KEY1 (GPIOB->IDR&0x2000) //PB13," ^* W2 ?: Q% C& Q+ K
  17. #define KEY2 (GPIOB->IDR&0x4000) //PB14. B% ~8 \( S% ^, \
  18. #define KEY3 (GPIOB->IDR&0x8000) //PB15% S$ x, q' g$ {5 \1 _
  19. #define KEY4 (GPIOB->IDR&0x0001) //PB0
    8 e' v, I3 ]# g- K9 c
  20. #define KEY5 (GPIOB->IDR&0x0002) //PB10 a' L5 H) I  u0 p" g! X7 D
  21. #define KEYON 0( o4 X$ d  S! V- I2 o- U" h  Q3 W
  22. #define KEYOFF 1  M5 }( }) j6 q" L: @! k2 n
  23. #define KEYPRESS 0x02  //单击
    8 }4 r( z8 j% r% f8 s/ ~

  24. . V6 [9 W$ B1 R( E6 E& f
  25. #endif
复制代码
2 d% X: j. H& e' ?4 p
相关功能:
uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。
0 f; e4 T4 a3 {. N' B- tuint8_t keycnt[keynum]; //计数器
. s( I+ D! C5 B6 l8 \0 F* D! Zuint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;
5 q* @0 ^  [' b  k, Euint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。
// KEYB12,PB13,PB14,PB15
void key_init(void)
) g4 T  Q# w3 b" v9 O{$ J# O) f' p, b7 ?
uint8_t m;  p3 Y1 |* ~1 o8 L
RCC->APB2ENR|=0x08; //enable PORTB clock! ^9 g# ~# ?, @8 p- I% U/ I" B4 T
GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£
, M. F6 Z6 `' w$ k5 IGPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15
5 F3 R! D% |1 GGPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£* i9 b9 }- F. F0 d0 b7 L! i& Z2 r2 m
GPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
' k9 Y0 p3 K2 |9 o5 k: c8 }GPIOB->ODR&=0x0FF0;
$ [0 e5 L% D/ @$ `2 {2 `( K  zGPIOB->ODR|=0xF00F;
% W8 R: N- n% E5 m
1 ^' |$ K) z* {0 ^3 b' w* kfor(m=0;m<keynum;m++){
- {; B* \& c& M0 g+ b+ Z) qkeycnt[m]=0;, t" ^7 C$ F$ P; n
keystat[m]=0;. K1 o3 _  r' M. N
keymod[m]=0x10;8 E( {' r3 n4 f
}/ E" ~- F% v/ B1 m
}
//循环扫描,在定时中执行- T9 A1 V# L/ [  P2 N8 f: I$ }) o
void keyscan(void)
0 X$ {! @) Z, J/ y$ d  V{# B' A& Y# G) E3 B, ?$ R: [9 I* n
    uint8_t k;" J* p, ?  S" p# ]
    for(k=0;k<keynum;k++){
, L3 u$ R$ |$ h  v  Q; j/ W        keyone(k);% D' \3 s' \% n) I- E3 G* A
    }
0 W) U, t6 U+ t}
//识别规则
& o4 L2 j' M  f% dvoid keyone(uint8_t nkey)2 \" C0 e+ }  `) h2 S: T5 g
{$ E  B5 o% u, z* ^( J
switch(nkey){/ M& }/ R9 z) i9 F* T1 I8 E
case 0:
0 d9 V" S8 r" t: A: @0 ]" Sif(KEY0==KEYON){# H4 z& {' ~! M8 k+ Z! l4 x
    if(keycnt[nkey]==keypress){
% m3 P* q) `" @' g% A$ L     //   keycnt[nkey]=0;//长按视为反复触发按键。
( O7 ~! L5 j, W6 P* ?        keystat[nkey]=0x02;( y: C- F" ]' F: F  ]
        }else{
/ B% N- I8 H3 n. b9 z1 r        keycnt[nkey]++;7 T* g, ^' K8 g/ e# d
        }
( P( L* P1 F# p( b7 r7 m1 G: i}else{3 i+ |2 I" Q, k; ~/ r
     keycnt[nkey]=0;( S! b; Q; U1 i, v  [9 H) n9 |
}. I4 Q3 O) E) ?& i4 }3 {5 @2 p& ^- c: D
break;
…………
}
//后续动作,在定时中执行- X+ ~2 P3 c/ ?- O  I, `
void keydo(void)* l+ W' I2 h3 }; L/ I" n
{, `$ a6 A" a7 Z' _% V8 g
if(keystat[0]==0x02){
, D( }( i8 O! a* m. \keystat[0]=0; //reset key after done
0 s! t! ]" t: K2 i+ a  I/ Pkset0();  //要执行的动作. D8 U" ?5 E/ |' W& C; B
}
- p! f  B8 s* z8 L7 j……………………* _; m. R( i% f
if(keystat[5]==0x02){
  E( z% `! S$ H! r: \( zkeystat[5]=0; //reset key begin done
) ^: P: i( [! M' p$ nled_flush(2);
! \' k1 X. s$ o  N: Cled_flush(3);2 x/ U' v, `- }/ ]; h+ ?
}$ t: l( o" u9 o4 N
}

8 L/ p9 B" Z( ?+ B$ t
收藏 评论0 发布时间:2022-2-5 23:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版