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

如何解决STM32按键长与短按的问题

[复制链接]
攻城狮Melo 发布时间:2023-3-17 17:30
Stm32 解决按键的长按和短按
6 F& ]3 y& Y6 [废话不多说, 直接上干货 注意:本文是采用Stm32 HAL库编写, 可以移植成库函数, 其原理是相同的!!!!
+ O4 ~; X& ~( d* f2 g5 i( T
第一步 : 首先在key.h定义几个变量
  1. / 按键的键值" d& A/ b6 E1 X, f9 ~% F
  2. #define KEY1_Press 1
    & H: X" ^' ]5 I* H# [5 `
  3. #define KEY2_Press 22 r' d$ C+ u, g. ]7 P" Q% I- l2 g
  4. #define KEY3_Press 3& n$ ^( F) O- J
  5. #define KEY4_Press 4
    4 ^7 |9 h- ?- N1 W2 s

  6. 3 f$ ?: D, J8 W" d% d0 r
  7. / 读取IO口的电平) b; K) h/ V$ L8 h4 `0 W8 D
  8. #define KEY1 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)& H" z9 [& Z1 y1 G* p
  9. #define KEY2 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)) _" g3 l& Z8 c. L
  10. #define KEY3 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)
    9 a9 k7 R# C2 R+ r. {) u
  11. #define KEY4 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0). Q' m5 S( c. q% v" X4 v5 y
复制代码
5 ]; y" |' y' K5 q/ J( |3 i
第二步: 在key.c 中编写按键扫描函数6 z# e' D  w/ a, Z3 G, |" T
  1. <font color = blue  size   = 5> 编写的按键扫描函数, 只需要返回键值即可, 不需要我们判断按键是否松开这些情况
    5 l* j( C" }+ w2 u+ y
  2. . A4 m- n. i: h2 h3 S
  3. uint8_t KEY_Scan()# W  f) g8 R7 q3 q4 M& e
  4. {
    7 F6 u) P3 t% {* Z$ h2 V$ h
  5.         if ((KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0)) 判断是否有按键按下; i  z  ?1 U# V  |8 q
  6.         {
    " @# P: a0 o0 {& x3 K7 M6 h
  7.                 HAL_Delay(10);  消抖
    3 c% ^* M5 v# [
  8.                 if((KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0))/// 判断按键是否按下7 H" g! ?, H% p/ m3 A# r! ]  ^5 w
  9.                 {0 v, J7 r7 h, \) E7 k. d
  10.                         if (!KEY1)  return KEY1_Press;/ 返回键值
    * g# M: x7 }2 X3 M
  11.                         else if (!KEY2) return KEY2_Press;7 i$ Z1 W# L- `' |# Y( f1 J9 V& ]
  12.                         else if (!KEY3) return KEY3_Press;
    1 B1 w% _  i" k5 o/ Y( b  W
  13.                         else if (!KEY4) return KEY4_Press;* s7 v- I- M$ z: n8 v1 U
  14.                 }' E% z8 |, j+ L, j2 }
  15.                 ! d# |  r" T6 W- N' `) E2 h$ q, Z
  16.         }1 \2 |/ p" u# ^8 k/ Y: e: y
  17.         return 0; / 如果没有按键按下 返回0* p! O( j! I9 C5 b
  18. }- D/ Y+ {8 Z6 E/ W0 S/ s$ m; l
复制代码
- F( [/ Z0 G- I2 D) ~9 L' m
, I8 i' U2 \3 k1 p& y& h
三 编写定时器(1ms)
* h, V- s! u0 w! U" H; A/ z2 |这里我们认为 当按下按键的时间持续 0.8s 认为是长按 !!!!, 需要开启一个定时器和2个记录时间的变量(key_last_time, key_now_time), 为了快速配置, 这里我们使用 Stm32cubemx 配置 我们还可以设置长按的时间来设置不同的状态, 这也是实现仅一个按键可以实现控制多个状态的方法 我使用的板子时钟配置为80MHz, 配置 1ms的中断,( j0 b' q* X, g; a" h2 f) H
% y% q5 z9 V8 j8 \  b  ~
e1591aab2a9c4328a80b9e9bf769cdb2.png 7 t- a/ D5 w) o& e! N4 k! J3 i* |$ Z7 o

; H1 `1 O( |' s  h" y2 p
68b29802ea884decbea7e2b31eda819a.png 7 O0 |. a/ |1 Q! P, T" l

' g  z' _- L; s! q. U+ |3 v, \8 A
6c3a1981ce9a42c8a884109d621897d0.png
. g$ S( p; K! y
4 B& V' j- P' W; r  i4 S9 {
接下来, 我们只需要 让key_now_time变量在这一个定时器中断里面加1即可& m/ Y7 u8 k0 e* B* x" s! H$ q. M
! P5 T/ N1 h( m2 C
868249bc1ace4ff7b04497ffdc6f4bc4.png ( B) t4 l" }( M$ q  t

. v; K4 r5 z$ S5 q
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)  1ms的中断
    , r2 H) j: t: M
  2. {
    2 b1 q% n- ?  f/ A7 g; Z
  3.         key_now_time++;' i* j) `  C' a
  4. }
    7 ]) l3 ?' G+ S5 }3 z, k6 _
复制代码

