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

【经验分享】stm32按键识别

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

  3. 1 o- z. ~0 @9 i$ }' y
  4. #ifndef __MINIKEY_
    : ^! F% n$ g1 j- z; H
  5. + {# m: O7 |$ O$ A! x) K+ n
  6. #define __MINIKEY_3 H4 J& Y  A: @- o% X% P# e

  7. 1 y4 V$ N4 @& A! g- S/ T
  8. #include "stdint.h". c6 b: y6 Z1 }* J" n
  9. #include "miniled.h"4 P8 N* l1 x7 b; Z: `; M
  10. #include "miniusart.h"
    & K5 o' S( _5 _1 V
  11. #include "minirtc.h"
    * t2 v* n3 y8 w" ?. V

  12. ( |+ Q! B. z& n" l& J+ P9 L$ }
  13. #define keynum 6 //On Board KEY NUMBER
    " \4 |+ X- j8 z+ n2 A! y
  14. ) ~& a; M* a/ v! q" D$ J, u% s
  15. #define KEY0 (GPIOB->IDR&0x1000) //PB12$ I7 E# h. J; F
  16. #define KEY1 (GPIOB->IDR&0x2000) //PB13,
    9 |0 l8 @4 M# x: E8 Z
  17. #define KEY2 (GPIOB->IDR&0x4000) //PB14
    0 n- w' c% ^' N4 @6 o% z7 ?
  18. #define KEY3 (GPIOB->IDR&0x8000) //PB15
    * R! S/ v9 @+ |6 k" s
  19. #define KEY4 (GPIOB->IDR&0x0001) //PB0
    ) H* e, E5 {: W
  20. #define KEY5 (GPIOB->IDR&0x0002) //PB1, E7 S( f8 @, I
  21. #define KEYON 0
    0 v. k# E- ]6 p3 [
  22. #define KEYOFF 14 o) ~5 s2 f5 i4 J
  23. #define KEYPRESS 0x02  //单击
    ) Q4 a5 v9 @" X" a4 Z) f0 L- ^
  24. / K$ I' e9 Z/ Z1 _1 a, O
  25. #endif
复制代码
. n$ c4 v- r; O
相关功能:
uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。
+ z8 H" z& s7 buint8_t keycnt[keynum]; //计数器
4 s) U, H4 O6 O; K$ n9 ]uint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;
# O0 q8 D% V- u, @/ L% kuint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。
// KEYB12,PB13,PB14,PB15
void key_init(void)
' A  ^7 ?* a8 Z2 c4 g0 x{8 F& N. \% G3 ^" I; q# F2 Z9 N
uint8_t m;
# N+ b& y7 t3 n( g1 ^7 ]8 C) |6 JRCC->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¡£
' _. H' A% u7 o! S1 iGPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15
4 [. {: g9 }/ s7 H' E, QGPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£
; g( I) V* K4 Z/ E, _0 c* R% eGPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
4 Y" j! n. Y6 r" fGPIOB->ODR&=0x0FF0;
5 I( L0 w, M1 n9 ~% dGPIOB->ODR|=0xF00F;
  ^( j( x# {+ C5 H, {* f
1 n- }, A, ?, R" @# Vfor(m=0;m<keynum;m++){8 {! i- b& l/ I
keycnt[m]=0;
* T0 @- t( i6 h* Wkeystat[m]=0;( _+ D$ j3 c! O* A
keymod[m]=0x10;, e0 }; K- ]1 t6 K  F% T
}
* [1 y/ X1 h" [5 |7 T- t+ b% ?}
//循环扫描,在定时中执行
3 ~. X3 }/ [- R' s4 ^void keyscan(void)/ j, @) ]" j( H) d/ u
{
3 j; Z7 }0 }, p2 S! m/ B6 c    uint8_t k;" M( l( H5 v, f: w$ G- A0 g
    for(k=0;k<keynum;k++){
6 s( ~7 j  R+ I- u! `        keyone(k);3 t3 G7 r/ _' l' S5 u
    }
5 A9 h, c5 \* G( [9 @6 b) Q}
//识别规则
9 I  l4 w1 ]" T6 X* @2 g6 j. qvoid keyone(uint8_t nkey)2 ]" ^4 O1 R7 a
{
) M2 _1 F# E2 g$ r4 u6 `; C7 W6 Cswitch(nkey){
, H' M% N6 @& K1 w1 d  m. ]case 0:) l7 k' Z3 P4 I( w$ S, j- g
if(KEY0==KEYON){
9 L& W/ ]+ L8 \9 w( g    if(keycnt[nkey]==keypress){7 u: N/ r8 s" @: g) v2 N
     //   keycnt[nkey]=0;//长按视为反复触发按键。
- a) m+ a/ m" L- `0 d& n        keystat[nkey]=0x02;" E- c8 c+ B$ s' \
        }else{
2 Z0 }. i9 R3 s' _. B        keycnt[nkey]++;
1 F) G; a' j+ K& z        }8 [" Z8 ?5 Q1 a1 `* Y+ l2 |1 G
}else{
; v8 q0 B) o% ^9 G! R% Q3 R     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)
! A6 ~  O; Z/ x3 N, B, }; \{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();  //要执行的动作
' F& q1 A: U; l) H) K}1 X+ x/ o3 y7 f3 q3 G. D
……………………3 w) ?! E' j1 V. @* f* z
if(keystat[5]==0x02){
* D& L" [9 M* f; f, w2 `. ?keystat[5]=0; //reset key begin done4 q% h! \& z: u; P
led_flush(2);
3 k" {* T3 x2 }( sled_flush(3);
3 R! l4 B  B% G* T& D. k9 o0 _}
& g$ @2 n/ V( U- F2 j4 l}

; j4 Z7 [" I- v0 }" d2 Y( c* ]
收藏 评论0 发布时间:2022-2-5 23:00

举报

0个回答

所属标签

相似分享

官网相关资源

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