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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
, F: ]8 k+ m' s( g6 p7 F' E- e$ x) r. o) f4 U4 n
前言9 N; I! T  T" T! `9 a
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。
; g) n$ L4 A! p  h注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。* D( k+ e. }/ S; b" M# {2 }. w0 ~
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
: X8 s  d; [7 R9 G; y  V0 S: `4 y+ U: m3 k( `% ^- z
! s3 O. n- T$ L& k& ]
先放一张开发板的实物图,它长这样~
% R2 F! ~6 O5 C6 f1 d  w
15.png
一、硬件操作
5 p; f8 }' I4 f% Y9 C4 z在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。: W1 o  a6 ?* J3 ~4 q

8 x0 t' {! J3 c6 G3 c* X1 P  R
& @6 K8 z0 r6 ~$ g) d
1. 原理图- {% n2 o; k/ v" m; j3 a  _% s
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
2 M% s# h$ U& [" ~3 ]
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)8 m, S$ p. P3 T9 d$ x
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;  T5 W' X0 r5 {6 q6 }
2.按键相关的IO口:PB0,PB1,PB2,PA0。
8 }+ _  w! |0 g: I7 f" X- Y7 x/ ~: o* R! H
+ ^$ s8 N5 C3 u
2. 硬件分析& i8 s* k; t, a  s9 \
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。" R% z: D) _4 \2 A
7 H8 ~4 ]$ _8 o
: P# x) q- s" @; _4 f" y
3. 初始化代码! G! c7 X1 E! j7 f! A
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    $ a+ w5 K* ~8 Y& X. O, r; Y
  2.   HAL_Init();//使用默认配置即可
    $ W) s$ s2 w/ Q. `
  3.   /* Configure the system clock */" a# t! G" d2 ~( U
  4.   SystemClock_Config();
    ( `: n' }  [, U8 d- ?: \
  5.   /* Initialize all configured peripherals */
    + a$ h9 N% d' f& C
  6.   MX_GPIO_Init();
    & u) w) E- D' s4 C* h
