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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
: m) @& Q) \/ Y+ v  u
/ X$ v) v. R- ]$ A" `5 a2 `前言9 [+ U0 b" t5 Q- A3 ^# f4 U
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。4 `# v% C" L7 F' f
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
* R3 w5 @7 l' {0 N3 y$ `6 H- O由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
7 }+ N; W! s) `8 i2 h1 T! S6 L
+ W3 R( ]; G/ V- W; @0 g
  F& U& u/ q% j/ @
先放一张开发板的实物图,它长这样~! `0 h4 i7 [# r* o8 A! u
15.png
一、硬件操作5 k4 ~2 n* x: q- e
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
3 \9 u, X4 P2 H" a: C/ C0 W( H
% N, _6 o* d" h8 g6 g

  S+ }# |  m1 n( P+ k! v1. 原理图# W% [7 J8 n4 g9 s3 Q4 t4 V
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。5 H/ |2 x1 o; `% t+ Y) O6 o
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
) Y# m& N! f6 Q# Y! [' h# t0 h7 p/ ~: R1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
$ |0 i  X$ \; d( s; l2.按键相关的IO口:PB0,PB1,PB2,PA0。  L2 F% L! G# w+ h5 {/ _+ O% x
/ ]! ]+ m3 c: B" N, v7 p% S
, X' K2 Q+ J  \
2. 硬件分析& v1 L# t, t8 \  U
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
5 E  O) ^  K8 y5 A+ ]- _- r/ A7 j( X, p; ]% u  l

! o8 ~5 k, k. L3 V3. 初始化代码- w) g) w3 s: f; V: y. |5 L
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    4 b/ K6 V; ]% |& `, |5 _/ W1 {
  2.   HAL_Init();//使用默认配置即可4 i: W$ m* J% r0 v
  3.   /* Configure the system clock */
    8 K% p1 p  }, i% @
  4.   SystemClock_Config();8 j. ~7 K9 [( A8 i( [/ H3 w
  5.   /* Initialize all configured peripherals */7 l/ i8 w5 k( y/ m# d" E7 q
  6.   MX_GPIO_Init();
    + k8 o; j4 T+ c* P
复制代码
(1)时钟设置
$ _4 K+ ~5 U# d, f这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
" P: D# B/ ~9 [& a8 x( a# M/ k
  1. void SystemClock_Config(void)9 G) R$ ]1 ~0 P1 W
  2. {$ P- \3 [: b, D0 Z
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};( Q- s- z; c) T  y1 ^& J+ z, J
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/ o( c0 q  M  n4 T. p0 I4 j

  5. / D7 e' n) ?  l  l& W
  6.   /** Configure the main internal regulator output voltage
    3 e. m4 l9 ~5 \7 X$ k; Q; B
  7.   */
    & h) D; s. ?: U5 p2 \5 m" g9 h
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);7 t% W5 a% D8 j* Q: s5 }! ^
  9.   /** Initializes the CPU, AHB and APB busses clocks 3 L' w( j$ r( ?: n+ t" [4 D3 ]3 w
  10.   */. w; t9 a! b& W" b
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
      x" E. f4 {5 v) Y% A
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;3 V, Q" E- H2 R0 X2 l4 J& H) f
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;* R! a5 x$ k& |$ j1 d
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;' A( s0 r1 `0 U; Z" n
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;! M+ a$ H% y' X
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    , U1 U" X" R$ W. Y/ H+ |) A
  17.   RCC_OscInitStruct.PLL.PLLN = 20;% Y8 |: v; }1 \% |# p6 Z0 ^
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    ( _4 _5 D( ~; G8 |! M
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;; o, F) }6 I4 A
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;; E7 P- H- q- P& h" s# V( _
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    # }! P& J; J: Q
  22.   {
    0 A) e7 S6 f/ J3 p0 y' p
  23.     Error_Handler();( ]+ A% B( N8 Q5 R  o* {/ I
  24.   }
    . c  E; b, e6 W/ J
  25.   /** Initializes the CPU, AHB and APB busses clocks
    ; D- k+ @% c( T' m
  26.   */9 w7 e) ~) V) `/ r! U
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    ' T# }7 U5 y" u9 z! F
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;) j0 t) }3 t) e% A- G& @# f
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;" j3 s1 f5 o) \9 H' @$ `! j9 ?
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;; y' }% \3 v- X
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    . Y% C  K! e; W4 H, [8 N6 Y7 e' K
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    $ B3 D+ u5 A3 l/ E5 V- J
  33. + r; v9 R, ~$ Q8 [
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)% O: a  y4 f5 w: [6 g
  35.   {
    6 h  e  P' K) a9 C
  36.     Error_Handler();
    & p: H0 x7 u" ~5 ?! k7 T( E
  37.   }
    ; U! z. j" m! _' q/ X2 }. V+ @
  38. }7 W0 D. @7 b4 M& X
复制代码
(2)GPIO初始化8 R: C- a4 K5 V# |6 ]3 o
  1. static void MX_GPIO_Init(void)* i0 \8 f# ~) L8 B' x$ |3 H) N- a
  2. {
    * X  L% T* M! m# d9 F+ l6 J
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    8 Z" a1 W2 n' j6 `' l
  4. $ E( F. s( R2 S5 q
  5.   /* GPIO Ports Clock Enable */
    - m) S0 ^6 Q  j3 }$ t2 `
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();$ n. _! h; x1 q3 {8 d# E4 Y, u' f
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();8 m9 `/ M+ ~+ c1 P$ P: f. J2 z
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    5 d4 U, M( v5 K: Z+ k
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    * u4 U, M+ {/ i
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    3 j) c0 x; U3 M

  11. ( |& c" A) F% r; w
  12.   /*Configure GPIO pin Output Level */
    0 I7 l3 b4 W. U6 X4 Z
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    ; A0 B) }- h) f, \
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);7 X$ N- x8 V9 Y6 y! ]

  15. 4 {1 g6 @: m1 K" S0 B' u
  16.   /*Configure GPIO pin Output Level */4 k# J3 q" N; k& F, ^. E2 h/ h
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    & B3 C: [6 }, L' A8 U  L& P

  18. 3 F* T% E& u# Q2 U! C# c
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 ; u% a- |# q+ Q
  20.                            PC9 PC10 PC11 PC12 */
    * e0 A* b* s6 x1 H% ^5 z, M
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    3 r% C+ T- Q. c
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    5 k, A6 \8 y$ w9 _8 q& L
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;, }% y5 J9 w7 z+ B5 @4 w
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    8 k7 D0 q5 t( w! F
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    + b: I' l; m% Y4 Q$ I
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);4 H* [6 |8 u7 s3 M8 [' X
  27. + s& N$ G: q: v3 }% j2 W
  28.   /*Configure GPIO pin : PA0 */
    8 R; T, Y7 ^6 ~, k) F" E
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    ( H3 i; e# C7 N1 e) x: K( u/ M0 t
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    + P. N4 S# ~7 T! A
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;8 Z1 \* Y! \7 |9 d% [" x
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    % ]% b6 q0 m, C0 |/ r6 z: r

  33. & r+ [5 e; k' a+ V8 T+ r
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */
    & z" A5 H" l# V4 }% w
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    ' b6 e5 M3 A; N: d. X% g3 g9 J
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    4 w: Z" ?1 F5 P
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;8 G* I# T" d" a$ Z3 h- t
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    ) ?, m( \8 h' y/ a5 p3 E. N
  39. + M4 J& ~6 b6 z0 r1 `6 Y* Q$ V
  40.   /*Configure GPIO pin : PD2 */3 _6 M; O, e/ n9 x1 @
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;" `3 }) d0 r9 z0 A. X
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;4 }% |. _, z! r& N/ o3 W
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    ) p% q' O. F0 e4 ]! f4 J
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;6 F4 G6 t( W# y) S9 @- M* X) @
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    1 F1 H  ^3 a7 K
  46. % U, d- i; M, Y6 O' i
  47. }
    2 w$ @$ x$ @/ n( _0 @5 a
复制代码
二、按键模块的驱动层实现
& r! B/ A, ~' X+ i3 `) t6 R+ V" ~1. 硬件框图
0 h$ _+ r2 o5 j) Q在这里插入图片描述
4 L6 y4 f/ s. X. V# Z 11.png 9 \5 q' v0 a' Q8 w3 w5 O
避坑点:2 O# y% ~' S9 b! ]# r
短按:按键释放时判断时间# s  `% ~/ `3 b, Z4 A2 i9 T2 T
长按:直接判断时间3 _2 |3 v9 ^8 C+ e# s1 S1 [
+ t- W9 Z1 o/ B" t5 G
' F9 U' M1 D. u/ F$ S% U
2. 按键驱动层代码实现
# R+ b3 b; x/ w  X- _& F6 X8 W下面直接上C代码:- s' V8 P8 E5 |

