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

STM32G4系列MCU学习笔记:按键模块

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
. y, Q) ^' T6 L4 F
: D5 J8 j) q/ G前言
* E2 @  a( p% j, \1 ]" e我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。: ~* Q" G9 H6 ^
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
2 a3 E6 Y5 g4 u% U8 R由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~  ]; v( L2 U% C1 t- Z
# c+ g" l& ?8 _3 S1 C/ p4 h5 T7 v3 I3 p

  S% Q, J. ?* j9 W先放一张开发板的实物图,它长这样~; U$ u" F  \- n6 ~: [$ }6 b
15.png
一、硬件操作1 \* H6 w0 V, A$ v" r, @. j
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
; p$ q0 F5 I# o9 Z8 P; ?3 U2 m9 \: \7 j# H0 |: k8 z

$ m; o- l- Y" o" ?, l& A1. 原理图
7 N8 q; z8 ]$ a/ C2 i4 ~
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。, o6 ^6 _5 L8 T/ g
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)- ^( |, e6 o0 n6 N: [( z) `' ]
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
. F& `6 n& [0 y) `9 h; m  E2.按键相关的IO口:PB0,PB1,PB2,PA0。
7 U( {5 d8 ^7 o& u/ G, L: H; n; M+ @* Q# I

" {0 M4 a! D. @2. 硬件分析( x+ u9 [  Y. c8 g: Y3 k
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。6 N: x8 @4 e( E% N$ ?  d

/ [) h* Q6 W$ u. M0 p* Y5 P8 O; g- [
& e, v+ @/ F$ ]1 f" Q- y# k+ ]9 h
3. 初始化代码
: X/ V; n; A$ M8 i
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */7 q" N+ y' s* x1 t+ {8 g6 V$ q/ b
  2.   HAL_Init();//使用默认配置即可8 K- {( u9 [0 K( M7 }
  3.   /* Configure the system clock */+ O7 A0 d: ]/ E; J
  4.   SystemClock_Config();
    ; C% a5 K5 F6 t! Z% O
  5.   /* Initialize all configured peripherals */
    ) T& p6 w3 }/ ?, g( [/ ?# K" w. L
  6.   MX_GPIO_Init();
    9 b5 i3 r9 \1 y7 T! P( ?
复制代码
(1)时钟设置0 Q4 x# v5 x" O% Z
这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。0 o/ B: n$ P- ?, H' W7 N+ o
  1. void SystemClock_Config(void)
    % J# e' B  O# L! A' U
  2. {* W! [2 C" K" @0 b3 r5 e
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};" W/ b; {+ g4 P# c" c4 u$ I5 d
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    ) `, g" O& ~" m1 U* C  Y! p) W- f
  5. 0 T& s( W+ ]# D- J0 y  y
  6.   /** Configure the main internal regulator output voltage
    ( y! u& [6 p2 z' y
  7.   */: r  U) e% a6 q: O% q& d: X- ~
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);+ {7 r9 s4 i2 w) x
  9.   /** Initializes the CPU, AHB and APB busses clocks
    * d6 S2 K& A* E& l9 [/ k
  10.   */
    ( s3 p' D% S; E/ @5 T3 z
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    & l: ]3 H+ B# {6 U3 W; B
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;, k- E! c% N2 R, O3 f
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    # X  ^: ]& t# r& L! O! w6 T
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    5 ^0 `9 b6 ?/ H- t+ a2 `7 `, _" X
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    ! I" @! c/ F) J5 f. A+ T/ ~; s
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    ) e0 Q. ?, d7 Q  V
  17.   RCC_OscInitStruct.PLL.PLLN = 20;3 U9 k& ]* [2 h: C" A
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;8 g# y) n% u( h
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;3 K$ S9 }; G& V- D
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;3 j8 k- e5 e4 [( h) J  Z
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    $ u6 y" r3 A+ B1 K# w
  22.   {+ ~0 i. l. D2 k, f: S
  23.     Error_Handler();
    0 v5 H9 J8 R* h7 r9 D( d
  24.   }. L+ }+ S. d6 _* l6 L, @4 l7 y
  25.   /** Initializes the CPU, AHB and APB busses clocks
    & Y& d/ i9 n- p
  26.   */4 i: c  V3 V8 S' `' j
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK6 Z: S' \" L) \% d% O/ c
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;' I3 ?* |: v6 ^6 b$ o& U8 @
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    6 d2 n7 s; G* B- n1 e3 `3 n
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    , B. F% B* [% k9 k8 h
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;+ |6 x7 r. |. I; S9 d4 X
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;- N" P( X/ B0 V3 |
  33. 2 z7 c6 M3 j: }. n- S' u1 `
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)" o5 \' ?% D% v  q3 U" l  t
  35.   {
    8 g1 q7 W+ `$ O6 R7 {' q- c2 _1 t
  36.     Error_Handler();9 X: F% ~9 w/ ]  `$ O1 @
  37.   }0 l! x% o3 y3 ~6 R. b* I# n
  38. }
    : e7 I, T8 O* k+ m
