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

【经验分享】stm32按键识别

[复制链接]
STMCU小助手 发布时间:2022-2-5 23:00
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。
关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。
前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。
本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。
思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。
对于具体应用,应进一步人性化。
部分头文件:
  1. // KEY:PB12,PB13,PB14,PB15;PB3,PB4" E' H* G$ D2 j/ h
  2. // KEY On:0 ; KEY Off:1 低电平触发3 C6 G9 u( y( ]' ]& [3 X

  3. 9 b: ^/ }: I: O& @- \
  4. #ifndef __MINIKEY_2 |( i  `0 \: g+ {- Z# i
  5. " ^8 n3 K2 W0 I+ S1 ~0 q
  6. #define __MINIKEY_  `$ o9 b3 i$ M% ?2 u* ~

  7. 6 I6 R$ ~9 l) q% P! ]8 u& {# J
  8. #include "stdint.h"0 {: {  ~6 w1 M
  9. #include "miniled.h"  Q$ U, [7 C2 A; _  _
  10. #include "miniusart.h"
    * c8 M' t) G+ R
  11. #include "minirtc.h"
    : M+ n. [- p0 E( x
  12. + |& t  G# @3 \( d  N0 \
  13. #define keynum 6 //On Board KEY NUMBER
    + B0 u1 r% }" r! g* c2 c' X% m/ f
  14. 6 a5 y$ T5 ?8 Y4 E% q$ [, b% y1 `( }8 F
  15. #define KEY0 (GPIOB->IDR&0x1000) //PB12
    ( }7 V! q$ r1 S" N  ~, x
  16. #define KEY1 (GPIOB->IDR&0x2000) //PB13,
    $ k( f- z) ~- B4 ~1 D/ M1 u
  17. #define KEY2 (GPIOB->IDR&0x4000) //PB14  T( v- o$ z8 [
  18. #define KEY3 (GPIOB->IDR&0x8000) //PB153 ?6 S* u+ r% W3 I
  19. #define KEY4 (GPIOB->IDR&0x0001) //PB0
    * r0 [' j7 y: Q' B
  20. #define KEY5 (GPIOB->IDR&0x0002) //PB1
    6 e  f- D: `* P
  21. #define KEYON 0
    3 U, a7 d9 n  ?4 n1 w/ d
  22. #define KEYOFF 1
    8 c, U* O( Z, r3 g! j
  23. #define KEYPRESS 0x02  //单击5 d0 x# Y  f; @8 r9 S9 v

  24. 9 L9 d# h1 o8 O: n# X$ T+ p
  25. #endif
复制代码

' l8 j0 c4 \2 v& l* l
相关功能:
uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。+ G/ }8 a6 k/ P4 j0 g; F& E
uint8_t keycnt[keynum]; //计数器
6 B0 x4 C& |' o  vuint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;
: c6 I- x1 a; s/ \0 [uint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。
// KEYB12,PB13,PB14,PB15
void key_init(void)
! |" ~6 Q) e# N" s) h; m* E& i{
. U' e6 c3 H! G6 f$ nuint8_t m;, u2 z3 L, e( ~
RCC->APB2ENR|=0x08; //enable PORTB clock9 y" J3 `6 y9 I# V
GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£- [# g* R2 o9 Y) p& P+ }
GPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15" r  b8 \+ T: M# u
GPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£
& d& I! e6 r$ v7 z! |4 b9 Z9 C) y( yGPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
- O! }* _! N$ U$ q: U! P' g/ qGPIOB->ODR&=0x0FF0;! V% H5 x1 H$ m& I! \
GPIOB->ODR|=0xF00F;( F5 ~8 h- I1 v  B
# {2 o' m. _' ^. D+ G, `1 w
for(m=0;m<keynum;m++){
/ Z! F0 T6 y% }' k( z5 A! ~keycnt[m]=0;& g) V) K3 e+ T$ s# L" A
keystat[m]=0;; Y  e* r; M7 X" Z# f
keymod[m]=0x10;) O' ~3 h; h3 ~8 N2 D4 e1 Q
}( z* ^1 I1 I- I2 b4 B
}
//循环扫描,在定时中执行! M% r0 X' j( S7 z, N9 ^$ m/ A8 b
void keyscan(void): x2 F! b- S, k
{* u1 n1 e  k  @0 k
    uint8_t k;
) {6 g' |: C3 Z* B0 J    for(k=0;k<keynum;k++){
$ j& B- T  u+ |2 d        keyone(k);7 ^2 @% o. g" V; R3 i7 A% ]
    }! ]) f" b2 h  j) Z
}
//识别规则
; H# t% Q2 Y( {+ W9 Z& e. ?void keyone(uint8_t nkey)
) E* O/ o# ?8 z' n$ c6 U( n{+ C) a0 M( Z3 ^0 }+ c  q" ?
switch(nkey){6 R; t6 V7 o; q7 z
case 0:
% ]8 h3 ?) ~5 B- {if(KEY0==KEYON){. y: u& V$ `+ t  B
    if(keycnt[nkey]==keypress){
6 M  c# p& Y( V; V6 V; S     //   keycnt[nkey]=0;//长按视为反复触发按键。
4 M5 S5 ?4 u; ]- x        keystat[nkey]=0x02;  j9 g' Q( {! c4 i1 W+ _0 \
        }else{* Q5 E; v% l6 |+ J9 C9 [; s' [2 a
        keycnt[nkey]++;) s, E' Y4 e/ ]4 Q. }  f! Z
        }
+ i9 u  l5 h6 \6 n, u}else{
5 o, D/ g, L- Z+ N8 t' L     keycnt[nkey]=0;$ j, A- z2 v+ k: n/ i5 I5 g
}
! h( _  {+ r) o4 E! K" ?) F9 nbreak;
…………
}
//后续动作,在定时中执行
) F* q6 p7 O6 f! H: |void keydo(void)
% e8 P# c3 l! W) C$ h& h+ B{- D, X! M. A! H: y+ N
if(keystat[0]==0x02){& }; e5 M7 B6 E) w3 S+ N
keystat[0]=0; //reset key after done7 D; I" t$ a5 h% d* l
kset0();  //要执行的动作6 s: A- g2 u% y7 d/ y) h
}" l* X, x! x* k1 {8 [1 C
……………………
0 a# |) h( ~3 D: @6 S. \0 N0 ]if(keystat[5]==0x02){
8 B" X" B" V; f1 N1 M7 w8 skeystat[5]=0; //reset key begin done1 g" ^! ^% J0 j  H$ k
led_flush(2);
) A8 q( J/ g  S8 E9 u4 kled_flush(3);
; p. J" Y* U* L( X7 {7 _}
" B6 j0 Z" r$ B; a! V}

# x' r8 t, r5 d( p* ^/ K
收藏 评论0 发布时间:2022-2-5 23:00

举报

0个回答

所属标签

相似分享

官网相关资源

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