: D% U1 Y7 r( @7 s
3 B; M4 |6 [3 @9 e( h" [% L0 F" B+ D0 t
(1)key.c# @7 R2 g4 b$ Q% ?" M- v
  1. extern unsigned int keyCount;
    , t) G' r. ]5 p' _
  2. extern uint8_t keyValue;8 n0 @- ?3 ?  h  E+ z; o, }
  3. uint8_t keyflag = 0;
    & }7 t* b/ J& C/ _  `- d/ H8 Z3 C
  4. void Key_Scan(void)( n: x' ~' ]6 u8 S0 R3 Q9 @5 D
  5. {8 x! Z% j- H5 m5 q7 I/ f
  6. //keyState  按键状态;
    3 J+ V6 n2 O3 [# ~& A1 {
  7. //keyPass   记录哪一个按键被按下
    : z+ q" o5 V( A, _# s
  8. //keyCount  记录按键按下时间
    * x( ~. }3 J& ]! V2 `
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时% f5 I7 ?6 Q7 D) A, Y
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件; u$ t: X7 f7 M
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    * {' w- H4 I2 }" C6 h
  12. //ShoutKeyx 短按x键值,: T4 f$ s) l& v( {% g* T  X4 F) _
  13. //LongKeyx        长按x键值
      \7 F% @3 J) X! _: q
  14.     static uint8_t keyState = 0,keyPass = 0;
    / V* |. t6 F; h+ L& i/ C( t5 h" y& y/ Y
  15.     switch(keyState)
    : Q6 Y) p% e& a$ i' t
  16.     {, J7 j# A! e* m+ I3 N8 s0 _& `$ B
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    - e( a: P, w& E; l# G) y
  18.                 {
    & j$ I0 @- |$ F& F7 m
  19.                     HAL_Delay(100);//消抖4 F! [' J. A. J  e$ g
  20.                     keyState = 1;) |& _+ t  N& K  ?' D" W
  21.                     keyPass = 0xff; //初始化按键
    + k4 \6 ~  ?3 ?0 n9 X
  22.                 }   
      v+ f, K: K$ F; B9 a, d, J% j8 @
  23.                 break;! }- P' e* r( u$ U% n0 J2 I0 G
  24.                     " o& c) ]. @8 m6 {/ q: F; c
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)  [: M1 r4 v4 S! C; w
  26.                 {0 D: g' I: O0 |" P
  27.                     keyState = 2;& }$ B- e, o8 S; p* L5 y+ s
  28.                     keyflag = 1;//开始计数3 n% o$ U  r6 }6 j# Q4 J
  29.                     if(KEYB_1==0){' c$ ], O- x  E$ ?) r! }
  30.                         keyPass = 1;//返回对应键值
    ) d- C& }( C) |/ z6 P2 c
  31.                     }   
    * a  G  W9 v1 u) n' T0 y
  32.                     else if(KEYB_2==0)keyPass = 2;7 j  S3 n$ }2 Y; W: j
  33.                     else if(KEYB_3==0)keyPass = 3;$ X( f* O) G$ Q, `
  34.                     else if(KEYB_4==0)keyPass = 4;5 h0 i1 k2 R' y* a+ R/ P! Q
  35.                 }   3 U. R9 h. A; v" E- O# R! Y
  36.                 else keyState = 0;//返回检测按键      
    - `6 F8 ?% f0 E
  37.                 " v, o% m* {7 R- u+ W
  38.                 break;
    % O8 C2 F' g" B7 r( v4 {$ v: \
  39.         case 2:
    1 @. K+ K& s, o# ]
  40.                 switch(keyPass) + J" f8 l; M+ h  Z
  41.                 {              2 [: ]& A5 U9 g2 {4 ~; ]* F- |
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    ) v- f8 L1 W' h2 e3 P7 v
  43.                             {/ w5 S9 h5 y* T. k0 S/ u2 Z
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    ' N& H" Y( F1 P
  45.                                 {
    5 N% v$ U4 X) m! {$ ?
  46.                                     keyCount = 0;$ x% r/ g. [7 q+ O
  47.                                     keyflag = 0;3 J9 a" {2 L  p0 c" f/ T3 a: q
  48.                                     keyValue = ShoutKey1;
      \- j) T5 E# u. l1 X- ^
  49.                                     keyState = 0;
    * F; A" g) E8 P4 z8 N
  50.                                 }   
      O& b6 k$ Z3 |: I; ]. |
  51.                             }       + b  x4 t& K; A1 L: N# g' S: \
  52.                             break;2 u: _4 S& p9 [8 T; c* J
  53.                     case 2:if(KEYB_2!=0)- D2 E$ b8 r- E2 C  H& r
  54.                             {
    . T* g: |# r3 ?' C, Y. s
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    ( W; M2 s  t( G# f( `
  56.                                 {1 _$ f) H0 [! u0 D. n) N
  57.                                     keyCount = 0;1 W3 w( D2 k" p3 T4 ~
  58.                                     keyflag = 0;
    ; y+ j8 e% O7 o: C6 O
  59.                                     keyValue = ShoutKey2;   r' C" [9 D' ]
  60.                                     keyState = 0;
    & p& `9 X8 S2 l# f5 u4 s' y
  61.                                 }   
    5 }9 n$ a% C4 k* X" q
  62.                             }      
    5 Q/ z' t2 u- ?
  63.                             break;. `) |& S0 Q0 G1 z, P5 {4 \
  64.                     case 3:if(KEYB_3!=0)' j  L  p# f, X
  65.                             {  w4 n7 W  h) V4 g5 L
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按
    : g" s+ A, H/ g* A/ _
  67.                                 {
    % I; k" k- d% U
  68.                                     keyCount = 0;5 w, ^* k4 W( j3 @
  69.                                     keyflag = 0;
    ' d, R& R. H0 w- j$ q8 c- V) `2 C
  70.                                     keyValue = ShoutKey3;
    , v: k7 G# A' C3 @4 o& }9 K8 x
  71.                                     keyState = 0;
    ( w) c- e# h/ P+ D
  72.                                 }   
    3 w3 H0 I! ^# V( l& w7 C& Q7 P
  73.                             }      
    ) \* L2 ~/ p1 R6 {8 o% b
  74.                             break;
    ( e4 s; V; z0 v! o9 Q0 s8 r
  75.                     case 4:if(KEYB_4!=0)
    ! e2 M8 ?3 \& U4 c
  76.                             {6 R' l$ R% n. v9 F& C
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    2 N8 T: |- P+ d; U, I
  78.                                 {: E& J5 X! l+ Q0 w' \" B
  79.                                     keyCount = 0;, |/ J" ^, S7 r5 [) e8 I) V
  80.                                     keyflag = 0;! y6 d; h, u) [
  81.                                     keyValue = ShoutKey4; ) c( W6 I$ d" _3 T7 U
  82.                                     keyState = 0;' ?" k" C& ^1 Y  P3 a6 B. x/ Q5 O
  83.                                 }   
    9 M. p1 R( L! k: f: }
  84.                             }
    ' ?3 b" H3 Q( n4 L
  85.                             break;" R4 e5 {( [+ }
  86.                 }: v/ \1 C1 l' j4 H/ N3 g% x9 V- S
  87.                 if(keyCount > 800)//长按
    0 l% x. b, E2 _; [0 ~
  88.                 {   
    % K5 {/ \3 n3 r) p
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    5 p: P% ^1 H3 I6 F/ [
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    ; C' M1 ]* J  q! @+ Q% c
  91.                     else if(KEYB_3==0)keyValue = LongKey3;# e2 o& P+ P  c, l' t. ~( F3 U
  92.                     else if(KEYB_4==0)keyValue = LongKey4;) }6 I0 n  d/ @( l7 d# v
  93.   ^5 d* |* I0 z* t6 \' N3 N  N
  94.                     keyState = 3;
    6 y* l. j8 B$ U$ h& \+ Q% X, O1 g
  95.                 }
    . \8 Z0 g3 G# d0 o0 ]2 K
  96.                 break;4 \) L3 m2 j! D! ?9 R* p  n6 d

  97. ! r1 l0 b5 q' p. v
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)  G5 B" h7 q, K/ Z3 \+ q
  99.                 {
    9 E! g. H, e2 F& \
  100.                     keyCount = 0;
    1 L2 w6 i, u: i; R1 k7 Q
  101.                     keyflag = 0;
    2 e; i" }% v( C8 l( v
  102.                     keyState = 0;3 q, ]3 O( [0 l6 A  h. j, ]) y% o8 a
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  3 [9 Y" ]& H& K
  104.                 }) L  O1 [3 w0 I
  105.                
    5 a/ v0 z& W7 T2 l  A& A" N. X
  106.                 break;
    / i9 b$ r- U/ m3 m0 O- }8 Q: d
  107.     }
    4 D0 B. _" v$ V- h. @
  108. }
    9 ]: P( \1 A- x/ |8 F" ^
复制代码
(2)key.h, A# G8 j* P$ `% V) x/ |
  1. #ifndef __KEY_H
    . x1 h7 m! ^9 l5 d$ D- m
  2. #define __KEY_H
    4 d6 ^  L0 n2 b# W% h9 P) a
  3. #include "stm32g4xx_hal.h"
    ) f* I  l5 B2 f2 C1 _8 Y+ k
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    0 c3 b) ?; k$ g! ]  `" K- _- x
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB11 h. H. d: e/ V" `
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2' ^9 u! D- {. y. W
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
      s  r8 f, k  l2 G# a& B; m, W
  8. #define ShoutKey1             1# ~: z. \0 e) q
  9. #define ShoutKey2                2
    # u' @2 Z" g" n# B8 q- _
  10. #define ShoutKey3                38 W+ M9 D0 }5 S* b8 S) u
  11. #define ShoutKey4       42 U  c# b4 {, W4 c# Z
  12. #define LongKey1             5; w# R  ^* `4 _1 E6 y4 P
  13. #define LongKey2                6
    2 q* E8 V% f/ u! b8 O0 g9 U, q
  14. #define LongKey3                7/ Z* X7 V1 Y+ j2 s
  15. #define LongKey4        8
    ! X1 K/ e% B/ \5 h
  16. void Key_Scan(void);
    3 ^5 k2 |7 k1 s; L3 Z: b
  17. #endif
    3 o: ?5 B! B6 C$ @) K