复制代码
(2)GPIO初始化
4 I9 u! |& T# p3 w2 t6 n
  1. static void MX_GPIO_Init(void)
    4 `, a' [: `: \5 w$ _  J: S3 i
  2. {& t+ r6 |: l6 Z2 }* S
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    / L  M7 ?  x5 i0 k6 `3 X: c
  4. / o$ C! V( k% Z& G* u: y. A3 V
  5.   /* GPIO Ports Clock Enable */
    % X( l+ R" k- E  h! O- c" P
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();2 B  w; J- s# |) {8 a- K
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();' C; \8 r0 J9 e+ b) r) P
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    / y3 o0 P: J( D9 G4 w
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();* _+ q) S& W8 S: y' N
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();* x% F2 D% X" g% w2 T$ E
  11. , s! w2 X8 X6 R2 L
  12.   /*Configure GPIO pin Output Level */8 i3 x) _4 H: X0 E1 S+ M9 n0 T7 Z
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    1 j! f% k- D6 N  U) |) I
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);) ~" Z  b1 }1 r2 A- E0 w' v( {8 e
  15. + w7 [; a; m- t
  16.   /*Configure GPIO pin Output Level */0 o4 K& i1 W3 v! j& X$ }
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    5 P5 N  z" n) p4 B- ]
  18. + k# q) B, M7 o' ?
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    4 i: i5 Y$ V3 U" E; G2 N" s4 S
  20.                            PC9 PC10 PC11 PC12 */$ Q: ]9 Z- j0 f) q! G
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 4 T& }! T& l4 l; p
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;% ?8 G4 a" y' A* L. P
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    : x8 o" Z/ K1 x) P( k; Q+ H1 _
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;- B. Z" l' G4 j) h' ~) V" s
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    5 E. S* U; x/ ]( Y
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);7 Q) r7 r( q9 u% Z/ s- S

  27. + p8 {9 @7 l: \4 b* s/ |" B
  28.   /*Configure GPIO pin : PA0 */
    # \1 G5 Y' U& b9 Y& ?# x  j/ j
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    " i+ J: @9 F, x; H8 i3 m% O6 |
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;% I" Q$ H' k, d) w0 C' U8 U
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;) T" ]8 Y5 n) Y! `  O9 r9 |% t0 F
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    4 K" V) A" {6 }3 d
  33. ! ]( b( R% K+ O
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */9 _7 m. C# U- Z' w. G. n& B
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    8 ~+ @* h7 ?- x* {( ^) u( ]- [/ `1 I
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;' q4 q: [$ {  m# P- U3 o4 ~  j
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    4 m+ M( I  Y8 u- v3 z, u" l! |
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    0 k8 N1 W4 K! s+ [9 ?6 ~: r
  39. % z# c/ e* B4 l; [3 ~
  40.   /*Configure GPIO pin : PD2 */+ z; v" a# T7 d2 J# y0 B
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    % F, G- e$ o- s% a7 v# M
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    5 [$ A# |, Q5 q% A/ Y4 a+ G5 b
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    , T& `! T+ a/ {7 y8 B6 U- m
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    5 J& A  F0 z7 H6 Q
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);6 j5 u  t8 H; T3 a3 W7 \
  46. . x& k# k) Z" u
  47. }
    0 H9 D9 G% z$ k8 c$ {0 H
复制代码
二、按键模块的驱动层实现
* x3 H( V/ Q8 F6 D; Y1. 硬件框图
2 S2 m5 G/ a5 g* @, }; l" D在这里插入图片描述
) R5 X# w& z! R8 ^- l3 }: B 11.png 2 m  `8 n2 S" v5 K
避坑点:$ S4 V4 w5 C) i5 D" s; B
短按:按键释放时判断时间
4 x9 [) C( R) \& v长按:直接判断时间! ]' q' p: d2 j6 Y) J5 \- F

