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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块% e0 ~8 }0 F" b) ]

  s/ P! t9 h4 R+ @9 N! e前言
5 U0 C( ]( I, ?: n- l* g1 Z8 T我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。/ V1 t( t8 X$ D* H2 @
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。$ ^( Z2 w& U. Y) L# S# V
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
+ a' w% _) N3 s: v% [) ^6 J
5 ]  d; ^: A- Q- J5 l9 p) D
1 E3 g+ h  X3 S8 i2 C
先放一张开发板的实物图,它长这样~# P0 O; O: b& g: k3 ^
15.png
一、硬件操作- A+ T; M8 `0 F6 y- l9 F' K
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。) I$ X' O! |" o: T
! s7 @8 F0 H9 P
3 Y- v3 r8 o" Z- F1 K
1. 原理图+ h: G" f9 A* n5 `, v0 ?
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
. h+ S* ~0 ?( Q' q7 b4 c
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)1 P4 G* `" o/ B& ?; t- n7 P
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
- r: N6 |  |" W2.按键相关的IO口:PB0,PB1,PB2,PA0。
7 I! z; F8 R% G- \2 x$ w8 q6 i- w( c  n
3 U+ Q. s( p: O! ]; y
2. 硬件分析" W) h9 R, c4 _/ V! @8 {0 t
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。( y+ C8 ]$ L' W

9 w8 Z3 T, b- }) {5 _1 P/ `

1 C4 s) Q' V/ S, Q) s" e5 `3. 初始化代码
- F$ x6 X' Y" c+ K+ t* N! u$ l
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */6 c0 ]: }- V8 i  ~$ D( D
  2.   HAL_Init();//使用默认配置即可9 n, d  R& W, }) N2 J5 U* z: a, ^
  3.   /* Configure the system clock */; N' i9 d0 H7 U& A
  4.   SystemClock_Config();
    ; x3 x+ g6 ^7 M  \1 @6 t
  5.   /* Initialize all configured peripherals */; I4 t  T& Z; ]0 e& s  X
  6.   MX_GPIO_Init();
    5 A1 X/ |7 f; q3 M8 D- s2 [, ?' {
复制代码
(1)时钟设置
+ F8 t6 X# J6 L1 D: ?- o这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。! w4 X% n2 |, s& q* ^3 W5 R
  1. void SystemClock_Config(void)
    ! D$ P) x: V/ b( u' g( U3 q7 t
  2. {
    / i0 H! b3 _4 c  t9 k5 e8 j9 D7 V; V
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};: L5 Z' S/ I8 ?/ E% S5 e9 _; F# n  E
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};! T; T% i# ?1 v$ F4 u, a1 r

  5. # l- M2 D: F, ]+ {
  6.   /** Configure the main internal regulator output voltage 3 v1 i! t* V9 v  o9 \- e: n
  7.   */, v- H# N1 Q! Q6 t9 z! {( G; F2 S
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
    # u. T. C9 j% V3 ?5 R
  9.   /** Initializes the CPU, AHB and APB busses clocks
    8 v" H4 k* y! r5 D
  10.   */
    - n; K" p6 I3 t. J/ b6 I
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;5 u1 ^) N! ?( z. M$ f
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;8 U8 p4 _- \& d' \  j; M: g$ ]
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;! \1 T- u# w/ D1 b
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;9 u; |9 h8 f# t' v6 z& i
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;+ T- \3 y, W6 t) w
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;+ E( f7 m: h' y7 a" N- d4 I8 i
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    0 T2 c! ~% R0 i9 d$ j
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    8 v5 j6 N- {+ K" y: I+ V
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    ( U6 S5 f" B& `
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;. u; _9 D0 |0 m- @4 m7 c
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)8 R. ~0 |. @7 i$ b# x
  22.   {5 r: {/ F; o* v; B, K/ Z
  23.     Error_Handler();
    . a# H  n6 X& ?# F1 M; q
  24.   }7 o; C4 g: q1 k; G( i
  25.   /** Initializes the CPU, AHB and APB busses clocks ; k, P- H& k+ B' l& e
  26.   */
    ; p9 Y* l! x" j. x& y
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK$ t  L% x0 p+ e" V, i5 q: ]
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    0 v1 \3 ^7 d, N: j
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    ! q  u) B5 \- p2 m6 O' D! Q, @
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;9 x, q. R2 e6 a4 A# o5 g0 d
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;4 H) ^) p$ H+ k! d: A( N4 ?
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    9 Y9 r) x5 C2 e# g
  33. . y7 A9 U; g; l) N2 Q) p
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)+ l2 ]1 f! ]) i7 E+ Y
  35.   {
    6 C5 q$ i6 O, {2 V* P2 ?
  36.     Error_Handler();
    5 y8 Z/ a  ^6 X4 w$ F2 G/ |
  37.   }
    " [5 A: f$ J8 Z
  38. }7 D4 ^0 e4 K8 H
