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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块9 V- A9 `1 Y7 m& L! l# C

/ E3 q% r! J1 C2 ?% W前言
, f7 D, Z: q$ S: q& \, ~) b我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。2 |# h  u( [% z, t3 J1 h2 s
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
6 V- Q" C" R4 Q4 I1 @. l" K由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~& P* e( J3 ]2 u8 ~' T
+ o- v6 d- B0 d6 T! N  n* r

9 |1 D. G) `% |3 h先放一张开发板的实物图,它长这样~$ f7 n& G9 v9 H2 o; c- w( m3 R' ~
15.png
一、硬件操作
3 @9 R( A" C/ A) S: J在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
% D5 Q( z" D5 f/ }8 P& M7 ^
  q. d: A$ I7 {8 p6 \
$ ~1 F( E* c2 ], ~# e
1. 原理图
6 `7 V3 @+ B, T; g' \5 A
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
2 j- r$ `# p8 I* U$ a
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)) B) w% ^' k1 n, j, b/ _$ Y- a* h
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;) ^! ?. p3 b6 Q- I/ G; m
2.按键相关的IO口:PB0,PB1,PB2,PA0。
# c' E8 y, ~+ P; B+ D) g0 Q9 h$ A! G" k) f
+ [( T# B8 X! J
2. 硬件分析- _" }" O' y! w
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
1 i- d8 Y' `& I4 W: p2 k% A
3 l5 I: I& \' J" [3 h4 y& n
( J6 _+ H/ ^$ r& Q8 r& Y/ t
3. 初始化代码$ M/ ~+ X3 [  Q) |/ X- U( h7 z
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */# l# \, \- Z( |6 ]; p
  2.   HAL_Init();//使用默认配置即可5 H1 k! p% V* b7 g- B& U4 K
  3.   /* Configure the system clock */. D9 `5 s! o6 J* f6 k; G$ b% o
  4.   SystemClock_Config();
    ' E! Q1 I& \! r" E
  5.   /* Initialize all configured peripherals */
    % V( O' ~3 |, w* I9 V
  6.   MX_GPIO_Init();
    7 h& j3 T* \. ?4 |3 i+ }
复制代码
(1)时钟设置
8 c9 k6 a7 ^$ d% z3 q这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
7 x6 a8 @1 B) H, _
  1. void SystemClock_Config(void)
    & Z5 }6 o9 j# l: g) T
  2. {% h& ~7 a% J% M7 Q" a
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};( O) Z8 W7 P( w& Y7 _2 ~4 J5 k, k
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    7 W; \! c/ z! h8 f* v) l2 `  J
  5. 0 l' J* o" v0 l: F2 z2 m
  6.   /** Configure the main internal regulator output voltage
    , v$ G6 m. J& E( W
  7.   */+ ^  E! W& @" ]9 |3 F
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
    / y8 C* p5 T$ l/ Y* H  m
  9.   /** Initializes the CPU, AHB and APB busses clocks
    ! q4 y. g( u8 T- d
  10.   */
    8 T3 E/ l, m3 d* Z) I& K
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;, Z1 _, R0 b+ a: i" c  E! M  a5 X& n7 i2 B. x
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;9 |5 K+ n9 Q* R& E& {
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;# \$ D# r0 l& q5 r7 C9 u
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;4 g5 t3 u# @+ U# F& m  J
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;+ t$ d8 T6 V* \1 T% q" Q6 [! F
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;/ D( B) x& M0 t5 o2 P
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    + F3 Y9 E/ L1 E+ `: i9 z2 ]2 u% k) D
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    - E; b9 p7 ~& b! F! r( B2 r
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    " o% ^8 C% i1 @2 Q/ n
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;( C3 X& G8 V7 f- Q
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    4 g+ H4 G8 T+ w# i2 C5 u% {
  22.   {
    ! s: M- d2 }9 d" K( b. `2 K
  23.     Error_Handler();: U" c+ V+ s* }( l, C
  24.   }" ^& M6 {+ H; q1 Y# p
  25.   /** Initializes the CPU, AHB and APB busses clocks % }: y" G: j1 _& `" C4 p
  26.   */+ X: @& E( }6 ^* W. Z
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK8 j7 ^' L. m- j3 U8 E
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;. y+ F; n& [5 D* u
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    & M6 @, g9 r+ y3 q5 U3 l
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;3 R$ T. A7 \. a! A
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;1 O, `- X# I: x# k( u6 ]& r
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    # W2 S5 ~( X: T; t: u

  33. * T  k, x, @+ @$ H% }7 H$ \
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
    . @6 l' v: _* H, Q6 C- \( G
  35.   {) `4 v% `8 f5 r$ ?. d: I1 z3 L
  36.     Error_Handler();
    & h' V, n+ n" J) D
  37.   }6 \6 W9 e: H) d! [& X% ~
  38. }
    . _- j5 x1 W6 d/ O$ X* z0 m
复制代码
(2)GPIO初始化4 M+ C) g, o6 _% Q6 H9 n
  1. static void MX_GPIO_Init(void)
    9 D* f1 ]9 I. T' b# I
  2. {
    ; j+ v0 n2 E7 r; `
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    # `" [& H8 p6 s- r& A+ z
  4. 9 Y0 d  o$ f# X; s
  5.   /* GPIO Ports Clock Enable */# l* U4 u* S8 O$ n9 y
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
    2 f/ z% I" A- R. b8 E# m0 r
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();( i/ ]+ Z$ Y2 d( c5 ?; l
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();2 {# n2 b- ], A! G
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    ) a/ Z$ q8 g  E/ R9 C! E% _
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();) u5 m' P, i% h% s
  11. 3 g, C! f+ h: A: J2 l
  12.   /*Configure GPIO pin Output Level */9 r" h- \0 _4 r4 v3 a
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 2 J2 d" H% N) F2 k5 D1 T3 g
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);; X, x; J" Z3 n0 M9 f# D5 S! h

  15. " L/ x! M& v( f8 J
  16.   /*Configure GPIO pin Output Level *// O3 ~' H' v* l1 [5 V% T
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);0 y( X' M0 B3 N& H

  18. 4 q& X  D5 }; C
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 ; {: x" j0 j7 m. u
  20.                            PC9 PC10 PC11 PC12 */; t' K3 h/ k+ ]6 X" L: o- v
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 - O* k* R9 p/ x0 e: J6 O$ `2 A" z
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    # ?: I. C5 ?  F! j! ]! O
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    5 h, }2 x# \( X
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;; ~# J) J9 i5 _2 @+ J2 T& g: m
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 W- o. `: B1 x6 ?( |" z
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);9 i. f7 B8 f' K3 m* B
  27. ' m; n/ b2 S3 Y. a# M# w( t/ P7 j
  28.   /*Configure GPIO pin : PA0 */
    ! x! U, [4 n: V5 s
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
      u( Z# B7 P- @- U, u" v2 Z6 P. o
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;" ]9 z+ }3 {: m% L$ G0 o  `3 d
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    4 E9 _7 E: O! s( ]" G( {! Y
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);& X; {4 p( D" H4 L" w" f, Y
  33. 6 E4 }! Q3 x( q3 U4 G
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */
    5 l$ H' K( d% ^) n7 m  R
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;% i* H' M- }3 U3 O8 c2 ^
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    0 {5 D, H# P5 M; q
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    3 ]2 ?  D. @  Z" ?/ h. y& K
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    0 {: }* r; ^2 N3 D# f! ~1 Q2 a
  39.   s7 ]8 _7 ^& n0 t! h3 C% Q
  40.   /*Configure GPIO pin : PD2 */
    4 J7 c: f- U1 \! E0 l6 {) B
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;7 \% r* y9 [7 V" y
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    ) |' j' J' q8 g% M. E2 o
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;* u5 B, u) W9 p, V9 N; r
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    * J, O3 {' b5 W, j& a
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);7 e* ~' {" w" R% m# v4 ~5 H( z
  46. . I6 [5 P4 y6 C
  47. }
    . T4 H( C: j8 g' O& }
复制代码
二、按键模块的驱动层实现& a/ V. I! H5 W+ d# `% v8 N! M
1. 硬件框图* J& z8 L+ H. c1 F
在这里插入图片描述
1 N. H! E, c) t- e; x6 j 11.png 8 I6 A4 W! B5 ^. W
避坑点:' H0 e, j2 v1 Y% U/ d
短按:按键释放时判断时间
% F9 m9 V) @- g) F4 B* j7 Z长按:直接判断时间
6 Q- _% h5 q7 Y! S+ v
& M# t. F$ _) b8 Y

- Q0 R( D2 x* v: o2. 按键驱动层代码实现% @* p/ G# q: ?" G6 f+ x& O* q
下面直接上C代码:9 ~: j$ j* \. c+ ~

2 S: W/ `/ E) m9 p
2 q! F; C/ Z4 l* K6 L! ^
(1)key.c
. u$ _9 j6 W% W. k
  1. extern unsigned int keyCount;  ^, w& ]8 h7 h& B* X
  2. extern uint8_t keyValue;
    : r8 u2 f  z) O7 H( Y/ B7 i
  3. uint8_t keyflag = 0;
    3 j( n0 N/ {# M9 D7 V! i
  4. void Key_Scan(void)3 ^& o3 _1 N" m  E
  5. {% x5 `0 g  ]# Z$ e$ l! t
  6. //keyState  按键状态;2 n; F0 Z( L  K3 E& X. h
  7. //keyPass   记录哪一个按键被按下1 t# ]4 E( ]9 R% z8 r6 N
  8. //keyCount  记录按键按下时间. p$ h6 i8 \/ T/ z8 J
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时
    0 C, Z$ z0 f  L+ K7 y* n' {
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件1 b: a! @' T' P6 A! f( e$ U' \
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
      p* f) n3 K% t' i3 j& W& o  i
  12. //ShoutKeyx 短按x键值," L9 N# U" q: J: C4 N  O, K& N
  13. //LongKeyx        长按x键值
    : V  S$ B) d5 B; S* C: A7 J! D
  14.     static uint8_t keyState = 0,keyPass = 0;" G0 B% S' B5 H" l6 a' J( ^
  15.     switch(keyState)0 p0 L# V. f& C; _! K
  16.     {
    ! H% e6 q" B8 b* ~5 v
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)  }; V* ?; x' d
  18.                 {6 i# ?! \) l. P" W* c
  19.                     HAL_Delay(100);//消抖1 {& X2 [. T9 u8 ^& f5 k. y
  20.                     keyState = 1;
    " m0 M+ W* q6 W3 Z3 L2 q& W
  21.                     keyPass = 0xff; //初始化按键
    % n$ U& U7 U. {
  22.                 }   7 r: g& f7 \8 x" I
  23.                 break;
    / k- b4 D  ~) X- e' v
  24.                       |; f. t& e8 {. w$ V3 O
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    " O2 c; H' {& o# }/ m
  26.                 {
    / P1 `5 w3 n/ @" H
  27.                     keyState = 2;, }; v- F$ t0 O
  28.                     keyflag = 1;//开始计数! T4 _  ?' j- D8 @4 h1 K# b
  29.                     if(KEYB_1==0){4 C& R" m8 f7 Z0 A8 P
  30.                         keyPass = 1;//返回对应键值
    0 X6 e/ M! m, w
  31.                     }   % g$ Q5 k/ C' R( y; E2 S! D) }
  32.                     else if(KEYB_2==0)keyPass = 2;  J' t, w9 f) n6 I8 H) i2 \$ t$ r7 G
  33.                     else if(KEYB_3==0)keyPass = 3;/ ~/ A( B. a: A4 W! X$ R. c
  34.                     else if(KEYB_4==0)keyPass = 4;& n* C+ X/ M$ k1 [# ^% F% l1 c
  35.                 }   . V8 \" @$ a  J: B
  36.                 else keyState = 0;//返回检测按键      / Y7 c! p" \( R3 }9 @" W# Z' h- e
  37.                 : h7 g5 W4 t; I$ i9 L* R2 x3 C: [
  38.                 break;+ ~) ?) e$ P' c, q
  39.         case 2:7 ^3 T' @! C* v
  40.                 switch(keyPass) . ~1 Z6 m6 o5 }" }; {: ^/ `6 R
  41.                 {              
    - g! U; U4 a& V& n( g
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键* }! p& l3 K2 R
  43.                             {9 o$ y. X7 @5 g; i" ]
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    + B. h: E2 H' U3 Q1 W1 Q8 P2 r9 a2 ]
  45.                                 {) Q( ?/ K4 Y9 G8 v* b3 E( k
  46.                                     keyCount = 0;
      j& u/ C- Z* K% U0 S( e, w1 a  {
  47.                                     keyflag = 0;5 z6 `# G' `& t6 g( w
  48.                                     keyValue = ShoutKey1; . P  Y/ x5 G; B$ M  }: Z) g1 q
  49.                                     keyState = 0;
      b% s2 B4 h5 i( f
  50.                                 }   + i( C" n8 [) x( T0 e
  51.                             }       * v" t' X( e/ Y4 d
  52.                             break;
    7 f$ U, o% ~; x: [
  53.                     case 2:if(KEYB_2!=0)! ~1 U6 ]5 M2 e6 T9 k2 c0 O
  54.                             {
    ' a: q% N3 q/ I2 q
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    ) A7 b+ n- ?4 I; G+ |
  56.                                 {
    ' ^3 \; F( b1 ~3 n" S( n
  57.                                     keyCount = 0;
    : G8 G/ L$ D& i8 C; S4 [
  58.                                     keyflag = 0;% Y# o7 j* w" k0 k% p7 V
  59.                                     keyValue = ShoutKey2;
    & Y+ P6 D" |* m- i3 j
  60.                                     keyState = 0;1 \- y1 i# J" [' y1 H
  61.                                 }   
    : g  |( [8 K" [% K
  62.                             }      
    : [" U, ]  c* A
  63.                             break;
    ' O* q/ c6 c4 @' y+ h- |& ~! O
  64.                     case 3:if(KEYB_3!=0)! D# s$ p3 q+ C* [
  65.                             {8 ~) T- s0 ^  J+ U
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按; v( ?( c* t" [5 z8 _9 m
  67.                                 {( o/ d9 v( r# Q- j4 e* Q
  68.                                     keyCount = 0;
    9 B: o6 G" I% D, `3 N6 o2 J
  69.                                     keyflag = 0;
    8 d( [$ m  q- A* u1 w
  70.                                     keyValue = ShoutKey3;
    ' h# h- [+ z# [3 y
  71.                                     keyState = 0;! O  F6 e7 g; F- U. |8 e
  72.                                 }   
    , D) M4 T+ N: P
  73.                             }       $ b# r5 X2 ~2 ?
  74.                             break;
    5 l" p$ I5 B! G4 W9 L, i3 f3 Q0 f4 L
  75.                     case 4:if(KEYB_4!=0)6 j7 ~( E: s& D" C; K
  76.                             {6 ^$ Q" Y8 L; Y% c( Z- i0 R, Y
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按3 |9 e, ~2 {$ r8 v
  78.                                 {# a/ E! \5 J( t. P1 B
  79.                                     keyCount = 0;) x- D& y, {" @& S
  80.                                     keyflag = 0;
    % G( H( n. m5 Y% Q9 K$ H
  81.                                     keyValue = ShoutKey4;
    + {7 p; n& X0 v: G2 ^6 a
  82.                                     keyState = 0;1 j/ N. Y% H: K) \
  83.                                 }   ) T+ A$ Y, |& n4 @2 P
  84.                             }: W$ R: O, j# x: K- }3 g, T( K; V
  85.                             break;
    - \% p  J. L; Y- B: g
  86.                 }- l" O! t1 k6 P7 o! ]
  87.                 if(keyCount > 800)//长按
    7 P% t; a$ _3 T% \- c0 a7 u
  88.                 {   
    5 u9 ?& Q' f+ @; k7 W/ Z* T7 ^
  89.                     if(KEYB_1==0)keyValue = LongKey1; 8 ^5 {9 g2 Y  I2 S7 R& L8 G8 |
  90.                     else if(KEYB_2==0)keyValue = LongKey2;) E+ \: @" t) s9 _3 w
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    8 F5 W% R9 C5 Z( P# P( b5 }6 l
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    1 h' A9 N& K4 I- K; E% ?
  93. . c: [  e. F( ]4 C* ^2 b" M
  94.                     keyState = 3;
    # U5 t+ l- t$ W2 M" |
  95.                 }5 a1 A; j" F& V) y7 y, G! }2 v
  96.                 break;$ T6 p$ G$ p! W* F

  97. # V  t, j4 A' r7 E  U
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)4 E. h& m  h0 C( e% o+ u
  99.                 {
    ' a# m4 G5 ^1 L" k* W5 F
  100.                     keyCount = 0;
    8 K# ?6 R# J. f  }  J
  101.                     keyflag = 0;
    * X* V3 {7 G' a- `! ]
  102.                     keyState = 0;
    5 c  Q, ^" i1 X/ E# G2 }: m5 ~% P
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    & V6 _( W% W0 P6 R( w% H
  104.                 }
    . N+ w2 e+ H% B6 f
  105.                
    , H9 I0 e( P* u, P! L0 R
  106.                 break;* v$ L' i" A& H3 Q8 B- B
  107.     }
    9 T9 I* `, I1 ]9 e4 n
  108. }
    6 N3 H. p+ N# T- a( h/ T
复制代码
(2)key.h
* E, Y3 ], {! K. x; I$ Y
  1. #ifndef __KEY_H1 f. g* r3 w4 a! r9 z/ C. w
  2. #define __KEY_H* j6 X/ o& K/ u, S
  3. #include "stm32g4xx_hal.h", O9 T% i/ d4 g# |0 z+ }
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0; U2 D  w  q; C1 n8 R6 J6 g
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB10 Z) E/ b! Q0 ^7 Z5 y- j4 ^
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
      c; e" y6 V/ Z3 l
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0' H# o6 X: G5 L9 A# O' K" H; q
  8. #define ShoutKey1             1
    - z  X3 ?* [. c6 `2 k1 V
  9. #define ShoutKey2                2: k+ j: U/ q8 y2 M+ i
  10. #define ShoutKey3                3* V8 G1 ^! h; ~$ C8 Z
  11. #define ShoutKey4       4
    7 |7 N' R+ N& ~  H0 X0 D/ d
  12. #define LongKey1             56 [" e& k8 ?5 S; C# `- U
  13. #define LongKey2                6
    ( a# A/ P& i( N0 R% c
  14. #define LongKey3                7
    1 X% v  X4 F, J- w7 j
  15. #define LongKey4        8  _) C& ]' c. k& n8 m: R7 [
  16. void Key_Scan(void);
    - z: y) A: h$ f. Y) {
  17. #endif
    1 |: `' Z' u; c
复制代码
3. 计时操作; Q) O% o6 x: ^- [8 z$ _# \
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。( `  t' B/ H' `) \: Q. U  C/ R
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~
' d% |% f( x' p4 r2 Z5 x
  1. extern uint8_t keyflag;2 y( P& x) R* t. S& p3 d/ ^! d
  2. unsigned int keyCount = 0;
    8 O7 @3 }% J9 h0 P9 e$ _
  3. void SysTick_Handler(void)
    , J- _7 U& |, b
  4. {4 f" j$ N6 ?( {1 c' ^0 e
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    . ]$ M' d% d/ E5 M
  6.         if(keyflag == 1) //若有按键按下就开始计时
    4 K9 J9 r2 h# }9 ~
  7.                 keyCount++;        # |) a. g. Q5 a+ C/ E1 g, T
  8. }
    + q, A0 o7 l( \/ O
复制代码
三、应用层简单逻辑实现1 B' U; r% ^$ h" w( c
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~$ a2 R& G4 f$ q8 A  T
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    # G7 q" E* Y5 s& \6 C" ?0 u6 k) s7 x
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    2 z7 g; k5 n0 ^3 z! o( K
  3. while (1)
    0 w% N; @9 U5 O( N
  4. {
    3 {: Y3 {3 F! F5 @1 d' b
  5.                 Key_Scan();1 K" _; l" q0 `0 O/ I; `
  6.                 if(keyValue) //有按键按下1 _+ u, ~; `! _' T4 k5 l' E
  7.                 {
    1 Y/ D& C5 Q. a( g3 K/ Z( L2 y
  8.                         if(keyValue < 5) //短按
    % P/ S5 s+ V7 a1 a* u* ~" l
  9.                         {: r! t: T7 h+ d  [! p/ g& C* b0 [
  10.                                 switch(keyValue)$ [! f2 ]9 A, i
  11.                                 {$ f" ?) x5 z* Z, s) d
  12.                                         case 1:, g, G1 T* \$ G4 c) \
  13.                                                         keyValue = 0;
    , U; z) ~' B7 F* K1 {9 i3 _, z1 P
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);. t# s. y! ?6 P" f; p" @; Q! d
  15.                                                         HAL_Delay(100);, z5 c+ G, Z& V1 I
  16.                                         break;
    . v. R% d  I+ h8 k$ I: Y, y
  17.                                         case 2:9 z& H  r/ V; V, V) q
  18.                                                         keyValue = 0;
    0 s5 R1 }- i1 K: C- P
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    ; D% }' j6 k0 ~! W
  20.                                                         HAL_Delay(100);6 D) Y) p' E5 `  L7 O. T3 t7 {
  21.                                         break;8 F+ v5 r1 M2 r% m
  22.                                         case 3:& `4 n) x& k9 G+ r$ j, z9 B
  23.                                                         keyValue = 0;) w0 w. F" A% n1 y9 G6 l4 @  }
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);& J. W+ a5 G/ I( L
  25.                                                         HAL_Delay(100);  ^6 S/ O$ a% g' S0 }" J
  26.                                         break;: u+ Y6 L; k% q$ C1 X0 @+ s
  27.                                         case 4:
      `: Q5 G/ H+ w
  28.                                                         keyValue = 0;  X' `$ G* y3 |% A3 t
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);! a8 R1 i3 x- D* v: g* i2 k, p9 N# {% C; P
  30.                                                         HAL_Delay(100);
    0 C$ o6 Y: |5 ]! z* H
  31.                                         break;9 O% P; c( k8 s! }, ^
  32.                                 }
    0 V2 W1 q# U* w+ ~% @5 @
  33.                         }5 T# U3 g9 H/ Y4 ^6 Q# i5 y; t1 O
  34.                         else- ]- E  A1 b" t3 j
  35.                         {
    5 ]: o# s+ _( ?% B3 i
  36.                                 switch(keyValue)
    8 P, m+ M2 {6 Z" F$ M( m, m
  37.                                 {  m6 m% m! m1 C. x- L# t- V4 Y
  38.                                         case 5:
    * h% l- ?% H0 z. C/ `
  39.                                                         keyValue = 0;- Y7 c3 w3 e1 j3 q
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    $ }) Z9 B% _* U+ c1 h5 x1 h
  41.                                                         HAL_Delay(100);: Q  `7 N  Q$ [, C0 P& M; }
  42.                                         break;
    5 B3 _4 ]. ]; d/ v5 n) u7 ^; Y
  43.                                         case 6:
    ' ?) I) a% Q! h' d; _
  44.                                                         keyValue = 0;% P+ d) K7 O& A0 H* H( C- f- R! _
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);4 ?$ O! T. H/ M
  46.                                                         HAL_Delay(100);
    ! j2 g5 R# [8 k' _  H, g, F' W
  47.                                         break;5 J7 S+ x3 V2 |. u5 u( F7 \# a, x
  48.                                         case 7:& ^/ X' F' Y5 J+ A. u3 K2 S+ g
  49.                                                         keyValue = 0;
    1 E% |. Q" c% l8 c7 B0 `( u
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    ) r. I+ Y6 ?3 n
  51.                                                         HAL_Delay(100);
    . h. s" j5 N* x, K( |
  52.                                         break;) f. i0 c7 E8 Z7 p
  53.                                         case 8:
    % b1 ^; I/ N) j- i' U
  54.                                                         keyValue = 0;
    . F& W  o8 O, X& V$ v
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
      Z: R; |3 P; z; j/ a. a. b0 b! D
  56.                                                         HAL_Delay(100);' G8 z" r1 p$ }( @! r- E
  57.                                         break;: e8 Z& E& U5 x% J" o7 W) E
  58.                                 }
    2 i1 R& F, t3 K4 d6 |
  59.                         }
    # d5 L# a% Q# R
  60.                 }8 D; H1 S& M6 n2 L& W0 [- c$ u
  61. }
    ( \* @: A( ~$ |7 F/ e2 c# q2 j, D
复制代码
总结
9 P) p9 x" |; s# y# n# c0 I5 p7 {以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
0 f% B6 U3 Q. H0 P) h- |% b3 ~5 j& n' I* V% w; P
: N/ W! H. x/ E
1 i7 K! A, n! p3 I2 K7 o! `. Q
3 H9 k: Q. E& c) P
4 d) L8 f" }; d7 A6 G

# W5 @5 l1 F; l+ d6 l7 A: i/ j6 T/ v  e( I4 N3 \

& h- ?! ]+ O$ V2 w% ^
: t4 X" H& r4 O, g
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~/ S3 f. N& b+ f. k! M

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版