( S: R" S( A( W( }6 e

) U2 M$ [3 ?0 }) q' m! c. t2. 按键驱动层代码实现+ |& Z: q& v: x4 m! L( |) M9 n
下面直接上C代码:
6 W/ Z2 d) c: Q3 d, X9 w3 C9 D! o9 s% ^- X9 T2 [

4 ], O8 r- c: X( r* f8 J3 ](1)key.c4 E9 `& M7 R. k/ B/ ]0 g( }8 m9 o
  1. extern unsigned int keyCount;
    - J  [1 ]* X) P  F
  2. extern uint8_t keyValue;" i4 ]  a( h( P8 B& o) p2 N1 }7 p
  3. uint8_t keyflag = 0;
    ! Q$ ~- G- s6 }4 F& U
  4. void Key_Scan(void)0 N( z5 v! r8 ~- @5 j7 Z
  5. {( e1 O) E! q. U
  6. //keyState  按键状态;
    9 c  v4 U7 M8 z
  7. //keyPass   记录哪一个按键被按下
    " k) K+ B" E& V, l$ [
  8. //keyCount  记录按键按下时间! h! K+ S! ^& q. f! u8 ]0 [/ d6 Z
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时3 ^- v$ w6 ~: O$ Y9 G6 p7 w
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    * c3 B" r/ m+ ]5 x/ q4 R
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    7 l, V; z+ V' u
  12. //ShoutKeyx 短按x键值,
    9 n: [  c0 K  ]$ I
  13. //LongKeyx        长按x键值. z) ^. ]8 d* d" N7 m7 y; o
  14.     static uint8_t keyState = 0,keyPass = 0;' N) Y# y3 y8 R
  15.     switch(keyState)' _4 b& L* K0 V1 c* a9 I3 ~# J: H" Y
  16.     {  k* H9 i" d% q" o; I' N4 [8 g
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)( @$ T/ h8 P. J/ ^" u
  18.                 {' x( ?  N2 l- M
  19.                     HAL_Delay(100);//消抖
    6 y5 d$ R3 x5 S
  20.                     keyState = 1;
    ' _6 i6 _% O0 _3 A# D8 Y
  21.                     keyPass = 0xff; //初始化按键
    " T( @, k9 F* M5 |" h4 b
  22.                 }   
    1 }4 u6 u" U6 d5 y; m4 [
  23.                 break;% n  S1 D7 _( s" d7 @
  24.                     
    3 l) M! @3 ]( F! a+ w: M  L4 ], [2 u
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0): ]) M6 b7 U7 r" P8 x
  26.                 {
    ' S# ~' f: p0 L. v2 {% R
  27.                     keyState = 2;7 E2 }! L6 T& {" C
  28.                     keyflag = 1;//开始计数% V0 _- R2 ~. u
  29.                     if(KEYB_1==0){9 \4 N0 F- a  R6 h8 |9 w$ F0 f
  30.                         keyPass = 1;//返回对应键值
    $ y. K$ w3 z) a7 T
  31.                     }   
    . O) q$ Z2 I( B. Q4 N# n- o) r
  32.                     else if(KEYB_2==0)keyPass = 2;
    - E/ j9 E, M) U$ a3 u2 Y3 F
  33.                     else if(KEYB_3==0)keyPass = 3;# _1 y- [  p) C7 E/ A
  34.                     else if(KEYB_4==0)keyPass = 4;0 y1 D  S* p2 @+ e; I
  35.                 }   * ^+ R6 c+ A1 Q" Z+ L# ^+ W. G
  36.                 else keyState = 0;//返回检测按键      9 K  @  a, A3 S
  37.                
    ' u2 A6 Q. w3 r1 P) B/ `3 a$ R
  38.                 break;" i$ G  D0 z: B& E2 B- g' p7 _
  39.         case 2:: z2 v: K# E2 @+ [' Y( [
  40.                 switch(keyPass) " |# Z# ^- r% {; w$ T
  41.                 {              
    $ u1 }! a2 l# Z9 l2 ~
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键5 W, e/ |( |2 a+ O, Q+ C# X/ s5 p3 `/ l1 D
  43.                             {
    7 Q% q3 S" |3 {8 b: Z7 B
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    # W& K8 @, H) l# O) V! [9 g1 g
  45.                                 {
    1 [% |& L, c, g4 B% Q
  46.                                     keyCount = 0;: \# I# X5 D' n0 ]
  47.                                     keyflag = 0;* o7 K/ g: f' O0 w7 N1 g3 X2 O$ Y
  48.                                     keyValue = ShoutKey1; . ^) m$ N) r' Z3 M; ]
  49.                                     keyState = 0;+ r: I& O; Y3 h: x* B5 ^& B
  50.                                 }     j6 H: F8 N5 f: A9 s# U  Z! x! N# E
  51.                             }      
    5 |7 o5 a# K0 z7 E' x5 k
  52.                             break;( v" v5 a0 Y) k& l0 T/ s8 Y  T4 C- @
  53.                     case 2:if(KEYB_2!=0)/ \; V& l5 U0 G$ s
  54.                             {
    & f% v) _3 B9 s) z3 T
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按( X2 v* {, U# [% E
  56.                                 {* l7 P  b1 F% u
  57.                                     keyCount = 0;
    2 E4 n+ h0 K) E5 |6 p
  58.                                     keyflag = 0;
    * l* T% X9 M! O
  59.                                     keyValue = ShoutKey2;
    7 ~# N# \+ N* k1 D+ Q5 w9 {4 E8 A
  60.                                     keyState = 0;/ X1 |! m! y9 H( s$ f
  61.                                 }   % i) y* U+ Q( m2 E! p- G
  62.                             }       & X. i2 v" `( s, {* F0 N
  63.                             break;1 }8 B/ f9 _) j5 G5 b2 |
  64.                     case 3:if(KEYB_3!=0)
    0 p  k, K" A: G" }% a+ R
  65.                             {
    ) E6 `2 S$ X% p* H% |+ A8 X& ?6 o
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按8 i5 v6 @1 D. {1 M
  67.                                 {- G. u- |! _+ k
  68.                                     keyCount = 0;' J; N7 f" W+ ]  r* B; h
  69.                                     keyflag = 0;
    # b5 k" p' O* M' D
  70.                                     keyValue = ShoutKey3;
    0 N  S8 n$ }* l. p, V4 H: C
  71.                                     keyState = 0;9 e  y# ~1 b$ [* ], Q6 k" n
  72.                                 }   
    % R; C3 }8 U; Q- G% D& N4 k' l  a; q, i
  73.                             }      
    : f' O/ _* P9 F+ q3 Q. u
  74.                             break;# s1 F3 n" n) K% C5 x5 N
  75.                     case 4:if(KEYB_4!=0)
    % P6 i, D$ R/ J3 Y$ `
  76.                             {! Z) t' j* N$ O
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    : v; P/ }  @6 V  ]$ u
  78.                                 {' ~9 X7 J* {! u$ y  E. C
  79.                                     keyCount = 0;6 V$ t4 K! o- k4 Y! p6 d4 l$ R3 Z
  80.                                     keyflag = 0;
    8 J3 K3 C5 O6 ~( E: b
  81.                                     keyValue = ShoutKey4;
    0 N& w2 G& f5 {- Y7 o
  82.                                     keyState = 0;
    4 g6 @( y" l! G. B0 J0 D$ C
  83.                                 }   9 b6 A! a" |  q& q0 \
  84.                             }
    & D$ `, Z3 j9 v8 e
  85.                             break;  C, ~% q: B! E- D
  86.                 }0 l" x- b' X% Z4 C9 ?
  87.                 if(keyCount > 800)//长按/ Z4 h+ I9 z% ~1 T0 t1 W# g
  88.                 {   
    " z* W6 G) f  Z, A% u, n! }2 `
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    , m! O/ x5 u! y( `  X
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    8 i' B" ?& C( w: b' u8 F- v
  91.                     else if(KEYB_3==0)keyValue = LongKey3;3 ^! y& H+ y2 S% |" V
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    % L, w& H# ]7 Y1 T, L& k
  93. 7 G# N. K2 \+ h+ x
  94.                     keyState = 3;7 }* n' m+ r  N/ f5 h& E
  95.                 }" x8 e+ [4 s1 d3 \5 Z
  96.                 break;* V) ]! r1 C) h8 _% G

  97. ! O/ F) O9 N, i/ _
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)7 A2 J- [, |, K9 `/ C
  99.                 {8 `, Q+ O0 \* t
  100.                     keyCount = 0;. |* E4 f) s. H
  101.                     keyflag = 0;" U& c. A6 e) x% C
  102.                     keyState = 0;
    % D% W- U* }- ^
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    : l+ M" m; W, U; ?) E8 {
  104.                 }
    9 I4 ^" @! z. Z4 C
  105.                 % [0 a8 Z% v( e/ f  Y
  106.                 break;+ }$ c6 a9 ^! R% H
  107.     }- J3 ^2 S- @+ l
  108. }
    4 L+ V0 ?0 ^# e4 J: l: _
复制代码
(2)key.h
: J  l' [1 O2 J+ k$ ?9 M7 x5 {
  1. #ifndef __KEY_H
    - }, K' W6 C* U' _4 t/ i) Y6 S4 ~
  2. #define __KEY_H
    3 D2 @) [' B7 Y' \: M. R
  3. #include "stm32g4xx_hal.h"  _2 o4 T; v$ V8 N/ g! x1 L! r: _
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    ( E. z" O# V1 f: R1 J
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    - y, K/ D( E7 e: H) |3 M  m
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    - W8 V" h1 p: l) U, U
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    5 S5 J4 P8 v/ G8 ?  K4 f
  8. #define ShoutKey1             1
    & `( B- o3 N6 k5 G- d
  9. #define ShoutKey2                26 J3 C0 f9 E1 a
  10. #define ShoutKey3                3( C' U8 o9 ~, e! Y" q' C0 U
  11. #define ShoutKey4       4
    6 H- C6 _3 z5 `7 k9 p# c) x' r
  12. #define LongKey1             5
    & h9 b4 Q2 N: l8 y8 M/ j. Y
  13. #define LongKey2                6" T4 e; l3 F9 q
  14. #define LongKey3                7
    # H* Z7 X: V( b& [, F( C  p
  15. #define LongKey4        8' q' J9 t0 C  ^
  16. void Key_Scan(void);
    . G9 j4 O" t! F" b
  17. #endif
    7 |/ p# d9 v1 Y4 F, j2 l
复制代码
3. 计时操作7 q2 g& i+ C9 F0 c0 T) x! n
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。
+ v3 K( N9 C! {, ]下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~% G) c8 R- z! n7 ]
  1. extern uint8_t keyflag;7 r8 m3 Z% w* p" C/ x0 |9 U
  2. unsigned int keyCount = 0;5 V3 r3 k: z& j7 z7 L: q
  3. void SysTick_Handler(void)  N: o" ^' X/ y. I
  4. {
    ' H( A: q9 V( N0 f# j$ O
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)/ w5 s- b9 M' b# Y+ D9 ?% B
  6.         if(keyflag == 1) //若有按键按下就开始计时
    7 _6 S3 Z5 R! |, Z8 g' G; U$ h2 T' K
  7.                 keyCount++;        7 z; v& f7 }8 M/ U+ b, J
  8. }+ I6 ]" z- ^  a* Z! M
复制代码
三、应用层简单逻辑实现
6 \  F7 X9 t7 d$ }! Q. `应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
1 E1 A5 a/ X+ K
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 $ R* z0 C% e- x  K
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器! B! j5 ?$ I( V1 A# `  y
  3. while (1)1 }* o. E. g( B& P" w+ i- N
  4. {0 _* d' V2 I9 K' X
  5.                 Key_Scan();
    + p% Q+ j( u8 `  U
  6.                 if(keyValue) //有按键按下
    ; v5 [$ M- @, p( r+ Z! d
  7.                 {
    2 w. j$ V0 v  a. `. Q! K8 J
  8.                         if(keyValue < 5) //短按3 a1 u! [% o. o' i/ |7 K2 ^
  9.                         {5 u( J0 p( I/ Q( o
  10.                                 switch(keyValue)
    * u6 T' g) u+ f$ W
  11.                                 {
    ) C* h( V' @! a/ F* @% z8 u
  12.                                         case 1:
    0 T/ s$ c' E; F/ ~
  13.                                                         keyValue = 0;
      c& a1 ?7 A# ?' R) d- M
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);/ i; Z: U9 ]% @9 ~2 ]
  15.                                                         HAL_Delay(100);2 f2 a' D' ]% z* |6 c- m" ~
  16.                                         break;
    " t: h5 c: K5 a& u' q
  17.                                         case 2:4 A+ X' c. o1 w4 h5 W* ^1 g
  18.                                                         keyValue = 0;
    # M' `- W0 t' i! T5 Y( u
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);5 j- S0 s+ E* ~; Z9 v. h; B
  20.                                                         HAL_Delay(100);% E& b; p) B2 q2 h% k& J" R
  21.                                         break;
    2 e2 P1 O) x' k9 \9 p8 [" E7 _; r
  22.                                         case 3:9 `9 \) v2 _8 J! |1 J
  23.                                                         keyValue = 0;* A. X9 ^5 a4 ^% ^& u. e
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    ( l6 {- k6 Y1 L) w' H& _
  25.                                                         HAL_Delay(100);
    $ }0 p2 p0 A$ X3 i) r, O& l7 K6 ~
  26.                                         break;& c, l/ V  S/ Q! E) _" a
  27.                                         case 4:# I; x3 ?0 J3 _& Z* `
  28.                                                         keyValue = 0;, ]3 ^# G" i! k& y2 S8 I
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    ' c! u% W+ V, C( Y& B+ n2 [, }8 W' A
  30.                                                         HAL_Delay(100);0 a9 w( Q/ N# }# a/ }# E4 U9 X
  31.                                         break;
    4 O$ E  U# P" {$ v# l4 R* H
  32.                                 }
    . e& Q5 w" ^% M8 @5 H. |$ v( p* W
  33.                         }
    / `, B3 H+ X  f( b) N: r: G
  34.                         else
    * d, b9 I8 j+ L- y
  35.                         {$ {/ a" _) D+ `
  36.                                 switch(keyValue)
    & |, m" M1 \& V9 ~/ l/ d
  37.                                 {/ d6 o' F1 k4 [, @
  38.                                         case 5:
    # n. g& U5 a! v! x# [( p8 _7 G
  39.                                                         keyValue = 0;
    " Q3 ^4 m) R- T4 ?+ T5 w( r" z. r( P
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    % g8 U7 t5 W" w
  41.                                                         HAL_Delay(100);
    ) j# W& P0 E6 `
  42.                                         break;
    ' m4 z8 M' a% f) R9 {/ M
  43.                                         case 6:
    1 o: F, n- V. k: {; D7 `
  44.                                                         keyValue = 0;
    ) c1 i( W% G9 r6 K% z  T( J
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);% R9 f8 m$ k3 f
  46.                                                         HAL_Delay(100);
    6 p! r4 r% D* }0 l6 S* K
  47.                                         break;
    0 H  h; J) y' E
  48.                                         case 7:% Q& Y2 N. r  W3 A' K6 o
  49.                                                         keyValue = 0;4 y/ F; k4 w# C- h, t
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);( {! j' c1 F  A' ]
  51.                                                         HAL_Delay(100);% \* I. J! L0 d$ E/ k* _+ |, M1 H+ o
  52.                                         break;: M4 q4 |, ?! E* Y% F2 e
  53.                                         case 8:
    8 w& p. s& t- n9 m+ n1 G8 G4 E0 v
  54.                                                         keyValue = 0;
      Q5 \4 k3 b2 [- R/ l3 K
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);2 D! U; E! r2 n5 T" h* `, o  d
  56.                                                         HAL_Delay(100);
    - ]1 `+ P+ V3 A7 \
  57.                                         break;9 K( V! }, @* _/ N
  58.                                 }1 I$ J$ v) A- ^0 k$ t  d- C
  59.                         }
    : ?0 i, x. g5 G$ A/ O% x2 P6 Y3 O  Y/ r
  60.                 }; \) h" x$ s" ?% W/ M
  61. }6 ^$ B1 q2 N& p4 j8 v
复制代码
总结( h2 X. q/ X+ f! v2 X: R
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
0 R' e+ H# @% x- ^
5 O& x; Y3 o& A3 J* B* a
% ^4 W( x8 e# Q; A9 @
' w5 a0 @5 w+ \9 L" W4 g: `* n$ o2 g

* q3 q+ z5 E; L% ~8 L( M
1 Z* H1 K! N8 w' X7 p$ s+ L
* n: j9 Z# w. L  E& d0 E# c( k
9 p2 |" k6 k3 t+ z
; S% G, S1 E! H! z- w& O' C5 ?  i
) k9 [0 A: J. w6 D
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~  g7 p/ [3 Q1 K5 d3 M0 P& P0 b

所属标签

相似分享

官网相关资源

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