复制代码
(2)GPIO初始化
. j! y* G- G* V8 j" U0 M- E
  1. static void MX_GPIO_Init(void)) W" h8 {8 w& S: o! i
  2. {
    5 q) l* p$ G& C( o
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};" h1 p$ r( B# w1 y3 [

  4. & b7 D1 x' p, w6 O0 U
  5.   /* GPIO Ports Clock Enable */
    ' _7 |; w* o$ _& E7 w' |
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();' y8 P3 O: x6 l9 h# ]) t
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();( \6 j5 |6 j. ?2 e# ^, ~/ X
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    + o; j# p  _8 ^2 b' Q& ~& o4 w& O/ d
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();$ `4 }% N/ h( b4 d
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();9 m$ F0 ~( q& Z! ~/ B' c
  11. / C. [* o. m  z& ]/ \; O
  12.   /*Configure GPIO pin Output Level */0 n: @4 G. k8 n/ Q7 |
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    * k5 b! p6 t* m1 o+ p; P
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);9 s% r( {9 Y' W! _2 z1 Z

  15. , b& O9 h( p1 N0 V4 c; a) R
  16.   /*Configure GPIO pin Output Level */2 l& C* A4 X& J8 {
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    : Z0 z" ]/ ^/ L$ c  N

  18. + ^" T6 e; M6 ~
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 + p* |9 r: T- e) m3 X
  20.                            PC9 PC10 PC11 PC12 */
    " s# q$ t; h5 v! w5 w" q
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    . E8 i: |6 X  u' {/ Z
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    4 W( h* I$ q# t3 ^; z
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    4 i% F/ J- b4 D8 O( u8 D$ Y7 \
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;" q9 x  g. p9 k, w# T
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ; W4 l. Y$ z2 ]) I, j" @
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    # }9 a3 D: p! }1 e3 C

  27. 0 Y- v# I! m; \- N" B! _
  28.   /*Configure GPIO pin : PA0 */
    5 M# r# V) X% j5 W" a0 S$ e6 Y9 \
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    0 z$ ?: }* b9 i' q. c* _9 S
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;- ^9 L$ ^, M6 ?7 m5 K! z, G
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    $ K& a8 `( N6 f7 `6 N0 C
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);$ q, b9 h# A" z/ H& U! W  [

  33. * b4 j1 l/ m0 H3 c( V+ r& ^
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */
    " ]- G, w+ u6 @, F4 X5 m$ I
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;, ]. S7 a, @$ [
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    9 W) S* z- A7 P
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    1 U% J2 n1 i. Y+ F4 o. F" x
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    , z0 P- k" }6 v( W+ u3 G
  39. 9 S) N1 v4 |! Y2 G* |2 X3 V
  40.   /*Configure GPIO pin : PD2 */+ W- G- Y$ E) v. J4 s0 a
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;2 n% c+ S  k! `& w1 Q$ l
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    ; C+ s$ ^# N  p9 U
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;4 v& x* t3 P4 ?+ D
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    1 p% a4 i  f, }" d  ~
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);/ C4 h( k/ D! o/ M5 Z/ x. r
  46. . b# O. R. m; z$ {- N$ _; q! R
  47. }" i, |" P% x, j2 W, R) W9 e
