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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
+ e5 x0 U+ ^, w' D  \' D- f* c; N0 _1 S7 ^9 K( h
前言) t$ w5 _1 ^+ g+ `2 \/ w1 M  x
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。  S/ a+ Y, l5 D5 D9 w" N, Q
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。9 H# i- g" G5 H3 z8 k1 d* G) h
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
! J( M& o1 Y! B& V7 _) }# j  Y' t/ ^  ]3 M: ^

9 T) l+ M0 u8 U8 ~& h; }/ {  G. p, u先放一张开发板的实物图,它长这样~  L6 w- H+ [: Q
15.png
一、硬件操作
' o; j5 \6 |% M/ u% A8 Q在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
- N( M# u  [5 u
( M! b0 ]( c( R
* |9 |; f, Q8 R5 r0 ^) ~
1. 原理图, J! M# n* q8 K1 Y
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
8 W# D5 C% g: {+ a' w" j6 Q
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
/ ~9 H) a) X, h2 _% T! s- D# s& t1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;5 r- s) V, |4 L1 u7 D
2.按键相关的IO口:PB0,PB1,PB2,PA0。
% a3 Z6 r6 b) X  O. [' v7 J5 B, O$ y7 h' _4 J" a9 ]  l7 k
' D. E' d! Q" Y$ y* H* b  V
2. 硬件分析
' e. X$ w# k! j( X" f8 Q( I0 z从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。2 D  }( h- W( r3 O% I+ d; a: }8 @/ }
$ x6 o3 Q1 ~# k  J) K5 i8 t

+ s( J; u8 J* o3. 初始化代码- f; S  _  _- d$ H
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    9 D& l) X  A0 |
  2.   HAL_Init();//使用默认配置即可
    : V! s$ k* K( [
  3.   /* Configure the system clock */
    ) Y( O) K# b6 C' D, u( p  L+ W- C
  4.   SystemClock_Config();$ x0 k9 ~  g, {6 C$ b
  5.   /* Initialize all configured peripherals */3 o' S3 e2 O+ F  W7 T. r  O
  6.   MX_GPIO_Init();
    ' [, M5 b9 ]4 g8 S3 C
复制代码
(1)时钟设置
# h2 |+ j5 X( c这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。7 L6 ~1 F$ G# o0 g
  1. void SystemClock_Config(void)
    ' D: Z/ d* H) k' A  u$ n
  2. {
    9 `/ t# L2 R5 i/ _! n8 O- }
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    + S* z8 `. X* X) Y- h8 Y( n* d4 o6 ]
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};& r/ k1 H8 L- I# X
  5. 9 q% m/ T8 O2 d4 ?$ l# ~
  6.   /** Configure the main internal regulator output voltage
    ( S% W( ]2 j6 ~* k0 T
  7.   */
    # c# m5 w# T8 t1 n1 N
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);$ H$ O$ L5 x+ A
  9.   /** Initializes the CPU, AHB and APB busses clocks : Z9 {* F- f$ n" R
  10.   */
      w7 h1 P; C6 B7 k! m
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;, x3 m+ `6 ]$ T7 ?% D; C
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;, n* u- e- _+ U0 Q8 U, R- D
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    ' R  T0 Z, i+ M5 n9 S- R: N  f
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;. m4 A  u, L9 _- A' [
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    : J. e7 l3 A  V
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    , u9 D! W7 W2 K/ J$ h+ _
  17.   RCC_OscInitStruct.PLL.PLLN = 20;% ]! m5 z2 m( ~) }& A
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;8 P2 y" X- s. [; `0 M
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    7 }$ p, b$ x6 s$ |, |
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;+ i  e- T6 w! @* G6 a' {+ ~7 d
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    6 h( O# B( s& Y8 @! B% V
  22.   {9 g$ o; G$ t! Y5 k1 l
  23.     Error_Handler();# k, o. N. a2 v7 }
  24.   }% j( h: }, j7 Y  f' F* I
  25.   /** Initializes the CPU, AHB and APB busses clocks
    ! `- ]8 b0 l5 G" M
  26.   */
    ; _# u. [! Z' F/ v
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK. s: F6 e5 n! }  m- c
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;- U" a. f. \  t/ g: J
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;# e& `8 Y" c% ]  a
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;4 m* E, e% F/ R0 j
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;# b' x( t# b5 M, i7 T  o
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;; Y" d4 L+ ^" y4 ~+ M
  33. ) B: L# l  B# K/ k$ G& |
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)! z& O8 q8 Q6 w9 G
  35.   {
    0 \8 r2 B/ g4 y
  36.     Error_Handler();' a' _! h/ G) t# z. K, g; c/ m
  37.   }" z! o+ M) p: |2 N5 G' n6 O
  38. }( e& P0 u# N, C! V% ^# n$ {
复制代码
(2)GPIO初始化7 c$ P  m3 N+ I- }
  1. static void MX_GPIO_Init(void)
    " v0 E4 t7 n4 l0 ~8 k/ M# V
  2. {
    " p( y  N. m2 _* c6 J3 u
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};, H2 \" q1 |) Z) {* J9 a, l" K

  4. . F. Z  F) C9 v! d2 N/ H! {5 n! T, J
  5.   /* GPIO Ports Clock Enable */
    % q+ @4 c) g. p+ `
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
      R& p" l( j) z; l6 P
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();" E4 U& l$ Q9 Z# z
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    * K! I8 }& k% Y4 z+ H% V
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    4 f( b/ t0 W- C: y( k, E% ?
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();6 j$ `  x" B4 C) e' H
  11. 4 q% o1 K; v1 D" Y7 z; X$ [' G
  12.   /*Configure GPIO pin Output Level */
    5 f# |$ L8 b; z
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 0 M- s- Q) e' y0 B
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);% K  Z# _; U& p: D, k

  15. % y5 s# w9 ^' y& o% o, K
  16.   /*Configure GPIO pin Output Level */
      f& E8 L5 O7 {' s! g; m& o: _
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);" p5 M+ Y3 G. q8 m. X

  18. 8 }1 P+ j- G, A: x
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 ' u, w4 Y% l+ J$ v. B! E% j2 l" P
  20.                            PC9 PC10 PC11 PC12 */
    - ?2 `1 N; j6 m$ F2 \
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 & |4 j1 B: M: R7 T, S6 e/ }( H; e
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;& m; H- Z: a/ Z" U
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    ' ]% R2 N. y! \$ T" B
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;% d) c0 }* v6 \3 g4 I  m
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;. x' F5 i1 L. e
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/ U4 C- @& C5 a

  27. % Z2 Y6 R0 m: s, w" {9 z- H5 M
  28.   /*Configure GPIO pin : PA0 */3 M) m! K# g; y% D, o  B
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;  L% H, }/ y; G7 m* g
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;, d. E( Z9 a9 X: O* ]. p: a
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    1 d+ d3 I- a9 ]
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);" O3 B( l7 H: [# u* |& \
  33. 3 Q, z6 }; J; p
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */$ @  G7 \9 C- s: b7 u  f6 Z
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    6 w, o( L2 H' u
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;! g1 z4 P; U' Z( A& ~
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;" K+ k( n) n% s" z+ W- B
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    - H  P9 j, i5 N8 O$ h
  39. , p7 h3 h) V1 E7 N* [0 ]; B
  40.   /*Configure GPIO pin : PD2 */
    7 a, y' a& D) ]
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;, e% x5 N  [5 |+ j/ N
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      }8 F: s/ O% t8 x
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    0 ^: P9 h7 ~4 p! f0 N1 ~  o
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;% K) K- H. ]) [0 O0 _
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    ( j, [, O+ w0 B& H; W$ _
  46. 3 d2 n6 [% _( L( I2 G
  47. }0 C0 U% v2 Q2 S2 Z2 D. f
复制代码
二、按键模块的驱动层实现+ i9 e) L2 a2 u! `& M: ^  {
1. 硬件框图! r4 G8 @2 p, C6 t
在这里插入图片描述
. w3 `+ e" ]$ I! j( _ 11.png 2 G: A+ P- N% Z, ?+ ]* S2 t* |- \7 R
避坑点:1 O7 z9 |: D0 y! N
短按:按键释放时判断时间6 a2 E& C  r+ }3 v" O
长按:直接判断时间2 V( e8 L, H" C6 d% K' ]/ r% H
! f0 T+ l4 `. l! E9 Q

( y1 i/ Q$ b! L9 [4 v2. 按键驱动层代码实现. M3 h) M7 L/ ]: [8 d1 w% s
下面直接上C代码:
. E) v8 R1 Y" r
; O* [& T/ W$ \; h* j, c- c
% {3 j9 W: F- F. K+ }6 e
(1)key.c
! |! t- W. c, ?  |
  1. extern unsigned int keyCount;, L3 k1 W2 {* m( L* Z' Z1 g
  2. extern uint8_t keyValue;2 A6 ?# Q* ^, t# B' ~+ b
  3. uint8_t keyflag = 0;
    , n" z& J" J  e+ _
  4. void Key_Scan(void)
    4 I! f; s% U) H3 G7 d% J
  5. {
    / _* m% f6 Q) F" M
  6. //keyState  按键状态;
    ) E8 J# ~1 L+ `$ k% [5 f
  7. //keyPass   记录哪一个按键被按下; T4 B6 b7 Q! S9 y$ z# z! {
  8. //keyCount  记录按键按下时间- V; O5 ]# i6 u( _) n# y
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时
    0 T8 |- O. k2 ]# ~& Q
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    9 ?8 Q) C, @/ O& H) [) i, ?
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    8 h1 X% ^! D" p7 E6 G1 b7 l
  12. //ShoutKeyx 短按x键值,
    3 ~9 c+ O, @0 c$ X+ b* |
  13. //LongKeyx        长按x键值
      r9 {2 j- J7 v8 m  K
  14.     static uint8_t keyState = 0,keyPass = 0;
    % u5 G1 E; j1 _" l& K
  15.     switch(keyState)
    ) W/ u8 [4 ^/ v9 @5 s
  16.     {7 `1 z8 @2 G" E: _0 D
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)0 H* [5 h$ m/ n! ]) d
  18.                 {
    + l2 }, U3 g; f; B
  19.                     HAL_Delay(100);//消抖
    # h% G( I2 r7 A
  20.                     keyState = 1;
    6 n/ _' a2 ?1 T6 h. t0 U) w
  21.                     keyPass = 0xff; //初始化按键
    ; M% B- V+ G  i9 N7 p
  22.                 }   & M2 P1 f. {0 \3 m5 p
  23.                 break;
    : {$ {9 l2 A$ i
  24.                     5 `5 V3 z( F( N" n9 v1 |' i; `
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    ; [" w: \/ U4 D7 B
  26.                 {5 i( j5 `: E2 p. {" P4 H. T
  27.                     keyState = 2;
    6 `9 g$ ?6 s; Q- X! M. [
  28.                     keyflag = 1;//开始计数
    $ f1 s6 W: A1 n$ P0 [& U4 r( u' Z! g
  29.                     if(KEYB_1==0){8 c8 T' c" c- ?$ V* q2 x
  30.                         keyPass = 1;//返回对应键值
    8 f/ a( J& Y: v1 G( b
  31.                     }   7 f, H- b5 U4 `- m
  32.                     else if(KEYB_2==0)keyPass = 2;5 a6 g. K6 O- l2 @
  33.                     else if(KEYB_3==0)keyPass = 3;# y, y; J* B! J5 R
  34.                     else if(KEYB_4==0)keyPass = 4;
    0 B& Z' l9 V; W$ V  K
  35.                 }   
    , z/ U9 e/ N! P" p* f0 u
  36.                 else keyState = 0;//返回检测按键      ! q3 M3 ?8 \' S9 ?* b4 [6 Y  M+ ]
  37.                 + T2 T/ i0 J* u
  38.                 break;, j: L# D% A6 R" G
  39.         case 2:
    2 X0 {  d$ d# T" x
  40.                 switch(keyPass) & u% _7 T# r3 {% L
  41.                 {              
    : l  Y5 d' \" p1 E4 U
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键" W9 P% }$ S% s5 T
  43.                             {1 Z" s% ^7 n' A& H
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    7 A! l6 R& u$ f7 A
  45.                                 {; K- t1 @) ?, b1 z3 s# H$ h% R2 U
  46.                                     keyCount = 0;
    / B8 c  e. H4 `1 y" [! ]  t  @
  47.                                     keyflag = 0;8 P0 j  p8 E: q) A
  48.                                     keyValue = ShoutKey1; ) V# \4 D; N1 Z' T6 b
  49.                                     keyState = 0;
    ; U6 Y4 ~9 q+ ^
  50.                                 }   
    3 Y9 K; ?& D: Q& h& _9 v
  51.                             }      
    8 h. ~2 u/ B2 n4 o, u1 }+ r
  52.                             break;
    9 c$ @- t: H7 o; r# D7 _! L8 N
  53.                     case 2:if(KEYB_2!=0)
    . r+ n" h, X6 X
  54.                             {) l0 d, ]0 ~6 x9 e4 H+ c
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    9 C; K* s4 n( Z' A" N" k2 T4 \
  56.                                 {' b; H+ |3 d! k4 K7 D4 p
  57.                                     keyCount = 0;; P+ w( ~% y. [. {% H. a* M
  58.                                     keyflag = 0;
    8 J$ ^, Y  X! y& z  Z, Y
  59.                                     keyValue = ShoutKey2;   H+ `+ u: R& T/ N
  60.                                     keyState = 0;
    / [; F% [0 J4 Y* t) f, Q
  61.                                 }   
    " A* j& w' p9 N/ L& w# V
  62.                             }      
    4 w5 h5 x" Q: R; V
  63.                             break;. K; T5 b( S- V, G' D& J
  64.                     case 3:if(KEYB_3!=0)
      U4 U  G1 |# s+ _9 ?
  65.                             {
    + V4 A, F2 a/ i9 V" Q
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按" B/ k6 f, H# c3 ^3 a. `! c6 i& r' X
  67.                                 {
    : N, N2 h, n* O3 e' u' ^  J1 O
  68.                                     keyCount = 0;
    ) E/ M" \- a5 g6 `
  69.                                     keyflag = 0;% u6 L* t$ C2 g- ]9 P$ b! p
  70.                                     keyValue = ShoutKey3; 6 e2 `4 l5 G# c  g5 _/ [
  71.                                     keyState = 0;
    3 Y+ Z' J* e- Y/ d* o( X# R
  72.                                 }   ! b( G' i4 _2 f9 N$ I
  73.                             }      
    1 E4 v0 m4 O5 _. P2 ^
  74.                             break;3 R: X0 b* l/ m
  75.                     case 4:if(KEYB_4!=0)
    9 o! z7 P. H+ f/ W
  76.                             {
    : ?# j! t6 v4 S7 Y, _% y2 l% H' t% `
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按& o! O" G$ H. F# C0 |
  78.                                 {! }" r' F# e. b3 A3 @% g
  79.                                     keyCount = 0;
    ; ^  Q# y6 f; @* Z$ R; M- a5 m
  80.                                     keyflag = 0;5 ]3 M6 P) N) E& X% A* H. h& l
  81.                                     keyValue = ShoutKey4;
    ( q5 E2 W! L- _6 {3 P: p/ }' h
  82.                                     keyState = 0;
    9 m0 J6 c' F& R' Y
  83.                                 }   ( u/ Z4 i% t2 ]
  84.                             }+ |0 N4 k* g6 c+ i
  85.                             break;
    3 \! V% H1 v4 a% {2 z. P
  86.                 }9 q" e' d( D, B/ Y) f
  87.                 if(keyCount > 800)//长按
      a+ ~- _' y+ S# M
  88.                 {   " C2 R9 [( d$ t/ \$ w' t% |
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    " @4 H. s7 u6 H; P6 ?0 o6 S2 ]- |  P; W
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    6 S6 T- Q: C7 q! |2 Q
  91.                     else if(KEYB_3==0)keyValue = LongKey3;: }7 Q9 }8 b! T+ {" ]
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    " l- o' N, U3 b
  93. 7 I4 e/ w0 u) P% r- }. \6 p/ [% Y- c
  94.                     keyState = 3;/ i& E+ X; {5 E3 v# g( |
  95.                 }; e6 E# d  q" m9 W+ `+ m' P
  96.                 break;
    : k- V" s* e+ [8 K
  97. 3 ~- W# g1 p' Y) d
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)  b% y- X1 a% x
  99.                 {9 y! C; h. E& L! ^- Z2 @
  100.                     keyCount = 0;
    # N1 j( D( ]- y( d: H1 c( a5 I+ i
  101.                     keyflag = 0;
    : g! a7 n: D6 Z5 q$ H
  102.                     keyState = 0;& s1 e" \. I2 A
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  6 C8 ]2 M+ X0 d4 T
  104.                 }% ?0 S6 e# |% w
  105.                
    2 ]4 V% i% m2 x0 d
  106.                 break;! M3 R: n6 g0 y% ]; a
  107.     }' y. N9 j) a# K7 V1 t
  108. }; @: z- b# g9 |7 `
