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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块4 o( e0 ~( }# C5 t( k

0 q) U0 r& j0 M# j$ \4 Q% u9 t前言
4 p$ |7 y! e6 F+ b% N/ y我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。, C# L) j" B1 Q% x; e( O
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
% i- g; s0 V9 R% v5 c0 [% f3 Q; M8 s由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
- F! `& C0 e6 Z' J' E# @& h2 T2 |. P" P' c7 q) e! L# ^! l* Z8 Z5 t
9 b8 c+ d) _, c) E
先放一张开发板的实物图,它长这样~$ z, h& G$ b/ e% p
15.png
一、硬件操作
2 s! p5 h* L" p) u+ U在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。* l0 P8 h% m7 `% G: @, \! {; {" n+ ?4 K
# ~/ J4 {+ X! [& o7 F

- }, q! }( ]) e' t: N1. 原理图1 S" H% @  F6 m  o# h$ g
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
. j( F" c) @0 V
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
  Y/ q, V! d0 t) J8 q1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;1 Y9 v0 {5 x) E& `) U% t" _
2.按键相关的IO口:PB0,PB1,PB2,PA0。
* |  {  l7 \3 g$ T: K$ p' Y2 b7 ~# Q
) O" Q, e5 b# @1 C$ s1 E! t' V( E
2. 硬件分析
0 c4 G/ d, {- v" m! ?从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
' m/ o; B7 i2 i5 s8 d) c9 ^
* q8 ^* k1 b% C
, i9 ^8 \+ s0 w
3. 初始化代码, G9 l5 K2 `1 j9 B1 [( `/ x
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    8 ^* w3 k# C' h1 _" Q7 H
  2.   HAL_Init();//使用默认配置即可0 }/ R4 x( \, ?. R7 ]) D
  3.   /* Configure the system clock */
    0 ]0 H1 f( l+ ]; X8 w4 `
  4.   SystemClock_Config();
    ; h: s5 [0 x0 r* d- }- N- @8 _
  5.   /* Initialize all configured peripherals */9 g7 y: P/ Y6 p: ^, T" u4 j7 b
  6.   MX_GPIO_Init();
    , [0 d# p4 o4 v- C. W1 i* t) b3 ]
复制代码
(1)时钟设置
" I- i. X. _- X5 T这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
2 m. A& g+ f; M2 _; i/ Q9 S9 u
  1. void SystemClock_Config(void)) m+ j  Z/ [9 R
  2. {
    1 d6 a- m( ]/ w! {) W* H
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};5 @# ]5 T' G. \5 L
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    # f4 f% U* Z( ?! `/ D* a# f/ O* I" O
  5. ! r, |8 _  j9 [, t1 D, z
  6.   /** Configure the main internal regulator output voltage ( V" V% Z- v' ~% p+ c! Q
  7.   */
    ; p* z5 ^4 C8 o1 {% q; A
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
    8 |" G+ b* {, J) B) I
  9.   /** Initializes the CPU, AHB and APB busses clocks
    & A: ]- M3 J, b9 @
  10.   */
    & f) |4 p! s, W4 z
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;3 A, ~% ]3 e2 M: a2 }3 W
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    # x4 R* I$ T& M- n7 R7 @, g1 v
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;: _2 E4 F5 |+ c, Q) J
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;+ t; k+ B' h1 I1 r0 h. ~/ i9 f- H
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;4 A% d2 p( _* L. s5 k4 b9 P
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    # h0 [  o5 z) d, J& b$ B
  17.   RCC_OscInitStruct.PLL.PLLN = 20;) F. T6 f# s! W1 z- B
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;; P5 S8 X% C& w4 s% u8 w
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;9 C6 {, Q8 c' v8 y- y1 f) ]
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;! m5 e. o& Q! B& J4 b
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    + u( V7 ]- b$ w) A
  22.   {
    + ~5 C3 p5 m- |$ s/ P* a
  23.     Error_Handler();
    / b( K4 }; Z. O8 P
  24.   }- u. P/ u" n, G: o5 \" F% S
  25.   /** Initializes the CPU, AHB and APB busses clocks
    ( N, ]) x8 w( b- ?
  26.   */' q2 |1 J7 e) N
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    5 f6 n! G) ]: q/ p
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;; q7 S6 ~4 y$ x) s% W; D+ S
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;& W  O3 T  k# b5 t9 B( z
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    ' `$ X* O( |' u! B9 d% t0 n8 k" v
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    3 g/ b, f+ [. |4 z
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;" R  P2 K) y" Z9 |0 |% J

  33. 1 m- n) S) u0 Z4 t" i& p# @, O5 P& g
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)5 j; Q% w  `; n$ D- H: n
  35.   {  m* e6 W- ~: ~. X/ q- k( u/ n
  36.     Error_Handler();) X; Y. n) K( L9 M* T
  37.   }2 f% M: z' F; B/ _9 p
  38. }: k" C/ E5 R0 J: i! C
复制代码
(2)GPIO初始化
7 O7 T; j- c5 g, }% h% f
  1. static void MX_GPIO_Init(void)
    7 z; }  @. a1 Q/ G" b2 ^% C
  2. {3 q: u0 }2 g6 ?5 E$ C- f3 N
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};4 D5 U" x. I$ ?- ?' L2 y" W

  4. ; ?3 D3 [6 v" ?4 P$ q5 a( C: D3 \
  5.   /* GPIO Ports Clock Enable */7 R2 ~8 E6 D" o: q; h2 B
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();6 o9 `* }: W2 \9 z5 [
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();
    ! T9 ~& }- b, l# l) I' m$ T
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    / E, o3 F( `, {$ S# B( Y
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    9 Y. s" O+ q6 g- q0 O: j9 n
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    . l+ F9 W% ?# L& m+ z- C+ e

  11. 1 f0 D7 w$ Z( \) F
  12.   /*Configure GPIO pin Output Level */1 z# x" `; ^. z+ ~
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 3 i: y' y: C5 m- u; P
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);  k4 e/ s- I" M4 w+ ?/ }
  15. 6 _% }5 n3 r1 P( X/ O$ N
  16.   /*Configure GPIO pin Output Level */
    + f+ R1 O. J3 O& h- f' k# Z% P
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);: I, W1 C1 |6 A: J- p. z
  18. 9 I  u5 r$ A' ^# G' x
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
      p5 K- Q! F7 n. i. A( o, e  T  J
  20.                            PC9 PC10 PC11 PC12 */
    ( d0 h  S) q: K. o. W$ q$ R4 Q- L
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 5 @7 D1 d. t' h( {
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;+ l& {: y6 U7 u, ~
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;/ ~( h5 b- x$ _9 T5 C4 n+ `
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;( i$ c( w- K- l8 j) u" G% A. h
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;, G4 T) U' ?+ O
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);4 b5 o' j, `( Y# \$ J0 a+ B! X

  27. & X5 [# {+ Q% m- D8 t3 N) u7 _5 Y
  28.   /*Configure GPIO pin : PA0 */
    # d3 Z! L' p( m, E2 P# A
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;9 Q1 C5 m8 g. }/ h7 ~
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;7 E& O- @( w7 o) a3 _% `
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;" i. P. ]7 u2 _/ ~9 m- ~. ~
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);% J( I4 a- A7 o9 `6 t
  33. & g7 Z' ?, J& q1 g
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */6 l" v" S5 [0 f+ p4 o
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;# z- z7 w3 k0 G! w7 j& u; E  |6 q. H
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    + Y- L4 O( \1 T$ D7 I
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;8 e; t# A( c2 i: q8 s# [
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    ' M  X. a8 _: Y" x, E  O$ r4 r9 ]: U
  39.   E8 J* `; `, u( {
  40.   /*Configure GPIO pin : PD2 */' q- @/ R* w3 I+ x$ ?
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    6 X) e0 G/ F0 ^
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;2 _  S3 a: H/ J# x
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 h; V3 ~, D* h2 A7 b, D! y3 Q/ D
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    4 {. T  D  Q; j+ T
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);4 H) d- `5 d7 {) C- J6 ~' w
  46. : U8 j; c: B; T8 M
  47. }$ k: r. P4 u$ \- ]$ P
复制代码
二、按键模块的驱动层实现
% ?  |! _3 ?+ }7 Z3 @3 m1. 硬件框图/ a2 E4 l3 `" Q) [) H5 {3 O
在这里插入图片描述
) W, `  ]2 v% U9 k" x 11.png ) Y8 r. }+ t3 B
避坑点:4 n: z, n; x/ Y4 T" V( a' o/ A
短按:按键释放时判断时间3 ?7 r2 ?( D! _1 Z! G4 E8 E
长按:直接判断时间
% o4 X% a8 y- w) `! ]- v* V8 u- \; f! e- T* q

% C7 t& r1 _- w; m( r5 F  U2. 按键驱动层代码实现
. y4 l& ~# u* J9 U) r- w下面直接上C代码:
6 v$ @4 [' N; k; E3 y# K% f5 B# p5 Z7 L' T( q8 k
4 |* p' ^- l: i) q. v9 g  t
(1)key.c; G! J; q8 {' q* R& ~% [' W* e' A8 U
  1. extern unsigned int keyCount;
    / q1 x. Z/ Q, I+ z
  2. extern uint8_t keyValue;% M+ ^3 Z1 X2 P# G  i
  3. uint8_t keyflag = 0;
    8 J! |8 G' N, R: i
  4. void Key_Scan(void)( ^: E; }" g+ q3 l9 q; P
  5. {
    + W: y: P9 {* `9 E& i
  6. //keyState  按键状态;
    $ x3 C" `# [+ v. {# n* C8 O5 u
  7. //keyPass   记录哪一个按键被按下; |" V' q! p0 w$ r( g
  8. //keyCount  记录按键按下时间
    ; v3 t" @) I! E% o
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时2 o+ g# I" M1 ]& y1 r7 G
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    6 c* p; }7 z: ~8 |, h4 P
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按( z8 W- j  m9 S1 e( H. {0 P3 y
  12. //ShoutKeyx 短按x键值," ?/ {+ A; [* b' r1 F) N
  13. //LongKeyx        长按x键值
    5 G( Q% |3 J, x# h; q$ H0 U1 b
  14.     static uint8_t keyState = 0,keyPass = 0;
    1 ~( _* q( ?( ~6 u
  15.     switch(keyState)7 G( \9 H! Z# _( u$ e8 Y
  16.     {2 ]/ d7 F& `6 |1 n% \
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)6 `5 G# i$ g8 D! Y8 Q2 e
  18.                 {4 m# m4 n  ~  j1 V5 j
  19.                     HAL_Delay(100);//消抖! N( @  H- B) x
  20.                     keyState = 1;
    9 F1 o5 B/ D! r
  21.                     keyPass = 0xff; //初始化按键
    * {* N) Z: Q; I8 O. c+ \# u5 i
  22.                 }   
    ) L# W0 o) D, w+ r* R
  23.                 break;: B4 _0 J4 ]' c. k- `1 D
  24.                     
    ' m! x4 M0 D' i% ^' D; B8 R. C
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    2 K2 Z  P1 r; D& |$ x* C  r
  26.                 {6 W+ E1 v' u7 A
  27.                     keyState = 2;, v) i7 o' ^5 V- Z7 I& F
  28.                     keyflag = 1;//开始计数
    0 p0 X' G5 F/ `
  29.                     if(KEYB_1==0){
    6 c5 M, l" [, v& V( E" e- _
  30.                         keyPass = 1;//返回对应键值
    $ \8 z, Q$ y3 F
  31.                     }   
    2 _; Y8 Q- @3 ~3 o- }8 o
  32.                     else if(KEYB_2==0)keyPass = 2;: L9 a5 ~& X1 K5 w8 [, M! L  x; U
  33.                     else if(KEYB_3==0)keyPass = 3;
    1 Y5 B3 f+ \! B' J: J
  34.                     else if(KEYB_4==0)keyPass = 4;
    ( a8 d/ F5 }$ g& i' c  s) a& U
  35.                 }   
    ; i" G0 @3 Z+ a$ {- i- @
  36.                 else keyState = 0;//返回检测按键      8 z) P5 }* E4 l* Q* e# m: d1 h
  37.                 - t2 O3 Z( }* p) b6 W
  38.                 break;
    : N' Y8 i& c4 {0 y$ {# f
  39.         case 2:
    , D" G  A2 ^) G. y+ D3 w
  40.                 switch(keyPass)
    # W/ g, `- B8 O
  41.                 {              
    0 q3 X2 K" E: G! \: y
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键! ?4 e" L7 X- E
  43.                             {% J% W5 B, z+ w7 |+ ]4 Z( E4 v
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按- U' k6 m3 Y7 ?. x8 p5 o
  45.                                 {$ h) B3 M* s* _+ |6 d7 b
  46.                                     keyCount = 0;
    2 ?6 ?5 \$ @" X
  47.                                     keyflag = 0;
    9 Q0 e$ S- w( d1 c7 ~% e
  48.                                     keyValue = ShoutKey1;
    9 s) v$ N& j, ~' l
  49.                                     keyState = 0;6 M+ j9 m6 v  s4 L) k" Z/ ^: u
  50.                                 }   0 [: |( C4 _+ @$ J
  51.                             }      
    - Q2 V3 \* c1 C: g3 _
  52.                             break;
    3 R3 v- ?, Q( }% P
  53.                     case 2:if(KEYB_2!=0), K9 }% `% v+ a  A7 {
  54.                             {; o) {! T( r$ h
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按& Z! O( H% H" l( y$ B* a! Q
  56.                                 {% E& i9 _$ Y* R( e" G5 p: G' y
  57.                                     keyCount = 0;
    3 S* g" f& b4 Q3 k7 C4 B
  58.                                     keyflag = 0;
    3 I5 `. y; W9 `& J( _6 {  @' p; x
  59.                                     keyValue = ShoutKey2;
    . g; d8 p/ T) A7 A' D
  60.                                     keyState = 0;% T' K4 j1 T9 N) R4 q, G5 |
  61.                                 }   
    6 g9 t& Y# E! Q5 q5 M+ H7 e
  62.                             }       9 A9 y) {+ h+ D! X" n+ U
  63.                             break;6 f8 O3 I% C' E3 }5 X0 X: x
  64.                     case 3:if(KEYB_3!=0)
    1 K' d8 P+ |; i0 |7 O
  65.                             {+ R& U8 G( L/ T- g2 D
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按7 U7 v4 ]3 {. s$ \
  67.                                 {
    4 N; c/ `% e+ ]- }. Y5 t
  68.                                     keyCount = 0;
    ( r9 c6 j3 E  k7 W/ |; y" C
  69.                                     keyflag = 0;
    / L1 f1 ^- ~+ Q9 ^7 U
  70.                                     keyValue = ShoutKey3; 5 P" l& T4 t9 l! ^7 w
  71.                                     keyState = 0;
      R. Y4 }4 K: W5 i! i% `. `
  72.                                 }   ( C/ j9 f" k+ R& A& |
  73.                             }       & @" w" P! L: O, Q+ K* p  `3 g9 v
  74.                             break;7 L' e, H. G# w* O# E
  75.                     case 4:if(KEYB_4!=0)
    + m* p. A$ B" D5 \8 _
  76.                             {. N8 h) t7 g+ t% A! F# v
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按2 n( `& ], U: M  J. W! b
  78.                                 {2 {; G' V7 [% e5 T
  79.                                     keyCount = 0;
    5 S; ^6 `' A% Y. o7 f5 i; s
  80.                                     keyflag = 0;' k) u5 _$ _! R' J9 c/ B6 c
  81.                                     keyValue = ShoutKey4; ( O4 M2 X- W( f
  82.                                     keyState = 0;
    ' c6 p& O% t# O9 E, u7 V6 ]
  83.                                 }   
    5 p: G# l, N$ H
  84.                             }
    + X" _9 ?! E) s1 T
  85.                             break;
    : J$ ^( P6 g' P1 a
  86.                 }& r5 Y% z  c. G$ y1 M7 i0 z/ G& t
  87.                 if(keyCount > 800)//长按2 J+ h5 B/ E2 C( C+ C4 ]( m
  88.                 {   
    9 {: E" e% X% i0 s
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    . x# V& U; k- P
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    6 w  f4 ~' t2 b% C# i" N
  91.                     else if(KEYB_3==0)keyValue = LongKey3;' B. X  q: j; c8 z$ f& _* [
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    0 J( m% t/ F4 v* q# |9 h
  93. 9 f9 `9 {  l1 N3 K& n
  94.                     keyState = 3;
    5 O4 f- d8 ^1 @
  95.                 }
    6 I9 w/ ?+ a, {
  96.                 break;
    3 }* s5 m6 }) n- q! M0 t  V5 I

  97. - i" R- R+ t# ?
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    6 W; |2 ]: c( Q& C( A+ Q( B
  99.                 {
    & d. I% Z0 c& K3 M8 f" A. \
  100.                     keyCount = 0;* g6 \& k# q$ `" O+ C
  101.                     keyflag = 0;& _# ~) P3 R: e/ s
  102.                     keyState = 0;
      `" Z+ ?% w! i
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出    ~: x3 H6 o/ H! i) @* U
  104.                 }# k2 L  f2 ^0 J9 j" F
  105.                
    ( M; b+ E2 k6 U
  106.                 break;
    * M5 S/ U  d/ h5 f
  107.     }
    * V% o, t$ u7 P
  108. }% E' C5 t2 p! Q$ M( o1 n
复制代码
(2)key.h' b0 @- i5 w$ S1 r5 ~. _3 |
  1. #ifndef __KEY_H
    ; R  @1 m8 G9 }. A; F0 ]- n1 c5 X7 r
  2. #define __KEY_H8 p+ e- M8 P* {2 [$ g* Z2 B+ r+ w$ |6 R
  3. #include "stm32g4xx_hal.h"% q) g! c& v' o2 \2 M$ t6 A
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0& ?1 k" W! r# l' k+ t
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1% l$ Q2 |! F* m. e: M- c( t
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2; a/ y' H2 N. ]% x3 q- \9 C% X
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA07 d+ ?6 X8 _* E; F8 n4 Z- r
  8. #define ShoutKey1             1
    % d9 o9 F2 |) ]: m) b. E( t
  9. #define ShoutKey2                2, X3 [% I5 L- M, D' J' _) Y$ [
  10. #define ShoutKey3                3
    - g. X- \9 Y1 x1 |4 m  W2 W
  11. #define ShoutKey4       4. I  S0 \7 d0 t
  12. #define LongKey1             5& `% b; ~& X3 t* t6 U$ N" y
  13. #define LongKey2                64 e4 a/ b# O- R4 @- k
  14. #define LongKey3                7
      s- s1 E9 b8 a% X( i2 z
  15. #define LongKey4        8, c0 a! ^2 c9 H8 \6 L0 s  N
  16. void Key_Scan(void);  K( R, u2 O; h  N. g) |
  17. #endif/ [: B+ I3 m3 `' D
复制代码
3. 计时操作
: ]& x: N# O5 ~( `/ D7 J我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。/ |. f, J0 H2 ^" G; J; n2 K
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~8 \5 v7 x) A( v' J- A' y" Q
  1. extern uint8_t keyflag;
    6 n* C! u0 [; T
  2. unsigned int keyCount = 0;- u8 u+ ?$ {1 u) Y5 V: ^" b
  3. void SysTick_Handler(void)) ?; G- ?6 c; w( ]1 U2 A, i
  4. {
      u2 \' `; W* d+ S* B2 {
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    6 g4 `1 ~4 X, W6 w
  6.         if(keyflag == 1) //若有按键按下就开始计时
    # e! q0 N! p1 p2 @; }5 e$ y9 E
  7.                 keyCount++;       
    - c4 a/ P/ D, R( }
  8. }
    - ^7 l7 M( \$ ?$ s2 v0 m4 M: f8 X
复制代码
三、应用层简单逻辑实现, k8 f+ k3 a- \4 r* p
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
9 O0 e: y; r2 g+ ^9 k5 P
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
      X: O4 j, H7 X; C, O% {3 W
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器% k) ?" \( Q( s( s$ m8 `" B6 J. ^
  3. while (1)
    ( S& J4 k2 Y( X5 V# g/ q
  4. {7 _4 M. k9 V6 M$ l% |
  5.                 Key_Scan();
    0 m6 L5 b" J8 r& X" |* X! Y
  6.                 if(keyValue) //有按键按下
    ! v2 k8 Y! o: w. \" ^6 h! h
  7.                 {7 Y& c" d. m7 {- a. C
  8.                         if(keyValue < 5) //短按) f0 {7 q* {' T$ l& A, p2 A
  9.                         {( u, r( A  ?' R, z" i" ]
  10.                                 switch(keyValue)' p$ U5 i$ e+ o0 j! ~
  11.                                 {
    5 D9 @/ z* d# i3 ]- h* m/ |
  12.                                         case 1:7 h, _' r* i' x# s3 W7 X
  13.                                                         keyValue = 0;
    - i( \7 W2 q0 ?% \* D
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);3 C: A$ G, L. J, {& P+ a
  15.                                                         HAL_Delay(100);- O! I- v2 y7 H# j! v' S
  16.                                         break;
    $ y% M9 j) ^3 S; ~
  17.                                         case 2:9 q! \4 ^2 {$ `4 ^7 u
  18.                                                         keyValue = 0;
    , e- E0 b' h+ U7 q: C# n3 e/ o
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    4 z) w6 G3 P' O- I4 V
  20.                                                         HAL_Delay(100);
    " V0 r! `- ]7 y$ ?( e
  21.                                         break;7 w! a: a: q, e2 o/ ?& n
  22.                                         case 3:6 _) D) N8 A4 L( r7 n3 n& C6 B7 @
  23.                                                         keyValue = 0;
    / i7 H$ B! i, I7 S$ k; J
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);$ b9 N2 i3 f/ F7 [- }+ |
  25.                                                         HAL_Delay(100);1 m! R4 H' x' a. j3 B
  26.                                         break;5 \9 `$ U" P* b* P4 R6 f
  27.                                         case 4:+ |  N9 O6 }- L0 c6 I; @7 T
  28.                                                         keyValue = 0;
    # k3 V/ C/ Z8 m' p; u' W
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    & @; L/ T. j0 \6 i
  30.                                                         HAL_Delay(100);
    - x* L5 g, x# h7 H/ d/ D# X
  31.                                         break;
    - v- h! m4 k- k1 }5 {! |$ \7 p
  32.                                 }
    ' P( y+ h# M6 r: P
  33.                         }, s/ z/ M( ~/ ~6 @$ J
  34.                         else
    . k0 l) l0 P  k1 ]
  35.                         {) J* F$ Q: ^. b' p8 g! b
  36.                                 switch(keyValue)# [8 K! q( p, a& w7 C8 ]
  37.                                 {
    - B. E. j$ R( k, w2 O
  38.                                         case 5:
    % R. }5 v9 M' C9 r* V6 q% a+ m
  39.                                                         keyValue = 0;) i1 ?+ t* Y* M! O- g' Z+ D
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    7 ~! F  I; k7 x, [+ a7 [
  41.                                                         HAL_Delay(100);
    ; ?8 `6 W: p  d8 g! _
  42.                                         break;+ A* B( o8 `, d# v: C, v& A
  43.                                         case 6:* a' M1 x/ S9 e, P+ G- q7 k$ C5 [
  44.                                                         keyValue = 0;
    7 R' H9 A" [! ~! l9 c, J; A1 H
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    * o! l4 h3 ?# @8 X5 U3 |0 J
  46.                                                         HAL_Delay(100);4 m" i' ]% l3 |
  47.                                         break;# {- v/ |6 t8 f! ]! d
  48.                                         case 7:
    6 Z- U2 v" _' K9 J0 u
  49.                                                         keyValue = 0;
    # _5 U6 X8 T( C% y+ `& t/ Z
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    ! J# A3 L; j4 W- _2 L
  51.                                                         HAL_Delay(100);
    + i4 K0 E" H. D4 |" I3 k
  52.                                         break;
    ) x6 l3 {& z, M+ k1 T* J
  53.                                         case 8:
    ; W" c- @1 F9 l" ^
  54.                                                         keyValue = 0;0 }( y# `2 |) E9 w2 b
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    - u0 F7 @6 K, o- E/ {  g# x
  56.                                                         HAL_Delay(100);
    . f: Q9 J9 t- u1 e4 q5 d" I, E" a
  57.                                         break;) e1 Q5 z& R# {* o' @
  58.                                 }/ i) E6 ~6 d) G% Q" H' A9 p1 @0 m
  59.                         }
    6 z9 \' _* L% y8 G8 }" W
  60.                 }
    , l1 U$ }- @. P2 Z6 v
  61. }
    $ q4 v- ?: `; k$ s
复制代码
总结
6 z; v- ^. i) P4 B以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。& f% k3 T- u; v9 H0 P6 I
# k2 t. u; n  K# b

4 f2 d4 b, {2 x1 \3 \
4 h' L0 F9 ?' |1 B8 ?5 ?

' z( ^& _5 I" |# ^3 Q- J1 J4 h, H/ y+ _% q' t8 |6 Z6 T9 @" \

5 E! v, I# Z8 D" `* M) w7 g) D+ X1 X

  U. k- t* \% I3 I& p$ }  Z8 \0 v9 L* v) h% ]& B6 p' \, \
赞 收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~1 ^* }7 j$ a  b$ D3 F; I

所属标签

相似技术帖

官网相关资源

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