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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
* d  p. K' w( V6 {  i+ P1 ~! G5 N3 Z: C6 D* A8 J- ]2 F% S. E4 ~: X
前言: ~9 O0 z; ~4 a
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。: [+ |. p7 ?; S( W5 P0 |4 p
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。& K* l/ b8 M8 _0 L+ G2 V
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~, q( E: r3 {6 ^  R

9 W# p! Z& o" O9 j1 j

1 t, \* o* k9 w' z: c先放一张开发板的实物图,它长这样~/ O- \$ f' b: F( ~
15.png
一、硬件操作
: ~- e8 P; @  ^- ^4 F7 v/ y# y在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
6 B" h& d4 |4 n. [. _7 o$ a1 n4 k9 G* k+ @4 e) d0 p
: ^( {+ R% b: b
1. 原理图* d8 p, ^$ q/ |+ Q! A) z6 c1 C  T# W
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
4 p/ g% d5 s% F3 k) P4 C
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
. c2 t) [0 `8 |2 u4 [1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;+ p( b0 M/ @7 z' t, F; H3 U6 |
2.按键相关的IO口:PB0,PB1,PB2,PA0。$ D4 N" O4 j8 j3 a

9 x! Y8 |6 G  y- @, Z, x
1 a7 i; `' b: ?1 q1 M, ^0 @
2. 硬件分析
: K" d/ g3 {# C- S$ m6 @从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。6 q: V; {2 ~  [' Q6 _" n( V0 f: c

+ T2 h' d' q" }
2 C) M' S8 O2 h/ C; ]* _. A8 }, Z
3. 初始化代码
1 c5 {6 p3 _  q' X; g8 T4 d
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    - v' H3 I0 K1 N  p% l! {& F
  2.   HAL_Init();//使用默认配置即可: a2 u7 U* M( x0 q' [5 X1 y3 O9 |
  3.   /* Configure the system clock */$ I' l7 z  Z3 s) O, j& ]
  4.   SystemClock_Config();
    , y) Z: W  T# I0 }) N+ E, A- [
  5.   /* Initialize all configured peripherals */4 x; _' Q  x: R( t) C
  6.   MX_GPIO_Init();
    ; i( r' B. c4 B9 \
复制代码
(1)时钟设置
0 y$ x7 @3 A  z4 i4 t- I% K这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
4 Q4 m  t% ?) k; V/ X; o- @
  1. void SystemClock_Config(void)
    + a9 b0 @1 C) q; m9 S; K. a& \/ N
  2. {
    ; w6 k( [2 p! ?( }
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};6 D' q% `: A2 ^# p# |
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    : d% W- j* u. G  _& L

  5. + {& ^2 W* \- E) V
  6.   /** Configure the main internal regulator output voltage ( R. q- |: S7 R: J: N
  7.   */9 b$ X/ ~% ~- a6 r3 K1 V
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);  @# R* [  ~0 ?; U6 v' T1 n  m
  9.   /** Initializes the CPU, AHB and APB busses clocks % C8 u$ J9 _3 _- d/ O% G. Z* K( B  c
  10.   */
    ! U5 u1 u( X' P7 U9 ]
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    , m( d1 W3 [9 d8 Z
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    ' G: A1 s& k7 U1 y
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    % D& w6 F2 O$ y1 l" ?2 X& R
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;$ B# ^3 M+ @! Y3 R* S
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    5 W* Q" x& y$ ~& D0 }: {! A% P& C
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;# N% C# u8 T! ?  W
  17.   RCC_OscInitStruct.PLL.PLLN = 20;0 r, Q# t5 v. M  d$ b( M; j8 R7 \8 V
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;8 k! b/ _( Q( u' d) U$ {
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;8 s( F/ ~6 I6 I, v  M& {
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    4 u" N7 u* J% C: h) a  Y  |# a# k
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)# n/ o8 {9 D3 t! Q3 q
  22.   {  s( ~4 [# Q3 Y
  23.     Error_Handler();! }6 [! u0 v0 x1 Y5 b
  24.   }( Q4 `0 ]! v% [2 l
  25.   /** Initializes the CPU, AHB and APB busses clocks
    4 T, Q2 f+ q, ~1 L
  26.   */
    % }7 [% j4 g: b/ E+ n% J% s) ?
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK( ]# j* Z4 W0 y. F2 v! z
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;. t5 R) F4 w: }4 d: Z2 o
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    $ Z# }. O  a1 D5 @$ |
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    2 Q( D! F9 }/ f6 z
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    7 u/ D8 k+ J) K) C2 b9 r5 T
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
      t' S* V1 _$ m8 n" I% [. Z
  33. / m8 h# j5 p1 E. r* j" }( U
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)8 e: C$ N3 F# z3 ?2 Q# u, |8 q4 N
  35.   {
    7 @) Y! `; f  T; z' T
  36.     Error_Handler();: }! }( v  \) s; e9 S, o) n( x5 _
  37.   }
    ! y  g4 C8 C  `" W* B. n! |
  38. }, e/ |7 ^. O9 s- W! {. S8 s7 ~, z
复制代码
(2)GPIO初始化: \' S2 w3 V4 E4 }
  1. static void MX_GPIO_Init(void)0 ^% {5 _$ F. P3 J7 H: p% X* x
  2. {
    ( F) R6 w# {& W, a2 u  ^; H: w! M" x
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};6 i0 e* m- I* Q# z* q  r% ]/ }
  4. - N0 Z* \7 Z. Y3 K2 C3 h' X
  5.   /* GPIO Ports Clock Enable */
      x/ Q2 l% [( l0 D" K) C
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();: Q5 x# f% K6 j! W9 i: A
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();
    ) R/ R! F0 ~9 O8 v" T' }
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    ; w' e/ [* e, Z( r1 @; ]
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    5 p/ U  `5 V% i/ Q
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    ( C9 y$ K+ y. ~1 g6 S# }6 H
  11. ) Z+ {  V' d8 H0 W' u
  12.   /*Configure GPIO pin Output Level */
    * F( O% E& X/ }+ r  g
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 3 Q0 i  B5 Y1 R+ `1 H, f
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);
    1 S/ v. R$ o* H; s7 ~& T

  15. % d5 G. v) c6 `$ l4 p1 W* h# L
  16.   /*Configure GPIO pin Output Level */
    ! O  J4 Q+ _" H  V9 L4 Z, S
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    1 Q/ C1 T$ C! Z4 D
  18. 9 x1 p+ a% t3 L
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    7 J7 q1 k! ]* v: a; V) X( M
  20.                            PC9 PC10 PC11 PC12 */3 E) [- E1 o# ^* t# c
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    # M2 g& ]( z* Z$ r( l" a. {
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;1 t8 J9 Q' h- V- P5 D4 }7 `) z! S
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;3 C% F8 f8 {9 x7 E8 y8 N2 S
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;  [/ |8 z" e2 c/ r
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ' d, e) P" |3 T( R6 M
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);( @( [4 s, q: Y; [2 n6 z* n. H

  27. ! H- y& K9 w0 u2 _4 s% [1 ~" V
  28.   /*Configure GPIO pin : PA0 */
    * }! I" f  W* X& D! R
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    ! c$ ]$ J8 l8 C, c0 q
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    ( p9 o+ n" J7 F2 |) K' E
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    3 U* F4 {! W! \
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    9 Z  Q( J$ J7 s

  33. ; f& y$ j) I5 X5 J
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */
    . @: l4 m8 f8 r) B
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    ! _! P. `$ \! d
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    , M) V. }3 P$ e$ a# P! R# b* I
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    ) |9 l5 K7 O1 X1 _% s1 g& u* Z
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    - Q" c9 \# A: v& q

  39. ) U" Z+ c; J* q1 U* c1 W+ I( ~+ L, |
  40.   /*Configure GPIO pin : PD2 */4 d% w/ b, J, j; n+ m8 d: B
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    : c4 p8 d- p" t9 V" q
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    3 P1 o+ Z& n/ v  J( h4 \" M; ]
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;$ ~$ `6 i  w5 X
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    % A5 V5 n  N9 u
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);8 o6 T% s; _  O- N: C* g

  46. * ]2 U  v5 a% o5 I1 D( S. ?' Q
  47. }8 T# I  P) }2 e* g% L+ r1 W( q
复制代码
二、按键模块的驱动层实现
( F% K+ L6 t8 e. Z& u$ }2 J1. 硬件框图
  ^+ {0 ]3 |5 o4 T在这里插入图片描述) l8 C' R* |; n! H7 c1 F
11.png 5 X- z' w% ]4 d- k& {
避坑点:
7 _3 F5 |. N7 }# B: W5 C1 x短按:按键释放时判断时间  s1 v* W$ |# @
长按:直接判断时间
2 M* b/ M0 q! X  f& P/ A1 _1 p9 p
# T$ d  O# z& g7 n1 g( b, w
# f; I8 \- I, z7 L8 F
2. 按键驱动层代码实现7 f7 H8 p# s: I  m$ M$ L  u
下面直接上C代码:
+ v9 T) `1 `2 |/ w; u" o& Y
' r" E: h5 B0 [' b6 {5 c0 U3 `

- P% A3 v! \3 q$ G(1)key.c& ]8 p+ m' g. G5 \
  1. extern unsigned int keyCount;/ C* Z$ s, ?, b" P8 q
  2. extern uint8_t keyValue;
    5 P" D8 k. T! l! ?# @
  3. uint8_t keyflag = 0;/ k& a7 m2 e0 e" G; M# f
  4. void Key_Scan(void)
    ( D6 l+ j# q( U* o  ?5 Y
  5. {' x6 a0 O" U4 D6 J( H* x6 a0 S
  6. //keyState  按键状态;
    9 E7 V4 S, }/ S* _$ W
  7. //keyPass   记录哪一个按键被按下
    ! i" s8 E4 V: B
  8. //keyCount  记录按键按下时间
    8 ^" T* \8 W, K! ~/ {
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时
    ' \9 |" g' q1 \) F
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    9 ^0 J2 e2 M0 k+ ^  w& e
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按. E. f; v% ^  S
  12. //ShoutKeyx 短按x键值,
    0 f4 F5 U+ t) S9 g# ~
  13. //LongKeyx        长按x键值& Q. i( p8 t- w& `/ j5 a
  14.     static uint8_t keyState = 0,keyPass = 0;
    ) p/ v& ~0 l, x0 X  W" h0 C. a* r) ~
  15.     switch(keyState)
    6 H# |8 K  }1 g" ~+ E5 R* E
  16.     {& ~6 D9 T6 a1 D, h9 b8 B  l* x- ?
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
      O, }$ K7 A! t( o- n7 x
  18.                 {
    ' o" p2 \) J' q( h2 ^$ |2 F6 M
  19.                     HAL_Delay(100);//消抖
    ' P( B8 {7 O0 Q( z- r
  20.                     keyState = 1;
    ; {' t8 I9 G9 l
  21.                     keyPass = 0xff; //初始化按键8 Q  w( l$ O6 H5 J3 x$ u
  22.                 }   , ]/ f$ @* R3 p0 ]& C5 g
  23.                 break;  y9 {) f: F9 I/ w, j8 J
  24.                     
    9 H) ]0 @$ ~. s& N$ z
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)0 b) p2 G1 l$ V0 d4 C
  26.                 {( [0 d+ `* o* a( T
  27.                     keyState = 2;
    ( S/ V9 Q: y& c! q4 h
  28.                     keyflag = 1;//开始计数
    : r8 V* u* U2 c2 h( k6 L6 @0 b% [
  29.                     if(KEYB_1==0){- w" D. H9 i9 u# v3 G- [: b
  30.                         keyPass = 1;//返回对应键值, \: `  O; J6 x; x- {
  31.                     }   
    ' \6 p7 ^+ x) x
  32.                     else if(KEYB_2==0)keyPass = 2;
    $ N( b; N. {& Y' x4 k
  33.                     else if(KEYB_3==0)keyPass = 3;
    / {0 T5 m8 F# y( D  R4 Z
  34.                     else if(KEYB_4==0)keyPass = 4;& z; `( M8 s- z
  35.                 }   ( E! D& r5 V( j* C3 x
  36.                 else keyState = 0;//返回检测按键      : o7 P& i5 ^) l( X5 e. g
  37.                 9 _8 q3 }' q' c- M
  38.                 break;
    $ f/ n7 r' V/ Y2 e* F+ q7 z$ p
  39.         case 2:- X8 o! c7 |% f* y
  40.                 switch(keyPass)
    ) O$ x. Y9 ]* {
  41.                 {              
    2 Y* a5 z) |$ }1 U+ B8 _
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    - s& j) }  f- b' `" z
  43.                             {, y# J1 }+ P2 H# v; V' D) Z: o& Y
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按' A: c" l) c8 d& f; |2 F
  45.                                 {* {- i$ Y  f- Q! a- a
  46.                                     keyCount = 0;8 m. \! M" f3 r/ D& ?
  47.                                     keyflag = 0;; R: i  q4 n! H
  48.                                     keyValue = ShoutKey1; 8 j1 @+ b. t+ s9 E1 g
  49.                                     keyState = 0;: e! X8 Q0 w* }8 K1 ~; T( J/ Q: N! e
  50.                                 }   
    6 h1 r0 s% A1 V- f
  51.                             }      
    , i9 ^+ F# c9 }, t) s8 \
  52.                             break;
    . e2 Y# |! o7 G/ I
  53.                     case 2:if(KEYB_2!=0)  F3 ~- Q- s, ?# K
  54.                             {
    - M6 y9 z! f0 }
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按; m8 R2 i& C( @/ n
  56.                                 {
    + a4 k% F5 o: I9 R6 q/ U4 i
  57.                                     keyCount = 0;
    . p. u2 [3 R/ L2 L% G
  58.                                     keyflag = 0;
    ! Y, L7 H+ S& s: h1 Q
  59.                                     keyValue = ShoutKey2;   ?; _& l) n* d3 b+ c
  60.                                     keyState = 0;/ Q$ u; y4 T" o4 k
  61.                                 }   
    ! F# G1 P2 p9 `5 T- G
  62.                             }      
    8 m7 {% D% ~5 v( ^8 M
  63.                             break;' ]* r) L- p: e+ v! B
  64.                     case 3:if(KEYB_3!=0)
    3 b9 ]" M" a& B
  65.                             {  X/ b' }( w/ n# {0 X* N
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按$ A* `- V4 Q- e( k
  67.                                 {
    9 t% G; V7 l' \8 o
  68.                                     keyCount = 0;8 t* V# E" r' p9 g) |
  69.                                     keyflag = 0;
    + R7 @) p3 p4 l8 g  s
  70.                                     keyValue = ShoutKey3;
    $ T1 b/ [: P2 B3 v
  71.                                     keyState = 0;3 l, n& F% `7 H) y: x) D
  72.                                 }   + ?1 V$ K7 U! y3 v& h! \
  73.                             }       5 h0 w" R5 }+ H
  74.                             break;
    2 U' ~! ]; E; I0 [
  75.                     case 4:if(KEYB_4!=0)
    # H, \' ^( q( q% w
  76.                             {
    * t7 w7 W& b& y5 w. C+ U- X
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按8 l" D* {4 @6 V9 u& J) V8 g
  78.                                 {
    ' p2 r  x& |- e. p( Z) S
  79.                                     keyCount = 0;% H% I& @  C: V0 B6 G+ H  t
  80.                                     keyflag = 0;
      O0 q: g# }$ w7 [: h2 r( Z
  81.                                     keyValue = ShoutKey4; , y& x1 N$ T; l9 ]) G
  82.                                     keyState = 0;# d7 o8 t" n1 @8 M& _- I
  83.                                 }   6 s  ~7 _0 P1 H: e2 ^
  84.                             }
    ' ]% @  _" ^' K! x; b7 h% [' \
  85.                             break;
    ; X/ j4 M5 _% e
  86.                 }
    " q6 o' Z$ @# b& ?
  87.                 if(keyCount > 800)//长按
    * _1 m$ a/ v$ [& K& V
  88.                 {   : Y( W5 R, N5 Q6 ]) M+ w
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    6 x- n) i! Y+ Y* G) m
  90.                     else if(KEYB_2==0)keyValue = LongKey2;3 J1 A8 r. h, k$ H. F* {$ g
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    5 k" v- j9 M8 s+ B# Z
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    . E+ K8 K7 |  O- \( o' s
  93. 2 b8 z( d, U4 B8 \7 z' b* {
  94.                     keyState = 3;3 l. s: ?$ z' f4 D  u0 R" v
  95.                 }
    , U( ~) }" H0 b  Y3 J* n
  96.                 break;
    0 Y( V$ U' |, p7 X: K
  97. : Y* m+ ^- C7 W# i4 r% T; w
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    : I. n$ V8 f! X1 L  n
  99.                 {+ k. U; K6 W0 f  H+ z
  100.                     keyCount = 0;! V; h& D. p. X0 ^' B& h
  101.                     keyflag = 0;( k4 A0 M# Q- [/ x' h/ w
  102.                     keyState = 0;# G. g" ^/ }1 ~& F+ {, o: s
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    9 f/ ^/ m6 D: v# E
  104.                 }5 w3 n4 q: j0 f# e8 M3 f
  105.                
    ) n0 i  z/ E5 R+ u: N( I
  106.                 break;
    + N0 C+ @/ b/ |% h+ M) H2 T* H
  107.     }+ x( U& _5 s# @) M! T/ K
  108. }9 r; x, h% @3 p0 D; ~+ J3 p
复制代码
(2)key.h3 v/ d1 r1 t% W
  1. #ifndef __KEY_H! P. L" L0 ?$ B4 F3 }4 e) z
  2. #define __KEY_H
      T2 L; q% r' J3 ~
  3. #include "stm32g4xx_hal.h"& r2 x( w( s1 i
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    / x0 m9 B. x4 |! N! Y0 ^9 }. |# h
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB18 B1 S6 O7 F3 n9 w
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    * u# @/ V* J7 e6 d7 h
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    4 V9 ~, ~  U9 @$ X% O0 m: X0 b% `
  8. #define ShoutKey1             1
    " m& j* I  C  v: f4 O' D" X5 w9 A
  9. #define ShoutKey2                27 u( W% o$ h8 j) Y9 d  ]5 c% q* d5 Q
  10. #define ShoutKey3                3: W5 \: z( s% @! _8 d' U# D4 R
  11. #define ShoutKey4       43 d. h1 r% A& W3 J8 F
  12. #define LongKey1             5
    8 a$ ]( [3 @* z2 J- k" g0 X* z8 H
  13. #define LongKey2                65 k9 y2 i+ F5 q
  14. #define LongKey3                7! Q/ D* R) u) X2 {4 o
  15. #define LongKey4        88 F3 Q" a6 a/ V! u1 J3 H- K" C0 ?
  16. void Key_Scan(void);! H5 }; i3 Q9 V
  17. #endif2 e$ c  w" q# h" s  x  b' r+ W
复制代码
3. 计时操作
* W& U8 J" M! s; c; V1 K6 w- d我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。
& I5 R; j" k; _4 {! [! H下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~1 A# Z0 G2 B. F$ Z
  1. extern uint8_t keyflag;
    " B2 m" X4 }8 A( [3 h9 M
  2. unsigned int keyCount = 0;
    ; R/ K3 n. @" N" `8 }
  3. void SysTick_Handler(void)
    & e$ Z* |# C) p) N
  4. {
    2 F* J' w4 J4 f3 I+ o) ^. K" k5 l$ U
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay): W) N4 G% z. m5 C6 o
  6.         if(keyflag == 1) //若有按键按下就开始计时: D/ i8 m' l& j7 t' s1 X- x& k
  7.                 keyCount++;        ) v: Z+ |+ b, S6 h
  8. }
    ' c: P1 p# ?& g* d6 W; C% E. b
复制代码
三、应用层简单逻辑实现
. {7 t! B( e! C应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
) g1 e" T9 o( j* i( y( B
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 ! r2 i2 @: ~% ]; m9 P- V' O
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器# S7 G4 \. h0 R& J" t# k0 {
  3. while (1)/ Z8 P7 ^! f. v: D: B8 H. t
  4. {+ ~' b9 {/ w9 _1 N+ G* h" A
  5.                 Key_Scan();
    ( u% h# }  Z( ?# w7 l* b- e5 n
  6.                 if(keyValue) //有按键按下+ O1 o: W* x. E! N! m, I5 l
  7.                 {5 k' r. C, F" m+ B/ u& X9 ~
  8.                         if(keyValue < 5) //短按
    1 R# b$ h3 \$ r9 E/ n1 i1 ?0 j; y
  9.                         {
    9 ]+ c, y* C9 t1 t7 V) `
  10.                                 switch(keyValue)
    . H8 {. g, A. i+ s
  11.                                 {. J' O7 r2 I3 Q1 i0 S9 a6 J2 K4 g
  12.                                         case 1:3 d- I. x8 \. R' `$ z7 u5 g- q
  13.                                                         keyValue = 0;, t5 h: g9 p1 o( C. ^7 }/ D1 Y, U
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    ; ], y- f) G8 ~4 y
  15.                                                         HAL_Delay(100);" @( A" }/ ^: b: r' c) ?
  16.                                         break;
    4 A  y. N6 z; j1 v( B  U/ ~
  17.                                         case 2:! d& u' ~. P9 Q
  18.                                                         keyValue = 0;& ^1 b6 }0 ^1 P4 b" S
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    3 d0 e6 C- w/ `' [* f
  20.                                                         HAL_Delay(100);$ ~: ~  ~7 _" c6 O3 W) B  c% m* s
  21.                                         break;9 H! N. z( `+ o
  22.                                         case 3:
    $ o+ W. H% u0 z1 B  q0 c
  23.                                                         keyValue = 0;
    & B4 [" U' H4 \% J, M* P  T6 h7 L
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    ; K! f3 K, Q# Z4 [
  25.                                                         HAL_Delay(100);0 C: z2 d3 D! ?! w  `) h
  26.                                         break;: ^- J; Q9 p' K
  27.                                         case 4:4 {& o: t) \4 y( Q1 O% {6 v- O3 g
  28.                                                         keyValue = 0;
    " [" E2 q' ^: }& |6 ]
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);2 U% Q4 G/ c, g% D3 u; i1 `& L' f3 R
  30.                                                         HAL_Delay(100);# g# x4 `; Y2 X/ C9 c  V
  31.                                         break;0 @* x: c' W% J" ]- b' a
  32.                                 }
    / J2 f& n- e/ i0 F* C
  33.                         }
    7 b9 D  g$ o% G2 G( E& X  o; Z
  34.                         else$ {7 E' L0 Z( T3 D# G9 |
  35.                         {
    6 [/ c9 |/ y2 ?5 {/ h
  36.                                 switch(keyValue)
    * X" c- ]1 U; e$ a& T; O
  37.                                 {6 B" d. t& x. p) @
  38.                                         case 5:
    / f; C8 o% ?( \. }
  39.                                                         keyValue = 0;$ q5 p3 B6 L; A
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);) x4 v! x9 G: F# w$ s1 p% T4 c
  41.                                                         HAL_Delay(100);
    7 s  d0 L  m, x) W. c4 Z4 V
  42.                                         break;( F6 ~4 T+ L; F( ^
  43.                                         case 6:
    ) c; V; @2 K6 }2 Q6 ~3 F
  44.                                                         keyValue = 0;
    # c( k1 r5 ~8 k# V3 @5 u4 K
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    ) B( L5 F8 g* n% ~
  46.                                                         HAL_Delay(100);
    - G' l! |: A7 D. U, W/ q8 B$ Q4 ?
  47.                                         break;
    9 |6 x. p+ d! L$ n8 W( |
  48.                                         case 7:
    # L( x! }8 F5 J5 v/ }5 V
  49.                                                         keyValue = 0;2 C0 b. [0 [6 l: K
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    / S5 l2 z3 s% ^" m$ T) e
  51.                                                         HAL_Delay(100);
    " g( u4 [0 u0 m0 v. ~
  52.                                         break;
    7 Y+ u+ r/ ]; U6 a; D8 p* f7 c
  53.                                         case 8:( r0 Z- {1 k5 m* b7 R
  54.                                                         keyValue = 0;
    ; B4 l/ w: s/ B) s2 O( \
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);; U+ ]" M& x7 o& y: T8 |
  56.                                                         HAL_Delay(100);- Z! Z8 |4 n5 G' e6 b4 N
  57.                                         break;+ G5 S- ]5 s" h4 g
  58.                                 }! L4 j$ G* E0 n; S7 z; U: k
  59.                         }
    6 Z) w' s- F( F! D1 r$ V
  60.                 }
    % }; q! y4 W* @" Z2 v% P+ i4 ^8 Y
  61. }1 P* U+ X' }4 q8 {; O2 Z
复制代码
总结) v% o- G+ }3 ]: C
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
$ Z2 A- c4 |; J! V1 `& ~! l0 N; q# t+ L& W$ G
( G1 c5 @. R$ o% ?& x/ V( x

8 j2 m+ J4 q2 [

$ r; x# A7 A: y4 C
; `9 O7 m% h1 k  ^
6 e( I2 k3 @! |/ k8 Y" P
' r- f% o6 r8 `6 ~) }( C

; m7 s2 Z) I% S- A1 X
1 M( N- g& h8 @. D- f$ U
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~- [( R$ N; K  }8 `5 `

所属标签

相似技术帖

官网相关资源

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