: _, u% P: I* J% C% l. c6 t3 p四 编写按键处理函数5 R( [  V; h! n- M2 u3 {# k
3 R( c) j: Z9 c
35745434387344c59c6ec20cfd09d83c.png . K* \$ Q2 e9 _( ~/ M9 e
, D# x) ?) ?* Y$ I/ s
按键处理函数:
8 [0 e) P/ G7 r$ M
  1. void Deal_Key(void)7 ]9 [" d4 K* E) J" T) j) U. z; N
  2. {( G% _8 ?! ?' Z% g6 D# @
  3.         uint8_t key_value; 3 B4 R9 v% m3 {- c) W0 ^
  4.         key_value = KEY_Scan(); 获取键值
    7 v1 J  G& ^% p. O& {
  5.           u1 R1 |- c2 F
  6.         ( j$ ]' s2 A3 ^, G
  7.         if (key_value !=key_old )
    & {2 e9 z7 V( m: o5 G: S
  8.                  与上一次的键值比较 如果不相等,表明有键值的变化,开始计时
    & y$ q! ~& c& Y1 r0 R7 X) ?5 l& u
  9.         {
    . P( A; H- ]" m1 E
  10.                
    ; O+ f: k" g" F1 A: }0 t7 n" c
  11.                 key_old = key_value; 更新旧键值
    $ k! y3 A2 S/ O' U, k( e
  12.                 key_last_time = key_now_time; 让2者相等,
    , I6 _9 m: x# D7 _  r$ I
  13.         }. G( o! A2 \9 {1 `; w" k# D
  14.         else
    ! B2 d' R' m6 F& V4 ~
  15.                 key_value = 0; 如果没有键值的改变 说明没有按键按下或松开9 r7 |) D: W: I2 g
  16.         $ K" h% W: Z' t, r
  17.         ( M% G- I6 c, E2 A8 N7 S6 ?6 P" q) r1 L
  18.         if (key_value)/ 短按处理 % \1 @6 Z' _5 P5 a! q; r! n, I( F  G& J
  19.         {
    9 y/ f3 T0 k' P& V- \& Z5 ~7 p, \
  20.                 switch(key_value)
    " `6 N3 p1 Q1 Z* Z
  21.                 {  V9 p+ A1 f4 U5 k
  22.                         case 1 :   printf("KEY1 按下\r\n"); break;2 ~0 F& E' G2 o2 }  R# D8 |
  23.                         case 2 :   printf("KEY2 按下\r\n"); break;- f, E3 n: ]9 j* y8 ?; N; d
  24.                         case 3 :   printf("KEY3 按下\r\n"); break;
    $ t" B' f. _/ w5 k/ Y
  25.                         case 4 :   printf("KEY4 按下\r\n"); break;, v* A6 Q( \6 R' D+ }# X
  26.                 }! X4 c# }3 r2 j5 j/ l
  27.                 key_value = 0; /// 该语句可有可无, 为了保险, 最好加上% d  D3 E- ?- S' s( D- A7 Q/ T* O
  28.         }$ E; S! O/ L4 y  c
  29.        
    # Y& {2 }/ N7 L' _; g5 X1 O0 N* t6 p
  30.        
    % I( W1 `% ^/ C
  31.         if ((key_now_time- key_last_time > 800))/ 如果按键按下超过0.8s 判断按键& Z0 y5 D* q. b
  32.         {
    6 w' K) i+ f* x/ t2 j" T4 ^
  33.                 if(key_old) / 注意 一定是判断旧键值, 因为当按键一直按下未松开时, 即key_old == key_value,3 n7 ~7 Q/ D( ?" t
  34.                  此时key_value 0 ;8 p. q! Z& v# ?8 A4 ^7 c
  35.                 {
    ' N4 g; B( @4 _! v6 b0 v
  36.                         switch(key_old)# e" ]( [4 q7 p4 g( W
  37.                         {1 z, H& b) w, P1 H
  38.                         case 1 :   printf("KEY1 长按\r\n"); break;" ~+ a- N( n4 J' F1 N, N
  39.                         case 2 :   printf("KEY2 长按\r\n"); break;
    / S0 u  t) p& w
  40.                         case 3 :   printf("KEY3 长按\r\n"); break;7 K% h- d* p: X4 n0 c2 o
  41.                         case 4 :   printf("KEY4 长按\r\n"); break;! M& q) \- _- V4 f( K9 ]
  42.                         }, ~  e( _4 y* c+ l( c, |" ~7 Q3 c
  43.                 }
    1 @$ j2 k. @6 i% e  E
  44.         }
    ! ~: c( U. E/ h* _
  45. }1 K* {( e+ J9 p; d  L0 c5 S  g  y
复制代码

0 S8 E& y. M% [$ B# u  R- M4 P% ]接下来, 我们只需要把按键处理函数放入while(1) 大循环中即可!!!!. D7 B6 ^( F& q% e7 {+ X; T

9 S- h( Z. Q7 N
edf053d1fdda48619f88d3ec34db8fd6.png
3 A$ H5 d- W4 }

. q* p8 d1 m. C- c6 P# Y6 S, e————————————————  q, C) C( }5 G1 H/ x% z
版权声明:YELLOW_YELLOW_YELOW
* E- b/ ^3 q3 Z/ k- u如有侵权请联系删除
8 K& s) }3 I1 u- W
, G8 N& D4 ]/ |
赞 收藏 评论0 发布时间:2023-3-17 17:30

举报

0个回答

所属标签

相似技术帖

官网相关资源

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