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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
9 S  v9 A7 h4 d2 N& N' L9 H3 ]1 Y) u
前言6 b) k# g6 I# f
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。  C9 Q+ `1 p" e7 M" N* J
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。' ?' {& h- `4 W' B& _* v$ t
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~' Q4 K3 L8 t% }7 v3 ~( O8 r! G: f
6 N2 {( v" r3 G

" M8 A, w& M7 S5 |9 T先放一张开发板的实物图,它长这样~7 r4 n& k0 ?$ Y: G; W& e$ q
15.png
一、硬件操作
' Z7 f# A1 t7 L在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
+ G) F! U, Q" \8 T2 Z4 ]- j
: \) O- N9 C  x( j' b

  j) S! E  \. e3 [1. 原理图1 ~) L# g) S: S. A: r' R; e
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
" N+ ]% U7 x: x4 p1 b2 R. Q8 H  X
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)( }, \0 P" c7 d- f! f2 d  p% x
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;; k6 f/ F0 S* J; g
2.按键相关的IO口:PB0,PB1,PB2,PA0。9 W. H3 P  U8 S  ]% t
* P5 S1 `6 v/ K( x0 W8 w. X# R( A7 D

3 O1 j5 L: d6 N; \: ?' d# t, A2. 硬件分析7 K- H$ @% ?% n0 T4 y/ B
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。7 n1 m, ?& r# u+ J3 V

' n& v+ V6 b) `0 @  i9 L
" W) T" j: O5 G) w& J6 o
3. 初始化代码
: g  I# p) \# q
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */1 T! m1 _; m/ `: k6 M# |
  2.   HAL_Init();//使用默认配置即可  |: K' p& O: O! s8 {& M' r2 q
  3.   /* Configure the system clock */+ L% t( _/ O- Y4 _5 e
  4.   SystemClock_Config();
    : I' T; R' a4 h7 b, W  S9 u
  5.   /* Initialize all configured peripherals */! A$ F2 g' ]5 N# `$ ]: p! `- O
  6.   MX_GPIO_Init();
    ! B/ c% O  Y5 w
复制代码
(1)时钟设置# g3 O! [" [, v2 x+ R( `
这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。1 U. f( V: x$ A4 D1 x. n
  1. void SystemClock_Config(void)5 o4 O# w! p' o, g8 y& ^
  2. {
    5 m% S5 h* g* c! n/ Z4 o6 r
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      `& I, e# O; U6 z) v# C5 P: d
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};( c, W: L5 F8 b! D1 r! e
  5. & V0 q1 O0 k! [7 H
  6.   /** Configure the main internal regulator output voltage
    5 M/ O0 _" ]) T- q/ {) y
  7.   */6 v, `# |: Z; s1 r- C
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);9 y, D8 u8 {0 E' v4 T# W% |
  9.   /** Initializes the CPU, AHB and APB busses clocks 5 c( n" {, B3 D* J; r
  10.   */
    5 i- N1 `# ]2 Y5 u
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;' V* c1 F7 B' u* g1 w5 E
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    & W) n5 u3 [- I
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;( B: t; w# x( j1 r3 X$ A4 R$ }
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    5 Q4 h3 n9 ^" C3 u. e
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;% u4 i/ j2 H; o4 {3 Y
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    ( ]' ]: `! H7 r- l5 K& `
  17.   RCC_OscInitStruct.PLL.PLLN = 20;7 H1 ~$ R9 C4 N4 ~! G5 P% ^
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;, L) B# \0 D- b& F
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    ) _/ Y/ Q4 {: L
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    1 o* m1 }" Z' E* k* Q
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)7 [0 S5 R$ V( T  V9 B$ Q
  22.   {7 r4 @3 d+ z+ ?+ _7 T7 K+ U
  23.     Error_Handler();2 x: ~: J/ e# g5 |
  24.   }
    & ^; q# v2 C# r% |+ a
  25.   /** Initializes the CPU, AHB and APB busses clocks * k; H2 ?9 Y" x7 D# V  d# S
  26.   */
    $ U0 ^$ |" W' H- ^
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK: b4 v, m9 ]9 C3 d* N
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      H, A$ Q/ K- E. L
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;6 I3 T6 \0 ]4 x" c. d. W
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;6 Q- g2 c, P3 I, L4 I2 ?
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;1 n  w# t, c% d: X; O
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;' u* g) [8 P/ U: M: c" o* o$ p

  33. / `& C5 p& B+ I0 s9 E$ S  |
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)( ]3 a! x2 r) P8 j, u+ ^% O6 i
  35.   {  Y) O6 T% z5 s2 Z4 o& y3 o
  36.     Error_Handler();
    6 K6 y( h# y- C0 W3 o
  37.   }) T5 f4 d% Z/ D: O. s  @% ~* B
  38. }
    0 i9 l, J; S7 r# K4 a  e* R