复制代码
二、按键模块的驱动层实现' o1 O2 \# S% h" _$ i6 S$ n4 n
1. 硬件框图# p$ ]% P$ u- [
在这里插入图片描述
& p& T# C/ M+ c0 d# i 11.png 6 T& j6 ]/ k, Q. ~4 O) r
避坑点:
' `# L7 n/ e. z7 N短按:按键释放时判断时间
0 y5 s, I+ [/ V' O- y$ [长按:直接判断时间
; C( r+ B6 F& C6 _# c! M
8 e+ u% W. P' [4 S1 N5 L7 N" G3 F" v
% t" z+ X: J7 ]
2. 按键驱动层代码实现
8 O, ], |3 K( f1 L, e! ?$ P' e下面直接上C代码:
+ ]1 C7 h7 [7 ~
3 V0 w/ {; ]: ]# {6 e
9 K. @/ o0 b6 G; U
(1)key.c
2 Q$ g9 U% a6 A
  1. extern unsigned int keyCount;
    8 @' Z6 _/ e  q0 R' A% D5 c- ~
  2. extern uint8_t keyValue;0 n# j) A. J0 {
  3. uint8_t keyflag = 0;. \2 z4 D- }" E* F9 ?
  4. void Key_Scan(void)" Q; X/ K6 G" }; s# w0 W
  5. {% [* k, G( E- g/ `0 x' M9 x$ u7 x
  6. //keyState  按键状态;4 y) s; k% x" i' n) l6 G
  7. //keyPass   记录哪一个按键被按下
    : z" j% B4 d% L+ W
  8. //keyCount  记录按键按下时间6 E) I) A' a8 }# T0 R1 ^
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时
    8 Y$ p* x% W: P1 V" L3 U4 r, [
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件, w7 w' d% p! X2 v8 D
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    3 D: g9 C8 J) H/ ?" r7 {6 W
  12. //ShoutKeyx 短按x键值,
    3 `6 ]6 {: g: J0 V3 @$ O9 s
  13. //LongKeyx        长按x键值
    7 o) X( u, A( m  Q. C  U: M/ s
  14.     static uint8_t keyState = 0,keyPass = 0;" v& U$ d+ V& A5 l
  15.     switch(keyState)& z0 ]/ ]( a9 ?7 }
  16.     {/ O5 D  _8 Q2 C" r1 u7 ~% V6 U
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    6 D1 }9 h. {1 Y' v4 z# T
  18.                 {4 |( p: n) t1 [: S" f% O4 B4 s6 T
  19.                     HAL_Delay(100);//消抖
    6 x/ r  x  V8 j' Z) O
  20.                     keyState = 1;" d* P* N" `7 W" [9 r$ t
  21.                     keyPass = 0xff; //初始化按键
    " E6 N7 A9 Z+ c
  22.                 }   ( \9 |; }& [, B& E
  23.                 break;1 J: H' t5 l% R/ Q3 U) B: u
  24.                     
    - s4 F) L- T7 f9 X& I! w
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)- O* l# O2 E$ l7 z7 G6 O
  26.                 {
    8 N' |7 |# H! u. W- j$ ~; e4 V
  27.                     keyState = 2;8 w! C3 n) @7 f4 `( Q$ s3 X) t
  28.                     keyflag = 1;//开始计数3 d) D& K- r! k* U' c
  29.                     if(KEYB_1==0){
    6 b; L/ i& W% l* X6 t& r1 Z% L# K
  30.                         keyPass = 1;//返回对应键值1 e* b+ C% D; D# @5 H+ s& P
  31.                     }   
    . D: ~! V# V, p: g0 B
  32.                     else if(KEYB_2==0)keyPass = 2;
    % ^+ _$ S) [! M# x: }8 Q$ }6 h
  33.                     else if(KEYB_3==0)keyPass = 3;: C/ q5 V1 R# Z  g0 y1 t
  34.                     else if(KEYB_4==0)keyPass = 4;* M7 u: g% }6 y! e. G# U. U5 E2 c
  35.                 }   1 T; J4 P! M  S- T
  36.                 else keyState = 0;//返回检测按键      9 J3 P, c& N) o
  37.                 & [9 r. o8 _) V' }8 ~9 g
  38.                 break;
    6 W6 x3 Y3 W; C0 F+ o, X  t
  39.         case 2:
    : P! t5 Y; Y# Z' ~+ E# C
  40.                 switch(keyPass) ( e2 o8 Y- p/ f: h) o, b
  41.                 {              
    ! M  m; f& B) @# B" m- X
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    " ]: A4 L( Y9 G5 j/ B( \2 `6 _
  43.                             {$ T, c* i0 O' |" y; R
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按, N; @9 v7 c  Z- F
  45.                                 {$ @- s' \* G. _: Q' X9 o8 C. \
  46.                                     keyCount = 0;( t# i% W8 |( z9 [, [" P9 f
  47.                                     keyflag = 0;) z- O* y9 Q9 C1 F+ i4 D6 @& A
  48.                                     keyValue = ShoutKey1;
    ! W0 p$ n, n$ d# v& @8 A
  49.                                     keyState = 0;; L7 ]2 f% X# d
  50.                                 }   
    - g$ Y+ y- @8 Q9 P* c2 @
  51.                             }      
    ; z% }  C8 z9 r* {# O; S
  52.                             break;" L4 n1 I4 I" R) r, w
  53.                     case 2:if(KEYB_2!=0)
    + [7 P  i& Q$ \, z+ n
  54.                             {
    $ k( h& q6 E* v3 J
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    + w! V) `& }% y: B& v
  56.                                 {
    - @( {7 {5 {+ O* Y; B( e- m- n
  57.                                     keyCount = 0;8 v& E9 f! u! |) C( E% `; A
  58.                                     keyflag = 0;1 G, W/ ?  z2 |" V: H/ z; c; G
  59.                                     keyValue = ShoutKey2;
    ! M, s$ W" G( B
  60.                                     keyState = 0;
    : A0 K- Q. q5 \. n
  61.                                 }   . y- L& A1 F! l6 K
  62.                             }       4 Z% y$ U% _( o. r  y8 `# D
  63.                             break;( `  T& v; |: J' S1 V* O+ G
  64.                     case 3:if(KEYB_3!=0)6 r% Z) O" `) h- _' H: i
  65.                             {0 z& S6 ]( c( E4 C2 i4 Q4 B9 ?
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按
    & B% Z, E2 h8 y) V6 T2 _! e
  67.                                 {
    : l+ M1 |. I  u8 |+ o; o+ k
  68.                                     keyCount = 0;
    8 k1 z; a- L! a9 V/ j  ]+ q
  69.                                     keyflag = 0;9 s+ L  C1 f7 i% E0 L! \' |
  70.                                     keyValue = ShoutKey3; 9 q1 W$ |0 V3 J" e6 x& _
  71.                                     keyState = 0;
    8 T' b$ z7 i  t, t+ h; o- U
  72.                                 }   
      r9 b& q0 v2 p" I' Q
  73.                             }      
    ' C( j3 a2 d9 Y! C7 W1 r
  74.                             break;
    5 F) Y( A  w& H6 Y. f; B
  75.                     case 4:if(KEYB_4!=0)1 a  ?3 D# I$ l" z" o
  76.                             {6 _) P' B7 i1 M; B* |
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按7 ?4 l' _8 J: `7 [. z
  78.                                 {
    ( f: h$ I( a& i' K) ?3 ]
  79.                                     keyCount = 0;
    5 g+ i, J# j0 S! [% x$ T# I
  80.                                     keyflag = 0;
    4 x. _7 K5 ]4 ~" i1 h8 Z8 R
  81.                                     keyValue = ShoutKey4;
    7 l4 [$ i  X& n" [; \+ ]
  82.                                     keyState = 0;
    0 [! t0 I8 S9 f: D
  83.                                 }   : S" _* G5 v/ ?# B0 s; Q+ S+ X# A
  84.                             }
    3 N. o4 G4 m  e  ]! z# P" c4 H/ {1 y
  85.                             break;6 J0 Y: T9 w* R# v. X0 c/ K9 I: W
  86.                 }
    ! }+ h: j) k5 g8 l* h; V, ^
  87.                 if(keyCount > 800)//长按; `# I+ ~) f( [. v
  88.                 {   / o) H/ [$ {  l$ Z7 z( Y+ K
  89.                     if(KEYB_1==0)keyValue = LongKey1; & w' M5 C1 l7 a. r3 {/ \
  90.                     else if(KEYB_2==0)keyValue = LongKey2;/ _6 g2 H8 M8 G3 N
  91.                     else if(KEYB_3==0)keyValue = LongKey3;9 f$ @, g6 T' o: f5 F
  92.                     else if(KEYB_4==0)keyValue = LongKey4;; P- ?5 b) r4 S! _+ _0 [
  93. , M; K0 W/ e* C  ^/ |
  94.                     keyState = 3;
    + Q% K+ C5 ]* [1 F7 U  [
  95.                 }
    * r" q7 V' N# y' Z. u3 c
  96.                 break;. E, X9 X. x4 m! q

  97. 0 [% S, T- G' d& _% E
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    " W' m, E& B& G' l: J4 K6 g$ M
  99.                 {0 ]# [8 k" e6 |6 ~9 A2 H7 `
  100.                     keyCount = 0;
    , G  p. P' ~+ W2 ~4 ?, H/ R
  101.                     keyflag = 0;9 W4 N$ x0 [% w" K- i# {
  102.                     keyState = 0;5 e4 J( M9 l$ Z9 {
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  8 I% U5 G, O* \  k/ W( J
  104.                 }' G5 T7 q( a3 a3 D7 H
  105.                 % L+ Z  C' u" `, C- u
  106.                 break;( {4 q0 K5 y: X+ {
  107.     }
    $ {: W' H! e) @4 A7 Z
  108. }
    ; a) K/ S# d& H, m
复制代码
(2)key.h
/ _: C7 @$ W1 i) f7 a
  1. #ifndef __KEY_H- ]& w) s, z1 o. }$ e( d' c
  2. #define __KEY_H
    8 e, v' R% M4 J
  3. #include "stm32g4xx_hal.h"
    # z! n  U( F0 @
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB01 A" @+ N5 B% M5 X( e5 o! c
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    # N, m$ I; j7 @. M( p8 G; U
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    . G" Q3 x/ c0 }, I6 J
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    4 d, n: q0 ?  ]5 K; N
  8. #define ShoutKey1             1
    ; {! S* I# d$ ^, y: n3 A
  9. #define ShoutKey2                2
    # F; x2 ?- A. i5 J: k3 K  n
  10. #define ShoutKey3                3
    : d; j* _* w9 m3 l: o
  11. #define ShoutKey4       4: I: y5 X( b% I
  12. #define LongKey1             5
    # U( B+ L* h" ^5 }7 Z) D7 O* |
  13. #define LongKey2                6
      a; n/ K( Q) k7 p* h
  14. #define LongKey3                7
    2 `2 h+ k; n5 r, J9 ], K8 l2 O3 X4 d
  15. #define LongKey4        8! `9 F# p/ w, m+ d) w
  16. void Key_Scan(void);
    " _) \: V1 ?: S1 Z, b7 F+ l
  17. #endif6 E" I: t& K/ k$ @1 z+ s
复制代码
3. 计时操作: {, x* {' J" Z# t1 u
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。
% V2 h' O, ]2 p, T" ~下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~2 i% |- M) @4 F! {- T% @
  1. extern uint8_t keyflag;; y1 T- h0 @6 Z3 A6 z2 \
  2. unsigned int keyCount = 0;
    2 x" |% o; O" B, h
  3. void SysTick_Handler(void)  Y# ?& ?$ M1 l& _$ D4 W; L
  4. {
    3 W% b  G3 Q% O  C$ @4 u
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    / ?' i4 O2 R) y# q8 W* c; y
  6.         if(keyflag == 1) //若有按键按下就开始计时
    ' @! |  d2 ~9 [8 ^2 o) g. y6 G
  7.                 keyCount++;       
    % `5 V$ Y; j. [: {) q& t8 t
  8. }
    - o5 @+ N2 H9 W7 X3 D2 o7 O$ h
复制代码
三、应用层简单逻辑实现# u0 i  L; |- g3 M
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~7 |% i" [3 d$ p( t  m1 W
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    0 B; n. B' @4 f; a
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    2 e/ ?/ Z; Y" x6 z" q
  3. while (1)2 X: G, j7 K+ x% d
  4. {
    ' V. o3 H# b* E
  5.                 Key_Scan();
    7 i' p. o2 q5 G& k) r$ v6 N  K" Z
  6.                 if(keyValue) //有按键按下0 z) P0 f. ~4 Y" Y% s5 O
  7.                 {
    ; j3 }. c* F! x9 ]* L
  8.                         if(keyValue < 5) //短按  Z# [& f! |$ S& g
  9.                         {
    5 L' A4 ^; l4 t1 [
  10.                                 switch(keyValue)" H+ O% r% ?3 s% B* O, |! I1 Y
  11.                                 {) `$ q& e, R* G+ O) r( R+ h5 X
  12.                                         case 1:
    ; O% R. m: A6 c  r' Q, r7 A, i0 _
  13.                                                         keyValue = 0;% a6 S$ d' V( T$ ]
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    & @6 ^( [- o  V1 P" w% W: t3 z3 l
  15.                                                         HAL_Delay(100);
    ! W9 p6 ^3 Q: Y- t7 I
  16.                                         break;* I# X. X! ]( C& M0 E, o# B
  17.                                         case 2:
    6 I: `. i2 t7 A( {! }1 A$ N3 P
  18.                                                         keyValue = 0;& V$ L0 A6 c! D- i/ m! l
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    8 J7 _  z( |6 O3 N2 ~
  20.                                                         HAL_Delay(100);/ W5 Z0 Y' ~  R, n& z
  21.                                         break;
    " Y6 H; `% y; o1 m& T( D
  22.                                         case 3:
    ! [& x) s) s, h+ x+ C
  23.                                                         keyValue = 0;" m# e  ]/ Q; r, P  d0 d* z) M
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);$ G: g# B2 m! }- d& a
  25.                                                         HAL_Delay(100);
    7 b# t- u" l+ m2 j8 d* ~$ T
  26.                                         break;
    $ J9 t7 f$ V" N# r( ^, b
  27.                                         case 4:
    8 R4 B7 T& @( M
  28.                                                         keyValue = 0;
    . L0 {$ X7 e" C5 i3 y9 V& L9 U
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    ! e: R* n& U! y8 b* M; f7 G" @
  30.                                                         HAL_Delay(100);4 d9 S; E: X9 ^: h2 F
  31.                                         break;
    2 W  }  U5 m) A3 y, f  r6 l8 C
  32.                                 }
    ) O! B% c$ _5 k/ N  o- d0 n
  33.                         }
    " Z! ]; ~" {) b% [- @: U
  34.                         else2 J- o5 D5 t& q+ I" _: L, A9 r
  35.                         {" L7 w. ]4 \4 B, v
  36.                                 switch(keyValue)
    8 {; S3 y/ \% I) T
  37.                                 {2 _% u- N7 c( W, t, ^, w0 |
  38.                                         case 5:$ B) I  A$ s3 r. G/ O
  39.                                                         keyValue = 0;
    0 M, [3 z, i( y* l
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    & W% U' b2 u; @: q; I
  41.                                                         HAL_Delay(100);
    . {- g) r6 Y1 a& o6 m! k9 u% `! U
  42.                                         break;+ o9 v; v: R( H7 m
  43.                                         case 6:
    9 X: U. G! p+ H6 Y2 a3 j5 G
  44.                                                         keyValue = 0;9 R8 @* C  y: g: q
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    0 a1 p7 K5 A5 @
  46.                                                         HAL_Delay(100);
    ; ?! `7 g4 M& N
  47.                                         break;
    0 p& R; B! W& D* G. H2 {
  48.                                         case 7:
      S# l2 x, f4 m* |# C
  49.                                                         keyValue = 0;' \1 F& }0 K* I2 P/ r
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);: H, P! X3 m, f! }0 p
  51.                                                         HAL_Delay(100);1 x9 Y4 h6 {# l' e8 R9 M8 `
  52.                                         break;3 m" ?* Y) A4 P7 J
  53.                                         case 8:
    $ `. m& o0 u1 g9 i6 C/ B
  54.                                                         keyValue = 0;0 h* @# a7 g3 {- P; s
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    + a5 K% l' V8 x5 y
  56.                                                         HAL_Delay(100);
    ( r; e3 ~( M% W, {! d0 ]' s
  57.                                         break;, q7 [1 I1 x% R& T! `& {9 I1 _. Y
  58.                                 }
    # o( c8 F6 e9 @1 n5 E0 r
  59.                         }1 S. ]7 |$ j, R
  60.                 }
      }( h% ^& q; g1 {
  61. }
    0 c, L: z+ _0 n. E+ Z+ ^
复制代码
总结7 \; a* |/ E9 f5 T$ N4 Q- D
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
  g5 J! A( J7 D' A* y# t- r- O" v2 Y6 {# Q

5 [; h' m3 _4 t( k( w$ a, k3 M$ w" f2 W: H. h2 D) {
; t3 w! Q4 R& a8 V  X

0 h* \$ E1 t: Q: V5 s/ @1 Z6 d
$ K8 A4 P% d3 m! ]6 t/ I

& e% p& A  N$ b) U8 g
- C5 ~& n3 X) w
. L6 B, b6 z1 {7 l# g
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~. G2 [% A2 j; p: E! {

所属标签

相似分享

官网相关资源

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