复制代码
(1)时钟设置
8 j; i- F. K! @1 g这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。9 d/ Z) w# y1 _
  1. void SystemClock_Config(void)+ h( [$ ?) w2 V+ `
  2. {
    4 j" G& T& l' B0 h4 j8 ^. ?
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};, X4 w- V3 q% z' ]! U! x& `9 r: ]
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};8 G5 U( I  O. z' g1 N; n0 I" H
  5. 1 G' d* |' D- o! A
  6.   /** Configure the main internal regulator output voltage 9 d4 X& O' W0 K0 G1 N6 V$ s; {) C1 V
  7.   */1 T5 }( v' g) i  G2 w! G( ]
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);4 H. q- r. f" P2 b1 P2 j
  9.   /** Initializes the CPU, AHB and APB busses clocks
    ( L# k9 x& f' @. H- m( V. ?
  10.   */$ l6 S2 {) u" O: o0 `! N( W
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;1 _1 o+ q" v, ~/ q
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;5 k1 |; |7 z8 i  l8 ?& n3 k% M. T2 y
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;. D) T. `3 w1 q9 m; i( x8 w
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    $ }3 C9 S3 a- W. Z2 L% ^  r9 j/ |/ o
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;; B1 D6 e1 }/ p2 X& y1 N6 @) z
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    3 @0 Y6 W2 G9 J* D% `1 S3 M- ^
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    6 j+ h5 v9 O( H; c' t* O
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    $ r' c* G# F9 A2 c. `; D
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    + U/ J" F5 e9 Y2 F5 a' @
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    * u0 P( `4 E3 I2 z; Q" j( B* W
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    0 c+ \  P& P1 I( I- U  `
  22.   {
    ( I$ P, M% V, N. @* c
  23.     Error_Handler();' y8 T4 q) ]- i/ U- Y& T9 C9 j& K
  24.   }
    5 Z4 a7 _) }  a3 c7 A
  25.   /** Initializes the CPU, AHB and APB busses clocks 6 n; V& H1 D6 U8 V% n: c+ ~/ b
  26.   */; Y! m+ \" }8 P  @. z# R9 W' D- P, Y
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    ; H! g3 w# s& `1 \% t5 Y6 E/ @
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    ! d5 t. _  S# r4 |
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    / b0 H4 A) w0 j# n" ]! T
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;6 B/ y: J' Q: u, @9 x* O
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;" J+ u' J# c. _+ ]7 r1 z
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    3 M" S& d5 z/ }, d" N
  33. + A, }3 V: R$ B) x
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)4 ]5 F# a1 J; F; p9 Q; n0 z
  35.   {$ Z3 j4 A, y! ?8 Q9 D+ o: E
  36.     Error_Handler();; i2 x! `! Z$ w
  37.   }
    # p  x. H' n" _( O3 D
  38. }4 E* k6 P+ e$ i: j
复制代码
(2)GPIO初始化
) o$ m' G7 v, z0 u
  1. static void MX_GPIO_Init(void)/ q0 C- ~9 B. h- \
  2. {
    : s% c% [5 H5 K0 x
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};: {, Q  {' q- o& \. M: F4 v

  4. * c: f4 @  U) ]9 Y( o# k
  5.   /* GPIO Ports Clock Enable */
    * ^1 t3 E7 e# z8 E
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();  ?- Z/ H0 b# E: d
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();
    , j* f6 z; {9 f* G& z  N
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();% R) |/ u7 ~9 p
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();) K0 b% i1 C8 Y# t* z: y, j
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    " ?2 B0 E/ H& P; S+ t5 n3 H$ U

  11.   g# ]$ M7 w7 b. W2 _9 y
  12.   /*Configure GPIO pin Output Level */
    1 n3 h8 F# Q. v6 N0 |; ?/ u: t
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 # U* C; D; v5 O3 @& l4 E& q- [
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);3 a, E3 w7 H4 Q* }7 J+ |" o( D
  15. & h2 S! ]7 U* x6 T
  16.   /*Configure GPIO pin Output Level *// }: R. i: Y# k+ o2 o
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);& S! J  _- u& j2 ?+ R4 A. d

  18. 5 _" B* Q$ M( X8 q( W
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    5 }  R9 C8 P, C% o7 w
  20.                            PC9 PC10 PC11 PC12 */. a& F! U! X' X6 D; U
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    2 l' E0 x4 a) T
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    : g: _+ g0 M' A1 ^
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    - Q. H9 |! B2 b" j( q7 a; H3 f9 J* W2 z
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;% P) w7 V6 a+ }& B# _$ M* R
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    3 J8 @8 a' G. I! c, L  T. R
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);; K, `4 z* q" f$ D
  27. + I! m1 a* v* n' v  r: ]4 |9 w% D1 ?
  28.   /*Configure GPIO pin : PA0 */
    6 q; S9 Q; W% V1 [; D
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    , k  G1 d! ]- e8 ]" I( x, U
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    $ Q: J  g3 F9 n' |) Y# |7 x% T
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    . I( W  N" S- w$ h8 d
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    / W7 v! @% i) p0 j8 K. ^4 v5 T

  33. , f* d- H3 ~9 O& y7 P2 i; N- a
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */$ ^+ b- A# K! N4 {  ?% O% l
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    2 {7 D8 \( N7 _' [! G9 O3 X
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    3 `( @. _4 x8 u4 z
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    - K3 R# H$ x# w3 ]
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);) [& f' y3 O9 M# N- `, z% e
  39. & a& c# O3 l" y: K7 n: }/ C8 Y" U
  40.   /*Configure GPIO pin : PD2 */
    ; `6 ]9 [' W3 i; U( O4 x1 J
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;7 U1 f- b, d! @9 E# Z
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;7 @+ R, k$ k5 t  N3 Z" a
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    8 z: m- ^$ W# t) M/ [) j
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ! Y& o, X1 d! r( h9 Q2 ^
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    % t8 R  t+ I; N% `5 W
  46. . ^/ D' n4 k8 @  |
  47. }
    - G) ]' a9 p( h5 q0 A