复制代码
(2)GPIO初始化
9 `1 X, e" ^! I* E9 O) l/ j
  1. static void MX_GPIO_Init(void)( h2 I- k- s" ~- _; m% I, h; d
  2. {. f8 ]1 X4 T/ U- n& |. R0 ]
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};: N( k3 g7 }1 V7 T" T  q( s
  4. , r: P7 z6 b; O& _8 Q& T
  5.   /* GPIO Ports Clock Enable */! g2 c- Y9 b, p/ n5 i+ p
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
    % J2 W. K+ O% Y* \2 n: e2 S
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();
    ( r: [' W. G1 Q* r
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();! ~* m4 L6 s- R4 u
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    & b2 E  F& r8 X6 Z; _$ V2 M$ z
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    6 m8 J: X. D# [1 C, w5 J
  11. ( o  c5 ~$ Q( ^& a
  12.   /*Configure GPIO pin Output Level */
    . _9 s: B* T% G" c9 N$ t1 Q) Q
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    - D6 r5 Q( O2 _. G3 b
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);
    ' |! Z( f9 O/ q% u* J$ j

  15. % c# D) w+ Q3 A* X) V" s! D
  16.   /*Configure GPIO pin Output Level */2 N4 v1 u9 ^: O5 C
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);4 R3 d; }; e" [8 S7 w

  18. , D1 \  J" y% A+ s
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    ' l0 l. X6 q8 V% u4 u8 R
  20.                            PC9 PC10 PC11 PC12 */
    5 ?  f! b+ b# T( v
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 4 a) `+ l3 Z- c
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;  o9 S' g6 g+ I. J1 \$ F3 a
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    1 a3 k3 K7 e: y/ c: ]
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;* \6 n& M- w8 o6 Y0 V
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;) k! n) m0 Z2 c) |. F# Y# d* p; a) I
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    . Q! V, n9 ^+ c7 B8 k2 k

  27. ) j# W: Z5 |- O9 n4 k
  28.   /*Configure GPIO pin : PA0 */
    / d  f9 P' v' w7 [
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;7 j' d( q6 o# S( B# b% Q, l! y+ w
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;& M& m0 n; r, P% U: d0 c% V$ r  X
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    8 y5 S" B' K* B- Q' g
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    0 s. u+ L3 Y# D1 i0 p
  33. 2 d! g6 s+ `3 t
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */9 v5 X/ m, h3 s7 _
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;! x& R. f* z! `+ M  m5 [- J
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;+ c$ t5 k' b8 a3 y$ `# ]$ _7 R8 P
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;7 a6 T, o4 C/ J6 E# L# V
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);; i. O3 Y  H7 L' C/ R! H6 B

  39. : m* W* {7 I' y9 s6 h. f
  40.   /*Configure GPIO pin : PD2 */9 I+ W) W) H% _6 h& C- [
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    ( q+ E. D. b; p. D
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;) Y, w8 a0 r* G
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    ' d' A; T6 e% s! m. G" n
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    & s, w3 J" D. a$ ^# F
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);$ [# }. a/ I4 m# z0 x5 b
  46. 1 e4 W: X6 D$ E- k& A- G0 w
  47. }
    8 K; o+ Z7 o5 r/ s1 M. f