复制代码
3. 计时操作
% w+ f) C5 B& D: Y) `' K1 E5 }我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。: z# z  }; C! {* q8 t7 \0 G0 o$ J
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~" v/ s& R' D2 y/ H5 t9 u
  1. extern uint8_t keyflag;
    2 N) J1 \8 {0 z  U% z" q
  2. unsigned int keyCount = 0;6 m1 D; w" H# g: q9 J
  3. void SysTick_Handler(void)
    - Z& ~; {$ n# Q% ]4 ^* E+ E
  4. {
    ( q) m3 C. e$ m3 G/ z* x& d
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)4 }5 D% N, m. H( }9 M7 Q! L% s2 x2 B0 ~
  6.         if(keyflag == 1) //若有按键按下就开始计时
    $ K1 d! }# H/ Q
  7.                 keyCount++;        5 a/ M5 P# }( r, _: P8 ~$ p
  8. }
    . K& z# F# z% F7 d1 w& ~
复制代码
三、应用层简单逻辑实现
! `. Z: U/ a' m. N2 m应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
2 L* V( q5 a+ a5 e
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    0 s7 O; x. V% a- H0 D! H
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    8 ?- S) L$ s# `5 `
  3. while (1)# I, T& t% c9 \2 g) L& H0 E
  4. {
    ; j2 E0 S  S% o5 m* e. z. |
  5.                 Key_Scan();2 T5 D; x! [+ x2 H$ W1 S
  6.                 if(keyValue) //有按键按下4 V* _' a+ ^9 t) O
  7.                 {4 Q8 f* `* |, I% ?
  8.                         if(keyValue < 5) //短按: X/ m% K$ z5 z# ^" |, o) `" l9 G
  9.                         {
    0 Q) K# P4 w0 A8 k% z
  10.                                 switch(keyValue)1 Y# b! p' e) f% k( s9 k8 s
  11.                                 {
    8 g$ @# u" ~" z5 K$ J
  12.                                         case 1:
    6 @1 U/ q3 B( L1 y' i. j, r( R
  13.                                                         keyValue = 0;
    9 s0 D! |; d- ]4 ^
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    6 {5 r" `6 u" U- X
  15.                                                         HAL_Delay(100);2 D; l, J# O5 S6 L4 [! O
  16.                                         break;
    ! P6 s/ \+ s+ `& i) |5 }' H, g2 ~
  17.                                         case 2:
    2 j8 O, u/ f7 Z# r; m5 z6 j8 b& ^
  18.                                                         keyValue = 0;
    & w+ \/ R3 S/ X3 w
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);( `! [3 w! b7 v) y8 [9 }
  20.                                                         HAL_Delay(100);
    0 s+ @3 y' `0 X( i! J
  21.                                         break;
    ' B7 O3 A# I$ z# {* G
  22.                                         case 3:
    7 _& h, E& J9 v& b7 ~2 D. \* \
  23.                                                         keyValue = 0;9 o4 O; i) c. R+ r3 e
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);$ i2 a$ A1 t1 u" t! o  O
  25.                                                         HAL_Delay(100);
    ! {- z& R( I$ n1 _
  26.                                         break;
    # [8 I7 W2 k/ }& y
  27.                                         case 4:: Z  t- C; ]: `1 C) q' ~! C( h+ w0 O
  28.                                                         keyValue = 0;2 z2 U+ |& W9 v5 u
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    0 S: y5 d: n  `
  30.                                                         HAL_Delay(100);
    & V: `$ p9 j  A% @
  31.                                         break;
    ; n$ Q$ T0 S6 d  y+ y
  32.                                 }
    7 a9 M5 ~' `9 H* Q) x, @' D
  33.                         }
    # w9 X& v9 P$ |+ u( A
  34.                         else
    5 j3 X; q, J4 G  ?5 H
  35.                         {
    $ e+ Q8 a2 u$ v  I
  36.                                 switch(keyValue)! I; y4 ^/ N8 Y3 y7 N( Z
  37.                                 {
    5 a5 Q. m6 N3 Y/ t' f
  38.                                         case 5:, F7 i# R; f7 F
  39.                                                         keyValue = 0;
    0 [& w8 H& c2 h& A
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);' L  V1 y8 Y& n4 ~7 h1 N
  41.                                                         HAL_Delay(100);
    # D% r0 v$ r8 ]3 q
  42.                                         break;
    3 ]1 @' [. X9 D5 j9 E
  43.                                         case 6:
    ( R( J; L5 g, u5 j8 T! c
  44.                                                         keyValue = 0;' G! B2 s& t0 ]' b3 j4 R
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    : v' o/ Y1 K9 h; P
  46.                                                         HAL_Delay(100);
      Z' H. d  k; l# _4 b4 _3 l1 l
  47.                                         break;# a" N) w4 c  h) }2 z
  48.                                         case 7:! P. O* A! R3 |. A6 \$ Q) L
  49.                                                         keyValue = 0;# T* f' F  O3 n) [5 i- B
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);) a" L' g0 o7 m! k+ v- Q
  51.                                                         HAL_Delay(100);/ F7 _# G) w: |5 I
  52.                                         break;
    6 }* ?! H. B8 a3 C5 E' i7 N6 [
  53.                                         case 8:
    # L* u( h3 M- O' e- V1 L" p
  54.                                                         keyValue = 0;
    5 i6 h' C  N4 B* T; @7 D  _
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);+ T% U' T4 @& v) K! s. D( Q# @: F: C0 G9 X
  56.                                                         HAL_Delay(100);0 X9 d* G% V4 l0 Q0 }/ r1 ]3 X& g
  57.                                         break;
    1 O  Y/ g+ }* e
  58.                                 }: X7 F2 ~) T) @4 P
  59.                         }
      D7 L" z" L, Z+ U1 t9 y4 `$ a  r
  60.                 }
    3 A/ e5 f5 y; |2 T* R3 P
  61. }
    3 Q' y" D7 A( t1 g5 a* ?/ o: E! z# N" C
复制代码
总结. p/ U* h+ j8 h
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
5 n* K% b# D" j& L! |( W' y- l2 \, O' z' W4 X# p
! K, _3 M& _- \6 Y$ Z* N

! m* j& t, A6 v+ k/ w9 L

% V- H2 R9 |% N* x- R$ n8 n! O7 _) j  e- t2 [4 _, O
( M  Q5 I* @# W( C
6 ]3 }4 n6 w2 \' M

9 ?: ^' P, K- e0 ^0 p" f
6 [4 F9 D9 Z3 n" c
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~
- ^" N  G0 m# X) X4 t/ s4 m+ D4 l6 \+ \

所属标签

相似分享

官网相关资源

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