复制代码
二、按键模块的驱动层实现  N3 \1 P% |2 U+ T
1. 硬件框图+ f* Z4 s& f, T6 p
在这里插入图片描述0 s% O& u8 D2 u; ?
11.png
5 H9 I$ Y3 U( O$ ]3 ~+ |避坑点:
8 r3 }2 e1 i( k  t短按:按键释放时判断时间
3 v) H- Y. q) D6 \( ~长按:直接判断时间
1 m" R, Q1 c- b2 m+ ^8 b9 p0 Z
: ~' _% x/ }0 [
8 b7 b/ g/ B6 `. h
2. 按键驱动层代码实现
2 Q; l+ I# ^: ]. K9 ]5 s9 X3 M下面直接上C代码:
, G# A. q- L5 k  V& g
1 u0 q. h: z1 a5 B" s" c" _7 `
, `* C8 i# t. G
(1)key.c) W8 X7 f( @& Z# ]
  1. extern unsigned int keyCount;! D$ C) q! I+ E+ ]
  2. extern uint8_t keyValue;3 A/ @' E' c1 T& x
  3. uint8_t keyflag = 0;
    ) S& w4 W' C3 Y% f' w9 P& j. M
  4. void Key_Scan(void)
    : e8 T5 y/ G, h' R3 Y" L" e
  5. {* c# N8 z, L2 |
  6. //keyState  按键状态;
    ) v# O+ r+ j, T+ K" W% I) F7 h' T
  7. //keyPass   记录哪一个按键被按下* t" u; K' }: e3 m
  8. //keyCount  记录按键按下时间
    : N$ Z7 P: p2 n0 A% @
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时0 B6 J: T; I( ]2 L5 D! Z+ i
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件2 Q: M, b  F, `7 d8 p5 V
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    3 A, E. c5 z; D/ j4 |& O0 S
  12. //ShoutKeyx 短按x键值,) Z( h5 C, O% o; o5 y& g
  13. //LongKeyx        长按x键值7 k5 R8 o" C8 M5 E5 g
  14.     static uint8_t keyState = 0,keyPass = 0;; P, _+ y9 f; [+ T
  15.     switch(keyState)
    : y6 N) D2 _! W! {2 i# l6 L
  16.     {: p6 P& {7 f4 c; K
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    6 S8 p1 `* u7 D: B4 n
  18.                 {
    7 q$ }9 M0 g/ ^. X4 A0 J. w
  19.                     HAL_Delay(100);//消抖
    5 h5 R3 M! ~( v9 G- B
  20.                     keyState = 1;. f* D2 f6 Y3 Y$ u$ {3 L: ?
  21.                     keyPass = 0xff; //初始化按键4 H' H4 H" _% s
  22.                 }   / A3 f5 x- n# G1 ?+ a# d  I
  23.                 break;
    & j# m$ ?  P) A  z$ u$ Y4 Y
  24.                     ; F3 W) y3 H8 ^4 c) J3 L
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    . D! H* _$ u6 z, E3 Y! {! u% {
  26.                 {
    6 o8 O# {6 [+ W$ m' v) v2 ^: t
  27.                     keyState = 2;
    / q8 H: i/ q8 c7 h
  28.                     keyflag = 1;//开始计数
    ' E7 T4 y, P7 k  R1 G
  29.                     if(KEYB_1==0){
      n0 y, i7 e1 P% Z# s/ g( e- W
  30.                         keyPass = 1;//返回对应键值2 Q. R% X+ w) Z+ @" G, ^, s
  31.                     }   
    5 Y9 W  l5 {" @
  32.                     else if(KEYB_2==0)keyPass = 2;8 J$ P' {1 g8 Z2 {* w# L
  33.                     else if(KEYB_3==0)keyPass = 3;0 [. S$ |/ e5 a+ d1 E/ c
  34.                     else if(KEYB_4==0)keyPass = 4;& X  x3 Z( }# w8 Y
  35.                 }   
    + E0 M- P/ n" X, X5 w
  36.                 else keyState = 0;//返回检测按键      
    " R5 s1 E2 |- ^* M) @1 r4 O
  37.                 1 n/ a5 S. J- _/ X, V
  38.                 break;8 K7 @8 m: K/ v, _% ?; h' l; h
  39.         case 2:+ k* Y0 J  W: Z. W- R3 D" b
  40.                 switch(keyPass)
    . A9 B% h1 r4 u
  41.                 {              
    : D/ J" {) j- w" y
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键+ S; x( U' v: B9 x
  43.                             {' v: k0 T2 \0 V0 T% w% z1 d
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按: N! B0 s) r/ ^5 Q# n- R9 s3 @# J
  45.                                 {
    3 u2 \. |1 }9 B9 O! n
  46.                                     keyCount = 0;, ?! S  G$ J5 [$ L6 f
  47.                                     keyflag = 0;
    # J( t3 o6 w, Y6 _# `# U
  48.                                     keyValue = ShoutKey1; * r/ P' `3 j2 X9 X. }. I' F
  49.                                     keyState = 0;* N- o' _0 U% e0 t0 p; {
  50.                                 }   # D  D( r- H* M: k8 e
  51.                             }      
    3 o& ^5 _  V. O7 ]; W5 L
  52.                             break;
    - ~  |, c' f# p
  53.                     case 2:if(KEYB_2!=0)' P9 x+ H; i* J) e# A  _6 ^
  54.                             {/ d' \& g- e$ c+ N2 i
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按9 ]- Z, v+ k+ d2 y2 i
  56.                                 {
    ! I' |( t+ r' ~3 Q
  57.                                     keyCount = 0;
    3 x' m4 G% o1 l7 G& @8 C
  58.                                     keyflag = 0;
    6 J" P7 X* F" U7 e3 ?
  59.                                     keyValue = ShoutKey2;
    % b5 O+ V  t* ?5 A
  60.                                     keyState = 0;
    8 q% o' e. H" T
  61.                                 }   
    ! Y; H! R! `3 x* e
  62.                             }       6 k8 e& @7 y# X0 e2 |6 ]
  63.                             break;
    9 w- N$ t2 I/ H; V1 y0 G
  64.                     case 3:if(KEYB_3!=0)+ _. Y. c4 B3 S! m& h+ W) A5 F7 Y
  65.                             {6 w3 u4 f- P+ Y+ q  V, W
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按
    2 R  w6 D  ?5 q# R) h
  67.                                 {$ h8 \0 I3 B' w4 g
  68.                                     keyCount = 0;
    ( ]9 v  I8 S) W5 ]) z3 B  J
  69.                                     keyflag = 0;
    $ H# @4 z9 D7 J% P$ F# e& O
  70.                                     keyValue = ShoutKey3;
    + S$ E) v) L( k& ]9 u' o
  71.                                     keyState = 0;
    + y. `+ n/ [8 F5 L7 N* T( w$ v
  72.                                 }   4 J, T2 L( ?6 F: v
  73.                             }       1 U$ q  J3 I* z; ^9 y% O1 I) E
  74.                             break;0 x+ Z3 S. h, ?- P% p, M6 H) I" d
  75.                     case 4:if(KEYB_4!=0)* F9 j* m  ?% h
  76.                             {$ f9 T2 ]5 m7 I. @/ r& }: U# z
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    # K' U% \# H' ]
  78.                                 {- ?( X' k% K" M5 N, `# _: W, v
  79.                                     keyCount = 0;! o4 @/ n% V: E5 L/ `, p: x8 h
  80.                                     keyflag = 0;6 ^6 q: W5 @) h, D; u# H/ m; \
  81.                                     keyValue = ShoutKey4; : k# b% F: X- O, ~
  82.                                     keyState = 0;
    # d" w8 }4 }0 e2 n
  83.                                 }   ; z0 ?6 ^$ f$ O
  84.                             }
    3 T- S8 I9 o: H( y
  85.                             break;
    & W9 Z- _' V; p+ T- M7 t- }
  86.                 }
    2 v; V  i" H4 e3 {! b7 F
  87.                 if(keyCount > 800)//长按
    " |' ~  k, |; Q+ `( v
  88.                 {   
    . R5 P5 e' |5 L6 T1 ?
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    ( J+ d6 [; \' c& }
  90.                     else if(KEYB_2==0)keyValue = LongKey2;& o0 w, u: ?3 A! B9 L" z6 J
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    $ g1 d7 }, s8 L4 q" o  D) \
  92.                     else if(KEYB_4==0)keyValue = LongKey4;9 R' w% m' y$ Y. [
  93. # J) o: C+ E+ x4 v$ y2 K0 I
  94.                     keyState = 3;
    2 Z# J  f$ [3 F) P: R/ z3 z
  95.                 }" y- W3 \8 s7 S
  96.                 break;
    + ]$ R- H" C$ f4 _

  97. ) U+ u# M0 b6 z6 c6 X- a  ?& C
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)( N" j6 Z' D( R8 K- A
  99.                 {* j  \1 q2 h$ X. y6 H
  100.                     keyCount = 0;
    2 W3 j, W' b6 E. @; c
  101.                     keyflag = 0;( W/ x0 V+ C9 k  Q" T" Z
  102.                     keyState = 0;
    1 J6 O. v' b( A2 o( Y' {: }7 Q
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    8 F8 D) H0 R8 J* D  e0 W: A. G
  104.                 }
    6 S/ f6 R* t9 b& `
  105.                
    8 U+ H. U2 r# M3 h( y& |
  106.                 break;
    & y; B9 G6 ^8 y* X
  107.     }
    5 S5 O, E# {! K' f, m- F$ A
  108. }
    0 f- c/ O3 d8 N. w4 k7 P: g
复制代码
(2)key.h5 C$ @5 A1 a* K) U
  1. #ifndef __KEY_H/ y/ y4 X+ k; Y1 d0 A' ~4 o% z
  2. #define __KEY_H
    8 \# ]) g! u& p" b6 B
  3. #include "stm32g4xx_hal.h"
    " L8 T, S* z3 i* s5 B
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    2 Z+ A- w% T0 w1 O' W( W
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1* D$ `1 Z! N+ r, Y
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    9 p: P4 A, d, m# y
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    * Y. U( V9 p- o! Z8 X0 b- a
  8. #define ShoutKey1             12 `9 F# G1 D1 n+ K
  9. #define ShoutKey2                2
    , M& `* F! J: k! t$ P  W9 ?
  10. #define ShoutKey3                3* W' F) j5 D1 r0 k1 p# M4 J
  11. #define ShoutKey4       4
    3 o/ o+ R3 C, A0 W2 h8 x4 q1 [
  12. #define LongKey1             5
    + ?: x8 I+ y/ g- Q0 A( G+ r) g3 c
  13. #define LongKey2                6
    5 s4 `: F* y9 r) [
  14. #define LongKey3                76 @, `4 _  L0 m; M
  15. #define LongKey4        8
    0 k- Z4 y8 N7 I5 x
  16. void Key_Scan(void);
    % C, B" T: S. @( y6 \2 w
  17. #endif. K" v% u  N" K4 c  J) v" i; d4 ~# L
复制代码
3. 计时操作
1 m, I) K" A4 t( x. I) p我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。
$ g2 ~# \. i0 G3 e! U下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~5 u8 v. a; U/ K- D+ N/ w; s
  1. extern uint8_t keyflag;
    + |$ I, ?0 w$ I! N7 h4 v- j4 l$ K
  2. unsigned int keyCount = 0;
    6 A) q, C- {: l$ a  |# W
  3. void SysTick_Handler(void)* S$ {, q4 {/ D" B; ]7 |
  4. {
    8 a+ e/ ]  ]! O1 f
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    " F+ C$ Z, S, l5 z8 I" T; C! N9 T9 G
  6.         if(keyflag == 1) //若有按键按下就开始计时- ~& v) @; q4 G3 ~4 o# O6 z
  7.                 keyCount++;          C) |/ z0 l6 [$ T* Y( J( Z: ?
  8. }; U& D) Y' t3 |! {5 E5 h& n
复制代码
三、应用层简单逻辑实现  f" |0 |& T/ t: n1 v
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~1 P, k6 Q& W+ B* p
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 - D9 o* ?+ a  q' f; J; z) B. \
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    ' L" M5 Q5 q4 N, G  m9 n
  3. while (1)! l2 C/ Z3 J( i1 N
  4. {
    0 ^8 f; g. ^, [8 G
  5.                 Key_Scan();+ o& y# G" L( j
  6.                 if(keyValue) //有按键按下8 W* z7 E+ r- Y" v0 L' p! f
  7.                 {
    8 @2 B& |+ z" A/ A6 ^3 G
  8.                         if(keyValue < 5) //短按
    5 y/ O" M8 ^+ t, A, X* L. F4 |5 b
  9.                         {& P" X% [4 X! U9 ?4 ~5 J  _, Q
  10.                                 switch(keyValue)
    + a2 _- e( r( R9 c! o- N7 r# [3 R
  11.                                 {% {0 q. @- M% g
  12.                                         case 1:
    2 F" D8 u2 p1 G" z- ?
  13.                                                         keyValue = 0;# Z* b5 {6 V, W7 d
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    " [8 A! W5 T5 ^1 H
  15.                                                         HAL_Delay(100);" f+ `* Z4 w8 n* D
  16.                                         break;
      H" z8 a( S& i0 c$ b8 v" p6 S
  17.                                         case 2:
    & c! M3 O3 r* x/ A8 W
  18.                                                         keyValue = 0;) h: J* _9 Y' h
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);5 r$ M* a+ O' g4 r2 n
  20.                                                         HAL_Delay(100);
    + M" Q/ B. `; y8 ~$ s5 m
  21.                                         break;, |0 s  q2 H7 r, l
  22.                                         case 3:: _3 c$ G4 D  ^+ e
  23.                                                         keyValue = 0;
    ( p- m, e! a1 o
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);' ^8 o0 M2 U1 J/ D; o
  25.                                                         HAL_Delay(100);
    7 {- @3 E( ~& b5 X6 v! g& ?8 d
  26.                                         break;. L( P1 {3 x0 }7 v0 I
  27.                                         case 4:
    9 n$ L3 u( e' V% u
  28.                                                         keyValue = 0;
    1 h  _8 |$ h2 q) i; I
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    ( L7 C. W! L2 Y4 j! B
  30.                                                         HAL_Delay(100);
    , G: n5 `8 ?8 g2 o6 _' c
  31.                                         break;; {4 L: g* F5 X- j# F1 u
  32.                                 }
    * s3 K2 J: g2 G. C+ q2 c& _4 x
  33.                         }
    6 ?" K' ^2 |9 c: Z
  34.                         else/ |8 M/ s  P1 K4 n$ _
  35.                         {
    6 t6 h1 T8 |7 E5 S6 [0 E  Q- G
  36.                                 switch(keyValue)! n* U8 L# G/ k1 c
  37.                                 {# P% K8 h$ q. Q
  38.                                         case 5:
    ( ?" E2 P. Q; p* i0 ~3 J4 p
  39.                                                         keyValue = 0;- F) e" ~- C, K/ o
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    : f: m9 k0 B* v' C5 [* {
  41.                                                         HAL_Delay(100);6 z7 `) q* Q9 g! B" R
  42.                                         break;
    ' D  P* H# ?2 ?
  43.                                         case 6:! C1 R* ~+ l9 ~& ]- D
  44.                                                         keyValue = 0;
    7 j. S# p  O! n' p7 ^0 s
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);$ i  @1 X9 e- V$ B! B9 \
  46.                                                         HAL_Delay(100);) R8 m5 H+ j, j* U4 D9 {
  47.                                         break;5 s0 F( q) \) P6 h9 o
  48.                                         case 7:7 |& m& U7 o# a2 ^! h% T$ F+ M% C( z
  49.                                                         keyValue = 0;
    : a5 P  ]5 r7 ~- ?
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    . {& c+ x$ A- Z6 H( |
  51.                                                         HAL_Delay(100);
    0 Y7 b  Z0 ~2 o, A# R
  52.                                         break;! T  f4 U' G: v; P( ~
  53.                                         case 8:
    7 C/ z$ X( V. k
  54.                                                         keyValue = 0;
    0 _+ ^% C2 ?7 Y- c1 L9 d/ t
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);& o$ @# j7 l, S6 c# e) R
  56.                                                         HAL_Delay(100);
    6 E* A: {( @# y8 D# H
  57.                                         break;
    # n- b  A9 t& a) |) F
  58.                                 }( L& l, E+ @) N  ?% h% ^
  59.                         }% q0 G6 g! ^/ W0 D
  60.                 }& @* `8 l: z0 Q) k, l! h
  61. }
    0 v8 q" D% V( U' k$ w0 K
复制代码
总结# w  X! e# q3 B" b
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。. [3 x+ \6 @0 P) t, ]

" I. d9 R: b& [8 E3 O

. p4 U7 z% J! U6 j1 @9 M3 T0 Q  i

0 n6 s6 J  Q- W7 @
( H: z* V- h8 i4 A# Y. L, D. z5 Z

" x, O( l$ O8 q1 E* q0 K$ D/ J: Z+ Y% p2 V; i
+ m( J* S+ k4 @! d  Y

4 C- n; \8 c' K) z7 x7 C
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~3 d& ~5 p9 ?% }
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版