复制代码
二、按键模块的驱动层实现
# I/ C) F$ x7 C7 O, T- A' f" r1. 硬件框图
& V; c1 R6 r8 o% d3 k" d在这里插入图片描述
9 S9 A4 H4 n9 I2 a 11.png 8 M' v4 T; F- B" f2 {0 j
避坑点:
+ H  v+ B% D  ]/ e短按:按键释放时判断时间9 {+ q8 e8 g" X& u  z/ Z/ U
长按:直接判断时间$ H9 F: U4 Z, r  R& W/ C6 y

3 H" S3 W- M" H& n/ \5 k
: _. k8 {  [; T( e' c% Y
2. 按键驱动层代码实现
) b. s: g  _- n) E下面直接上C代码:* Z& q; R" l, K2 g  B/ \/ w

$ s8 S# x+ |- n- G3 c

9 {( Q+ ~8 n5 c: v* G& N(1)key.c0 B: Q; g: z* r, y
  1. extern unsigned int keyCount;, H/ c) U4 c/ p
  2. extern uint8_t keyValue;/ d- q- d6 l* V& j4 ]5 S5 F+ _/ v
  3. uint8_t keyflag = 0;0 x1 A( G" r6 M/ R) X7 J
  4. void Key_Scan(void)' L# Y  t1 A7 k) g' V
  5. {
    . Y3 P' W9 J7 b0 _" n1 z
  6. //keyState  按键状态;
    8 U: r0 @' @7 r
  7. //keyPass   记录哪一个按键被按下- s  I% X, Q" W0 _
  8. //keyCount  记录按键按下时间. [$ p. x4 X4 L: f
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时8 m2 M4 H' y! q. O
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件) _  \3 c- k, i
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按# i* L8 ~7 t" ~" i5 ?" S: m
  12. //ShoutKeyx 短按x键值,0 {* M& h1 x7 i
  13. //LongKeyx        长按x键值  A' X7 z4 p* Y$ B9 P
  14.     static uint8_t keyState = 0,keyPass = 0;- F# _$ |) Y, L" F
  15.     switch(keyState)
    " U5 |8 b6 d5 Z* j8 V
  16.     {, Q2 c2 J( P: |% g7 t
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0), a1 N5 S% O, K8 P
  18.                 {, T: S, v4 w. C+ F; `; o
  19.                     HAL_Delay(100);//消抖+ ]7 G: W" b, j; M* s, e4 }
  20.                     keyState = 1;( }9 J( [. o3 T2 L5 r# T
  21.                     keyPass = 0xff; //初始化按键5 q/ h* ^% [' j" Y2 K
  22.                 }   0 K9 R( a3 u, X2 Z' |  }2 P6 b
  23.                 break;
    6 `/ D# Y8 C& z# t1 w; k0 _' V
  24.                     
    ; {& |/ f8 h( l
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    ! P! E, \/ |, w. U( l& M, S
  26.                 {
    ( Z+ g9 T2 t8 A4 G
  27.                     keyState = 2;
    % J( T7 _  X/ X, t  m, M$ [
  28.                     keyflag = 1;//开始计数
    1 h" {6 }! j+ K9 L! m% N/ J
  29.                     if(KEYB_1==0){
    / m" V  U' ~1 c  k3 s1 w
  30.                         keyPass = 1;//返回对应键值
    * Y) p5 C1 A1 n8 O  p5 i
  31.                     }     _( J0 g" r( b) V7 v6 D: k
  32.                     else if(KEYB_2==0)keyPass = 2;; f/ ^9 ~6 c' x" e
  33.                     else if(KEYB_3==0)keyPass = 3;
    " I7 C5 E# C. m: P: @
  34.                     else if(KEYB_4==0)keyPass = 4;% q4 }2 p1 a8 ^8 F( x4 F5 b: {
  35.                 }   # a  Q( J" F; }, ~
  36.                 else keyState = 0;//返回检测按键      
    6 c9 i1 \* w- l* z  a
  37.                 4 F1 n' g% ~% ^  L9 u- ?) V' R7 [
  38.                 break;2 V1 R- u) C! S6 N- m( y7 s
  39.         case 2:
    3 q- L6 b( m; ~( Q+ b
  40.                 switch(keyPass) , Z7 f& [# l, e( O+ p
  41.                 {              & g! K$ Y4 h# k/ E8 ]# [" I7 ^
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    4 L& C& n& ]3 Y3 s
  43.                             {+ h* V% ~4 ?9 D
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按* o8 Y  W# p& Y0 c  K
  45.                                 {- ~( P  T" b% |4 c3 X; q  ]
  46.                                     keyCount = 0;
    2 G+ b1 g) C7 e
  47.                                     keyflag = 0;
    0 j: l2 ~% ~# ]. t0 T! t( ?7 I
  48.                                     keyValue = ShoutKey1;
    " o3 K' L! ~  E$ S4 {  C
  49.                                     keyState = 0;$ D# a) m" G) \3 G
  50.                                 }   
    $ t% ]% w# J9 g2 o( g* C+ i
  51.                             }      
    5 N* m, O% y1 P
  52.                             break;0 V: T5 X$ Q/ r. o
  53.                     case 2:if(KEYB_2!=0)4 W* u2 r5 F  O5 h5 j
  54.                             {9 ?, `# N0 [# N. n: }- ^) S, y, _
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按5 l5 d0 h* i) m+ v3 E
  56.                                 {
    $ J8 u$ d' q* z/ j
  57.                                     keyCount = 0;
    ) P' j  ^- V: A: V6 p1 }  K
  58.                                     keyflag = 0;
    : q8 D5 k6 Q, A" t/ O7 S; r$ i' r
  59.                                     keyValue = ShoutKey2; 6 P1 r9 H- w7 G/ Y# v6 N
  60.                                     keyState = 0;
    ' ]9 n7 i1 A+ _% x
  61.                                 }   
    + V2 a2 Q8 d! Y4 y
  62.                             }      
    2 N! Z, c. M/ S) s
  63.                             break;
    8 J. X8 u2 `' w! W: [' Q+ q
  64.                     case 3:if(KEYB_3!=0)6 H9 j, W3 O& Q4 k. H
  65.                             {
    ! A; x, J4 g" y) C! A/ c. b9 b
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按2 ^) z+ \$ ^2 U: |) E
  67.                                 {1 b" a( @, M- x% x" `
  68.                                     keyCount = 0;  J, U1 {' h! J. y* d3 A2 y4 @9 u
  69.                                     keyflag = 0;3 d9 @# K  v) N: ~2 b6 D# Z: P) w' y0 r' Q
  70.                                     keyValue = ShoutKey3;
    % [0 g! h, N6 y" Y9 ?
  71.                                     keyState = 0;" Q- ~% O! C: j6 x0 o: D$ y" L5 L
  72.                                 }   
    , j. M4 K& F$ O% w: s
  73.                             }       + S/ ^; H' @8 d' s0 M+ O5 V
  74.                             break;; X$ }2 l  V/ A# x
  75.                     case 4:if(KEYB_4!=0)
    : k, b% ]) D5 W. n
  76.                             {
    4 o; A0 c  R  p* [) s( b9 ]
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    $ o/ I+ @# p, R; B# b9 ~! ~( s9 r9 S
  78.                                 {4 ]. c- e' K4 ?3 r' i' q
  79.                                     keyCount = 0;
    ) h; z9 I6 Z# c1 D' A
  80.                                     keyflag = 0;& {/ n' @& Z, n$ K9 M. l/ E
  81.                                     keyValue = ShoutKey4; . M3 E( m, O$ ~/ h- s. M
  82.                                     keyState = 0;
    1 X1 ?- l# [: U
  83.                                 }   
    0 T$ z2 [0 R! Z% |1 |  ?6 q
  84.                             }
    1 d6 _! }2 f! {! V1 C; j! e1 a
  85.                             break;
    7 z, O! A0 {; V
  86.                 }
    ) Q6 p+ ~! z# W
  87.                 if(keyCount > 800)//长按7 s4 w1 Y7 g& S. i( p0 K( j5 i9 s
  88.                 {   
    , [7 b3 d: x9 y- o0 p- _8 g+ _
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    8 A: u7 u1 J# s# g0 u* }. L8 l
  90.                     else if(KEYB_2==0)keyValue = LongKey2;6 r6 h2 H* L% u+ C, C9 F' _
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    8 ?8 {  n0 J, S. I$ j$ h! |: y
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
      C2 P5 W3 X. R: E/ Z3 Q

  93. 8 p$ t  L) U8 I
  94.                     keyState = 3;
    ' @! p* y* v+ R& j6 Z1 ~. p
  95.                 }, E! ^8 o8 J3 P6 t& \1 n$ o
  96.                 break;  W% f7 T7 c# G

  97. & i6 s/ z8 @4 Q% v6 T
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    $ z, _) y# s" e" ~
  99.                 {
    . T# n. }/ B% C* z+ q3 b4 h: T# Y
  100.                     keyCount = 0;
    , q# H) c% h* Q0 x1 h
  101.                     keyflag = 0;4 J* R2 Y' f, |3 s5 d2 T$ T7 p
  102.                     keyState = 0;
    7 }  k: U, F$ r+ w3 p! d: N
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    ! g. V: u0 l* |& p* [
  104.                 }
    7 A+ Q; b* m: f
  105.                
    5 Y2 ^, G# I7 e
  106.                 break;
    * U0 z4 M9 `/ ]$ H3 K
  107.     }
    - i; V1 R1 ^8 y
  108. }
    9 L% [# i" }. x# X  I- A  N: l
复制代码
(2)key.h
# v; A* V" r. ~) V9 {5 z
  1. #ifndef __KEY_H
    ; u  r# p5 L* l7 C- R% X: K# S) ?
  2. #define __KEY_H
    ; `: @. G$ U" o1 i0 k
  3. #include "stm32g4xx_hal.h"4 N+ T! G1 H- @
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    9 D( a$ I: m+ }6 a; m% G2 S
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    2 p) }! C  H0 P6 B$ r* s
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    4 ?/ l; h8 T1 ~. e- n1 N& o
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    ; ]9 A  Z( p& N
  8. #define ShoutKey1             1
    2 z4 }9 h% c7 Q& P0 D6 D* A
  9. #define ShoutKey2                2
    5 U+ Q2 [3 h# m4 p
  10. #define ShoutKey3                3
    ( S$ ~) [+ ]& V2 C6 q- t
  11. #define ShoutKey4       4, a1 s* Z7 e3 U4 j% v
  12. #define LongKey1             5
    ; b! q* ?9 E/ d
  13. #define LongKey2                6
    3 b0 c& f# w4 g2 Z
  14. #define LongKey3                7* @: K5 ~, U' {$ n/ p9 S" x. r/ z
  15. #define LongKey4        8; I- k' v# [  b" [  u  R
  16. void Key_Scan(void);
    7 M6 ~* u) F0 {/ m) N% f$ Y
  17. #endif  C9 R$ h! Q. H0 |) @
复制代码
3. 计时操作
3 q5 {( l1 n  ~( l8 ?' Z# m我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。
: E! @6 h- ]0 [6 B' v! [+ p下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~3 i* I1 I' b# t" Z. P7 A1 ]5 {
  1. extern uint8_t keyflag;
    $ \& E+ j3 n7 Z  [  z8 h6 Q
  2. unsigned int keyCount = 0;5 j$ Z/ ~6 {$ Q4 {/ @) H
  3. void SysTick_Handler(void)7 b7 |% n+ g! P1 u- ?
  4. {
    , j& M5 S8 Z9 v; _  Y+ E! Z! j
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    6 ]) [' Y* T( `4 J  V
  6.         if(keyflag == 1) //若有按键按下就开始计时7 f( V8 Y' s9 e3 v
  7.                 keyCount++;        . c; b4 }0 f! E5 N5 O, w
  8. }
    9 L9 o" y. ]0 X9 _- l
复制代码
三、应用层简单逻辑实现* e9 V" j4 w3 |7 ~' l7 U- A0 e
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~+ Y/ G3 q9 F/ X- k4 l" \: U
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    / H( g& |# B- }. ?. M! y
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器4 \3 ~9 A  u$ e* i$ B. g$ J
  3. while (1)
    7 d1 _8 t# p4 @$ j2 E6 f9 g
  4. {
    * U# h- ~8 t- a1 X3 r( y
  5.                 Key_Scan();" H( e* c- w& {4 X5 K
  6.                 if(keyValue) //有按键按下
    0 M/ J; i0 b! M' ^! K! a: w' H
  7.                 {8 x5 r, {: Z% l& w" v, r
  8.                         if(keyValue < 5) //短按
    ' Q) `. Y; D9 {2 ], h8 S- X
  9.                         {
    0 R7 B8 y( z& ^* M. r2 U$ T& a
  10.                                 switch(keyValue)) ?, S5 M0 V& l* m1 d
  11.                                 {
    ' x9 q; _, D6 J7 U4 i6 v5 ^
  12.                                         case 1:* A$ r% I& G  \7 D. c
  13.                                                         keyValue = 0;( M5 ?  w& G5 W7 \4 z: w
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);1 h4 Z1 k+ z. q: t1 T
  15.                                                         HAL_Delay(100);
    # p- \& K) E8 O) P
  16.                                         break;
    ( X# |- |9 ~" D4 s0 Q
  17.                                         case 2:
    9 u! H1 z: b' |7 @5 I
  18.                                                         keyValue = 0;
    : b  R% T7 a3 ]' C
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    $ ]* C9 T* O& a4 N6 u8 T. o
  20.                                                         HAL_Delay(100);5 x. ^; ?4 Z' c$ C0 N0 s
  21.                                         break;. b3 t! l- O3 p) r
  22.                                         case 3:
    8 A7 H$ g6 K9 u% d7 t4 s$ m4 j
  23.                                                         keyValue = 0;. d& V+ D5 j4 W9 ^( e
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    0 I* d* Y9 B0 A$ t' o' z
  25.                                                         HAL_Delay(100);
    6 V$ f% U7 M: X
  26.                                         break;
    5 a% C. S- X' y
  27.                                         case 4:
    & P6 j, I9 O' F6 V
  28.                                                         keyValue = 0;4 ~0 m) B/ p% L5 c: C
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    & }* k& j, r! ~( z5 C, W
  30.                                                         HAL_Delay(100);( G) }* g# `7 n! D( _+ k9 x" C  q
  31.                                         break;
    9 E3 A3 F! A' p& q( }2 M
  32.                                 }( p6 P! p2 h: }
  33.                         }+ F( f# I, K6 x; h5 E, @
  34.                         else8 K9 N5 O  t% |5 R6 @/ Z$ ?
  35.                         {
    2 D0 H8 C& E6 w6 O( k) n
  36.                                 switch(keyValue)
    ' |; U5 \- G* t4 _7 p/ q7 s
  37.                                 {3 L  g0 r) Y& n9 B! g
  38.                                         case 5:# r- ^4 r7 b% F- X' J5 Q( A
  39.                                                         keyValue = 0;7 y' {$ ]5 R2 M0 N$ m" I
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);0 E5 G4 F9 Q" c$ B1 J  J" O
  41.                                                         HAL_Delay(100);
    # z3 [/ j3 o( b+ e
  42.                                         break;) S5 y* f* b" s; l
  43.                                         case 6:' l% N& @$ @+ I
  44.                                                         keyValue = 0;
    / {. f; n3 V+ x( l1 q$ i. I
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
      y( G# m. n% T! K- s( D6 R
  46.                                                         HAL_Delay(100);, a* u% \" _$ x( ?% A
  47.                                         break;+ K! W- l. h" ^
  48.                                         case 7:
    0 @- q5 L8 l& e$ o: _
  49.                                                         keyValue = 0;
    . F/ R  |* H8 U4 `5 [* C6 r
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);# S9 k) x2 f6 U- J
  51.                                                         HAL_Delay(100);
    3 n; m! W4 w8 P9 b  ^) H+ K
  52.                                         break;
    4 {$ p  Q: S! l) C/ p
  53.                                         case 8:+ ?- M* R) M  Y+ T
  54.                                                         keyValue = 0;( G3 v& s/ h4 E8 l# S! O+ o5 q
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    1 j/ F6 p& M- e6 k! e: n0 o) `
  56.                                                         HAL_Delay(100);
    . ?2 W- C* U  h9 c( t9 b
  57.                                         break;$ A" X. a2 F$ ?* F
  58.                                 }
    6 E% ]0 N7 Z$ X) c/ f; M
  59.                         }
    8 h' w: R7 L5 Q3 ?8 S! t) }$ ~. r8 x
  60.                 }
    ; L6 z0 a& N8 v! }! f
  61. }( s; v* c* G& L3 e0 W) ~
复制代码
总结
, d" z/ r4 f, X7 {( a( c以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。5 y9 G3 |! {0 ~# T; z$ G( h
% c! x3 g) ~! h8 p& V
8 v) @: J) J  ?
# u; K& p& W! s% Y. d3 N& c
4 i0 k" }. U9 |' ?8 k2 D( u

6 B) V0 e0 h1 p% U& i( s% G/ S

) x* j! o( `5 d/ j% U0 b7 A, t1 S6 g  U+ ~0 c- ]0 D

5 C0 ^1 \7 l# m0 F4 ?6 f7 p7 y# v% G% R
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~; H( V% S" ?1 N; R, V& c

所属标签

相似分享

官网相关资源

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