复制代码
(2)key.h
, o) a; D5 l9 i: p1 Z
  1. #ifndef __KEY_H
    & w& d8 l1 L3 ], q9 r" U
  2. #define __KEY_H
    - @& M# W1 @( u' r+ g7 }0 p2 _
  3. #include "stm32g4xx_hal.h"
    7 @' s" q. n- S! R6 N" I
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    + L$ z! H% m: X# k( z3 c- x1 H9 n
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    & u/ G+ R6 t8 x+ C) h/ B  x, L; R  o
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2, U2 s* v) o& A/ Z1 L7 n
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0: I# F' r, Q4 G! K- s8 L
  8. #define ShoutKey1             1
    & h# R9 ]. P5 b( |* r
  9. #define ShoutKey2                2
    ; p9 t1 W; A# ]: Q0 o( e/ d4 ^
  10. #define ShoutKey3                3! R  @1 y; e0 \. b
  11. #define ShoutKey4       4; j4 L  E; ?  X$ h
  12. #define LongKey1             5
    : ?5 v- A- H9 H! S, z3 J, D" ~& ]
  13. #define LongKey2                64 p% t4 g" y' @# c% l
  14. #define LongKey3                7
    / }8 ^& p, C; S" r
  15. #define LongKey4        8
    . ]" Q4 m) k- j
  16. void Key_Scan(void);: w8 [0 t1 l, V
  17. #endif' s4 h' g8 _2 p& g& e3 D' V
复制代码
3. 计时操作* {# g2 w0 h" K& H: I
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。# H+ A# D& V4 a
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~
7 }2 s" @9 d& t! S4 f
  1. extern uint8_t keyflag;. t' h' ?7 J2 y3 b5 q( z
  2. unsigned int keyCount = 0;
    . }) r5 O4 L2 x+ t! j/ B1 I
  3. void SysTick_Handler(void)/ f3 O9 I* F5 Y( P# o$ i8 H
  4. {
    ! A+ R  P1 f6 l. n" T  y( |
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    8 }* {2 f' C9 U, ]
  6.         if(keyflag == 1) //若有按键按下就开始计时
    5 |1 I4 ?7 @9 z) G& B3 Y( M
  7.                 keyCount++;        ; L  a) j3 V" A+ x% u" a
  8. }
    & [7 ^3 c; w( H" S1 ^9 m# s- |
复制代码
三、应用层简单逻辑实现/ f+ m( N2 B5 P7 ^6 f! C+ g
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
* Q3 t0 }; l. D. m- \  K
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    6 X2 {# ^) y$ a3 N2 G# o
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器3 e8 ?2 d8 b! J8 f
  3. while (1)
    3 [( m+ n! }8 N  G, h, E- C
  4. {
    2 N1 @$ M6 J0 R
  5.                 Key_Scan();6 T7 ]8 t% M+ T9 A2 p4 M$ \; J
  6.                 if(keyValue) //有按键按下. z: @- U, F+ I; A! \" z6 ~1 d/ P, \
  7.                 {, M. }4 }( J. j: n
  8.                         if(keyValue < 5) //短按' d2 R2 L% ~) g5 t7 U
  9.                         {8 N, Z  j' W: [& t2 p& ^/ ]. O) x
  10.                                 switch(keyValue)2 ]: t* `/ V: n* }+ Q6 e$ W
  11.                                 {
    . Q; d7 h! a. N; V
  12.                                         case 1:# d8 z% g  x, J7 |5 x
  13.                                                         keyValue = 0;
    , ~# j! H/ V5 `5 A- K8 e: X
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    " t# R# m7 N" l0 N6 y
  15.                                                         HAL_Delay(100);
    6 u9 l9 c: g; O. G) F3 k8 `
  16.                                         break;3 u# {& e. y# a8 W' [9 O) A
  17.                                         case 2:
    7 w6 J3 t3 ?. {( g) W
  18.                                                         keyValue = 0;$ K: ~/ u( T% K; j
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    " F9 _' w$ T+ ^9 b
  20.                                                         HAL_Delay(100);! I1 E% \9 `" n. M$ C8 @- ]% ~2 ?. N
  21.                                         break;
    / Z) I4 B9 g* i# B
  22.                                         case 3:* ^/ G) q5 I6 [" [$ r
  23.                                                         keyValue = 0;' l7 C. @. f  u2 ], S% s: B
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);& }, Z7 U- T3 ?% n3 i
  25.                                                         HAL_Delay(100);
    & s1 R/ Q: \4 w% o; |
  26.                                         break;7 z& M4 t' L6 I+ R- c2 I
  27.                                         case 4:
    ! f' P- d4 A% B" K5 w
  28.                                                         keyValue = 0;
    $ `: }) u: n& E" }9 }( H
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    6 r3 S5 Y' Q. u; G+ _
  30.                                                         HAL_Delay(100);1 [! g: o& H0 M$ {
  31.                                         break;0 ~& `+ q) i! _! ?. b
  32.                                 }
    % E; |2 u/ e; X+ {
  33.                         }
    * x: G: D0 r. v8 J; k
  34.                         else
    . V' v4 x- C: O) s
  35.                         {
    9 K/ l! l: g0 Q1 d! x
  36.                                 switch(keyValue)
    % F$ @; o- V) U/ z
  37.                                 {  U, x* I+ ]7 K* u# _
  38.                                         case 5:! G! {  H3 s5 i7 s; s. {
  39.                                                         keyValue = 0;9 v" o0 h5 a' s% n! G) F% o
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    7 Z' }! I* B2 m  `, a+ M* d
  41.                                                         HAL_Delay(100);
    9 b% T5 @* j6 k5 M
  42.                                         break;6 A( q6 U) h7 Q% }4 h8 ~" o
  43.                                         case 6:! ]* W" ^% v- g, M! V5 U! l
  44.                                                         keyValue = 0;
    - f- ^$ s2 @. @$ l) A+ K
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    & t: p& v; M. x) S
  46.                                                         HAL_Delay(100);! j; e; z0 K6 I1 F: v3 u
  47.                                         break;
    # \5 t3 H" J& E  t
  48.                                         case 7:2 p, J4 U: p# X) }$ E" c
  49.                                                         keyValue = 0;
    # E. v& F% Z3 b! a+ O- m2 E- q
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    5 {# g1 E9 x( `% c+ t
  51.                                                         HAL_Delay(100);
    5 J, N3 N) t, o5 Q4 X
  52.                                         break;' q: i$ P0 j/ T
  53.                                         case 8:
    8 n/ e6 I4 m& A  A" Q1 L$ N
  54.                                                         keyValue = 0;) k8 Y. f  ^( c
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    ( C: K* i9 o) G" M- m
  56.                                                         HAL_Delay(100);
    1 b  r6 K& ], p6 G4 r: }) b
  57.                                         break;9 F& e7 R" l& {# ^
  58.                                 }
    / w/ p& z! @0 G& r4 a+ w
  59.                         }! v1 }) [# l- h) }
  60.                 }- p: M, h' \3 |: x. [
  61. }$ B1 p+ G9 ?* b4 c
复制代码
总结
& w- Z4 x) k, q8 o7 J以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
  o# J# M$ [; _3 B2 v) }0 I% q- |/ G/ s6 h0 A* J3 q$ W
2 \* K. {0 o" @( g

( z6 |* O" ^0 \

" f8 t% b% p) k- I  }6 c, D0 r& H0 i
7 H; K! l# Q1 f2 x& T  N9 ~0 q

7 T& l# l" }! c* ?9 Q
( {5 f% C! M1 p: \# h3 ^

0 s: A- f! S' y+ }, C* |2 w
赞 收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~! U( r" n& {6 s0 c+ D5 e- }

所属标签

相似技术帖

官网相关资源

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