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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
* v3 X$ H7 o6 s4 [* j4 t) d0 @. H* R( k; }# O) K
前言- a0 p+ o4 z. r7 w7 I
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。
9 e$ Z$ E# \* E$ f4 n. V+ L* J注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
* d0 w7 A; |4 I7 K+ s) A由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
1 c2 U( _  w5 i2 K: S! D8 k3 g
# s7 G5 t1 V7 X- j" `
7 s5 y* W% b6 \/ C1 C
先放一张开发板的实物图,它长这样~: W2 L4 L- K0 l; y. \
15.png
一、硬件操作/ G) {/ s/ o- Y+ }8 n
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
* x3 N; K; d  }3 {: Z2 n+ `% O3 E1 j0 h0 T

! x/ b6 D) j: l1 k1. 原理图
) ^4 B- v% n3 H; b7 j0 r' I  G& T" T
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
! {$ v. W( b0 T' w4 A+ j
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)/ O$ u0 S, \' Y. z8 X, N
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;( D+ ?" C; A9 i! }( t% G7 X7 ]; b7 N
2.按键相关的IO口:PB0,PB1,PB2,PA0。3 i% A' Q& \/ c0 v  A' G  ?
: ?% M# e7 \3 f2 y, I. O0 l9 v
1 d. w2 f3 z" h. r& p( [
2. 硬件分析* c+ x# N2 \& f: E* s
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
) H; m) \( o/ K* u0 O( b  v$ P& k
; |  g$ x' A! H/ n5 t0 u
$ [2 y% Q' i! ]6 Q# p" N. j+ J% [
3. 初始化代码/ f( Y$ B. K- K2 W- ~, `7 C# y4 Q
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    0 P% @1 |: x* a% D) f
  2.   HAL_Init();//使用默认配置即可
    ) |+ P7 T6 j7 G
  3.   /* Configure the system clock */
    : Z$ @5 v5 C- S$ u+ d6 B4 B- a7 W& L& X( k
  4.   SystemClock_Config();) ~0 s9 K' }; `
  5.   /* Initialize all configured peripherals */; H2 k0 }# |0 a: K5 G
  6.   MX_GPIO_Init();; p; Y# r2 o) x
复制代码
(1)时钟设置
. C3 N9 \. i% z- ~8 k! B$ D这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
. K* y& D% o/ \, W" ?2 [
  1. void SystemClock_Config(void)
    / X) f+ p4 A; w5 y! c  O: ]
  2. {, Z8 W& h, d" c$ o2 q1 F
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};2 ~( `& f3 y! L* M4 U
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    ( J4 R) X0 q8 x$ T. E* L6 B% ]
  5. ! S& S# x  E" H; [
  6.   /** Configure the main internal regulator output voltage
    9 Z0 K. H9 \' u! i8 \
  7.   */
    6 x" x9 V* t8 V+ h0 F+ a
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
    # l: M7 w( A' e" ?- _
  9.   /** Initializes the CPU, AHB and APB busses clocks   P9 x- Z, X1 u
  10.   */
    " t+ l$ A+ n1 @$ R% i# X" P) b
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    % C) o% F! ?5 i8 I+ p: l2 k( A( j
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    * i1 t4 P/ H- R* U' C5 D  X, _
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    - M* A2 ~& W* Q- z' V7 V
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;- L( j4 K, C9 v: D; r% J0 O& y+ Y# J
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    7 `# A/ t: N' D
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    3 E% ]$ ]" S& H8 s" X
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    0 g3 L  Z% G% {/ ?9 @
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;% E# d( y: Q2 B" Q/ {  J
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;, I) X. L, G5 t- U7 x. @& `
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;0 {" e" Z  q' o; e1 @
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)- g: t6 H3 g$ o, B
  22.   {9 Y3 d2 Y! S" c2 ~! w' H
  23.     Error_Handler();
    $ O8 y6 q$ [5 r# e" t2 J, u
  24.   }
    ' E* {) j2 P5 x
  25.   /** Initializes the CPU, AHB and APB busses clocks
    ' L% o# @4 W9 q0 j
  26.   */
    ( v( R5 [" Q2 S
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    4 m3 Z. H5 j6 L# W! P& |7 x
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;( I& u5 m5 m7 D9 d& t
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    , c& C/ g+ `/ J6 r* t! o' z
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;( Y% Y4 T/ U) H4 s; |! L1 i$ S- e
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    0 m- r( k. N( o) C
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    : k8 `( R2 c' C5 k) c2 n

  33. $ U/ b6 U' j4 s! t& e5 X
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
    + _$ g% }# Z( \3 B( |
  35.   {; }4 f$ k2 S2 ]* D1 P. w6 r) k
  36.     Error_Handler();$ L- F0 e3 i3 Q
  37.   }  U0 I$ o( }6 S: j, @7 K
  38. }
    $ F5 g4 ?: d: Q: @6 |' B" g
复制代码
(2)GPIO初始化7 `+ h5 V8 n% h$ H
  1. static void MX_GPIO_Init(void)
    ' R: q- S3 Q) k
  2. {
    * e4 H8 j) q6 t4 d, K- K- D
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    8 z9 ~3 P. V8 t$ }2 C
  4. 7 F, a/ b" s2 k( H0 U
  5.   /* GPIO Ports Clock Enable */
    9 }% T5 K( C9 d9 o5 W2 k
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();" b$ b; L) `' O: M* r9 p* s
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();1 W, @  k2 h; n6 x( i. |4 b
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    1 F4 z8 O1 Q$ k3 l
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    ( i: |1 E& M: `7 G# U! v+ q2 Q: d
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();, w* k* W3 g: o& |
  11. 1 R. ~9 W5 ^5 b5 J; g: k1 k
  12.   /*Configure GPIO pin Output Level */( L6 ]  o( C1 N1 }9 k
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 . J5 ~/ O3 R2 V1 z' ?) s
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);7 D$ X) ?! [2 k# M7 @3 f

  15. 4 `' @* b# A) a9 d6 E4 y( @" x4 Q* n
  16.   /*Configure GPIO pin Output Level */8 D9 \0 w- s" h8 ^: M) V
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    8 L0 h( F- k, i8 `% ]% A" X3 {
  18. ) X! `4 Y% X! o+ y9 X! m4 ?
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    ! t: r, t8 t8 R6 v+ P4 w5 k* w8 n$ j$ J
  20.                            PC9 PC10 PC11 PC12 */
    ! d& B8 n2 Y. a) Z: {
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 , T# M8 F# s% z; f' t  M
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    7 Y6 l: M" O9 d: V) E
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;3 B0 g& c$ `# f9 @
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    4 e- u0 q; z' l- x, _+ m, C  l
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    6 p; D# c7 }* x1 A! m( s: O! z
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    ) P; w" c, t; v: e8 k! @) U

  27. ' e& z, P+ L' `3 w0 i2 J* x
  28.   /*Configure GPIO pin : PA0 */9 w8 P0 q9 U$ Z3 P$ \( ^! t, j
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;, |3 ^7 Z4 X4 c* x
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    " W$ Q3 d) ~: J9 L2 I9 }+ U8 ?
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    / I7 y+ a% o0 ]. O
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);& m; B" D# m( ?2 _

  33. & o- r1 A- Q/ Q# I% [8 F4 X& J, N
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */- _; F: g) U2 x
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;8 w, v3 X/ F( L" o& W, r# S
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;5 D# r9 f4 Y4 n8 X
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    / ]2 E8 a) e' u* p7 O+ E
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    & e6 A% n2 U- a
  39. 2 @8 \! t) b- A* x2 P, N- [
  40.   /*Configure GPIO pin : PD2 */
    : ?4 V4 C# c( T3 F% S3 K; z
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;5 l" E. K4 y3 i3 w' o* W  e
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    " ^% M3 M% }/ Y' }+ k0 P
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    . Z& [2 Q3 ]. a, p) b+ s
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;3 R. @: X0 K$ }4 w$ p
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);- U( _. n! i: Y/ ?. q1 _3 g8 x

  46. - i1 i( @8 C( {7 }! D4 a
  47. }  R: ^, Y( V/ M/ N0 A: ]! i
复制代码
二、按键模块的驱动层实现
) h) \! O' O- {2 p& @! [+ h1. 硬件框图) P5 O9 Q& e1 d& N
在这里插入图片描述
; u+ E7 X  m/ { 11.png
7 W1 {0 \& g! J# N避坑点:
+ S* k- ]$ y, I/ [短按:按键释放时判断时间7 J: y3 j5 Y8 O  W# p
长按:直接判断时间
  a& l/ U4 x% s: [; U* O* J) @9 v4 c4 w- |; d" _

; i7 F, |: U+ P# q; i9 D5 O/ T2. 按键驱动层代码实现: f4 L  l# D/ r' w2 G, x# i
下面直接上C代码:
  _# _* N* `" X, z" {' ?" T3 L7 ]# p4 _  ~7 I8 A! y
7 B1 {: J; U: Y4 C0 m+ b7 U; I6 o
(1)key.c
; b8 Z* |) _% i' e; D# B4 l
  1. extern unsigned int keyCount;1 k+ f+ E2 B5 ?. P7 e) e, d3 E
  2. extern uint8_t keyValue;8 Q2 q2 Y, `$ \1 F: K/ s
  3. uint8_t keyflag = 0;
    0 `8 @( P2 B- d7 Y5 [& W
  4. void Key_Scan(void); G1 o/ \" v1 c3 r, H% C0 f
  5. {$ _4 {( a9 B' I0 P: _4 e
  6. //keyState  按键状态;
    ( n* n! z9 U: f: Q3 Q
  7. //keyPass   记录哪一个按键被按下0 V* \) j  Q# m6 o0 X: C" e
  8. //keyCount  记录按键按下时间
      T2 o/ b! k# a& b4 g
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时3 T8 e/ v- v" H; p! v1 z
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    # n* h1 I& D# d- n7 o" c7 V
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按! `8 _, s: \: |3 m# y0 W& l" V
  12. //ShoutKeyx 短按x键值,
    * m- J: D% ^% z. _
  13. //LongKeyx        长按x键值; I8 {! r: E3 ?9 I7 C  H0 N: n
  14.     static uint8_t keyState = 0,keyPass = 0;
    ; p4 P+ r  |  L
  15.     switch(keyState)% R! e* _! O) `
  16.     {" N' }/ y1 ~" g' {) F# F, d% \
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    : h) u1 i, N$ ]! P4 C: ?
  18.                 {
    ' [, H8 S' o, J/ w) C: ?
  19.                     HAL_Delay(100);//消抖
    ( s9 A% V3 H. Z$ t2 Z( i
  20.                     keyState = 1;% q8 Y! J1 y' J8 U
  21.                     keyPass = 0xff; //初始化按键
    ) d# t' P7 }' d
  22.                 }   
    : p2 ~/ w- F- ^& N' i/ a, Q0 G
  23.                 break;
    % W8 P) {' u, w) q- _( x2 D
  24.                     ! I$ @) ]) u4 g2 S+ J
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    6 D7 ?+ U' U/ `" F) t
  26.                 {& [1 S+ q' S' ^" V1 F. a
  27.                     keyState = 2;
    7 G2 Y7 {( j/ W# [6 q6 D
  28.                     keyflag = 1;//开始计数/ G% N! t6 B2 [2 G
  29.                     if(KEYB_1==0){# m1 f! f+ H  i! E0 u4 f# r% Q3 s
  30.                         keyPass = 1;//返回对应键值
    2 d* u, a. w0 o8 c" |- a- ^# k
  31.                     }   
    3 N* c7 M& i* U+ c% Z
  32.                     else if(KEYB_2==0)keyPass = 2;
    6 Q  K% }7 [/ Q4 l3 R0 s. S
  33.                     else if(KEYB_3==0)keyPass = 3;4 Z; w. |* m1 o; A5 W! ?: ]
  34.                     else if(KEYB_4==0)keyPass = 4;% @4 t! |/ `3 X& Z. Q
  35.                 }   
    2 a4 d* ?% {- _* l
  36.                 else keyState = 0;//返回检测按键      
    ! q) P/ m  Q8 k! _
  37.                 ) z# c" @# N# l  Q% Z* r6 |
  38.                 break;9 @- q- R! y. C, J" x4 {: W9 I
  39.         case 2:
    3 C# T- e" d) T- Z
  40.                 switch(keyPass)
    " |' Z: A1 q1 V$ H7 F- [0 U
  41.                 {              
    & X! L3 I( t! A6 }
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    ) l8 x- S! H$ P6 W& I0 ]
  43.                             {2 M# q5 `/ L. }
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按, U5 H! ?/ h+ N/ c
  45.                                 {
    3 `# m  g- x$ ^: }
  46.                                     keyCount = 0;6 R( [9 V& Q, N
  47.                                     keyflag = 0;
    2 z% V9 d% `' e" i7 I
  48.                                     keyValue = ShoutKey1;
    . `# R& k/ o% Y8 O$ |3 N, g. Q( r
  49.                                     keyState = 0;
    , {9 k7 V( t( ?) ~% p
  50.                                 }   . p, c3 Y( ?" F; ~" v
  51.                             }       % a7 S) V$ q- i3 ]
  52.                             break;+ ?, n, S3 v/ ~
  53.                     case 2:if(KEYB_2!=0)3 I* ~5 E; g& q7 c; X! [
  54.                             {
    ; f4 F. p) c( u% j3 h8 Q* M
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按+ x6 ?5 X* B: K. f7 T7 i. b
  56.                                 {
    ) ?+ E3 ~! `- i; D& F
  57.                                     keyCount = 0;  U6 z; j  a( s
  58.                                     keyflag = 0;
    # }1 U% s- @$ p0 q
  59.                                     keyValue = ShoutKey2; ( O- R- j9 u0 {* ~  H/ V
  60.                                     keyState = 0;* s! |( R8 p- N7 g  W) a" Q$ b
  61.                                 }   6 r0 U; b4 z2 m; e) V
  62.                             }       % A7 _( b% c) O
  63.                             break;
    . z' K: ]5 t- `2 M2 I
  64.                     case 3:if(KEYB_3!=0)1 l4 V" p, {; U6 [. z; G
  65.                             {# ^/ }' z: v8 {: K9 G# y9 P% }* a  s
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按, X# ~# P3 ]: X
  67.                                 {
      d, Z. s+ ]* D8 N% m. \/ M
  68.                                     keyCount = 0;( z6 W, ]+ K4 K! E" q) }
  69.                                     keyflag = 0;
    4 N) f% D( }" C- T
  70.                                     keyValue = ShoutKey3;
    ) s" A$ z9 v3 V% G& Y; P$ I6 s2 {
  71.                                     keyState = 0;
    0 |8 M0 {+ w9 m
  72.                                 }   
    4 K* r! G' u! h( Q2 B8 K1 H
  73.                             }       8 c+ k6 }% C/ D+ R; \
  74.                             break;
    $ w. ~" S) O" Q1 p- ?
  75.                     case 4:if(KEYB_4!=0)# B8 U' X+ s( d0 F- `% ?9 k
  76.                             {
    0 C- p3 T0 {3 C5 [  O
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    2 y$ k8 p5 g7 C7 Z: E: V
  78.                                 {
    6 r- C+ p0 ~: A' b
  79.                                     keyCount = 0;
    - w; A7 d- ]: `# {* Q  N) b
  80.                                     keyflag = 0;
    + \5 F, Q: c7 e
  81.                                     keyValue = ShoutKey4;
    % y: G, Y' ~1 A* G1 N# M- Y) O7 X
  82.                                     keyState = 0;
    2 s* g: s5 R8 y% p6 \# Q7 K3 X
  83.                                 }   + O. ~7 y7 Y3 ^8 i# O
  84.                             }; z# r0 s, G2 U2 o/ W: n3 s  V
  85.                             break;( @2 [; u# ^: n; f5 t6 P( C) ]8 e0 ^
  86.                 }. e7 _( M' x' A
  87.                 if(keyCount > 800)//长按" t5 D* B$ }, ~; ?
  88.                 {   / D2 ]9 U. \1 p& f5 O' t
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    3 {( s; e/ Z5 o3 C
  90.                     else if(KEYB_2==0)keyValue = LongKey2;! W- @( e4 O5 Q1 P
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    , ^9 N% J/ h- m+ a9 l% K
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    7 l6 y9 x0 E3 `( n' T1 b" G0 v
  93. # K& O) R, o8 s7 _4 N/ I
  94.                     keyState = 3;
    * y' c6 p. s7 J0 t" m# Q2 H
  95.                 }
    7 L9 v' N* Y+ N$ q: c+ j
  96.                 break;8 K8 b( n" x* S% U7 l7 ~. l& q- g

  97. 0 q# E% u5 m5 w9 V9 h; j, y/ a1 A  x
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    1 Z) N/ f% I8 k3 _
  99.                 {
    + w& v: x- F" u4 x7 e
  100.                     keyCount = 0;$ Q  w# J" a3 C& _8 w2 r
  101.                     keyflag = 0;% j$ \* c* M! q6 L
  102.                     keyState = 0;
    ) {. m# P4 n2 `  {
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  # y& v9 q1 F6 B& I, X- ^
  104.                 }/ |( B4 c& R& i% r2 C  a
  105.                
    7 i- w) R! W4 [* b* D2 D
  106.                 break;& P! n4 k; l: O
  107.     }
    7 P# [4 D2 f6 R, A* f$ w$ F' }
  108. }
    " E( Y" ~8 F  B% q2 u8 p& P! r* g
复制代码
(2)key.h8 r/ G( ?0 r% r- X
  1. #ifndef __KEY_H" D+ x) ~% b* T; U
  2. #define __KEY_H& u$ e$ Z" U% [5 U, T" m
  3. #include "stm32g4xx_hal.h"; U& Q" l; n( m8 [
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB09 ^6 z$ I  d9 `) J$ R
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    6 Z7 w+ t. t! K! e- r) B
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB23 F0 m/ P& V* |* h$ I/ d
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0
    5 ]3 Z! o; B0 ^/ k2 W9 o! e
  8. #define ShoutKey1             1
    4 S$ u$ b/ U7 C' y. p0 {% \
  9. #define ShoutKey2                2
    2 ^" ?" t9 O. U
  10. #define ShoutKey3                3
    1 E1 x" [$ C+ H
  11. #define ShoutKey4       4
    2 ^" F) o+ |; P* d; ~; |; c  P
  12. #define LongKey1             5* X: L8 |4 O5 S" {5 p& [" X( Z
  13. #define LongKey2                6
    $ `* f! i$ I3 I. p; T5 _% M
  14. #define LongKey3                7
    2 o4 t, b# p* w' q/ N7 C
  15. #define LongKey4        8% x& I/ m9 a  s1 a- A" Y: k
  16. void Key_Scan(void);
    8 r; E  g% Q3 F1 d- l
  17. #endif
    # v+ G9 C- p7 L3 X
复制代码
3. 计时操作" j. Z% [, o. b
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。/ t& K- ]* v: i( v7 I' k, q
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~
; E( p1 j: K. e& f2 d5 J
  1. extern uint8_t keyflag;
    6 ^, o' @  |' Z" F
  2. unsigned int keyCount = 0;
    3 x1 V* `) t/ P  ^# n8 B3 ^1 F
  3. void SysTick_Handler(void)
    3 d3 u1 {, A$ Y" E+ ^7 e5 H  i
  4. {
    % n7 u, N! h) u1 Q3 u
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    ' _" _& N: v( I$ v, B
  6.         if(keyflag == 1) //若有按键按下就开始计时2 ~9 P; ]% b4 [! l1 {' C2 E
  7.                 keyCount++;          d9 D7 [; X, v5 k# m5 V
  8. }( u: s1 u; M0 N2 S
复制代码
三、应用层简单逻辑实现6 ^3 D1 ^0 Q+ P3 b7 F& R3 a5 o9 p
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~( R4 i: ]( r5 G8 j$ z- Z; T$ E
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 % c) D! I/ ?7 c5 [* K) f
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器7 ~5 d: q- p" W: L* u8 k2 t9 b) F4 q
  3. while (1), G  v. X; O9 d) [) g! R
  4. {6 A: B0 V$ J& r& E
  5.                 Key_Scan();
    4 m* P& W% p$ t; M' T: S4 S& m+ _
  6.                 if(keyValue) //有按键按下2 G" {9 X! R# y( O3 A4 f
  7.                 {
    . a* Y2 A' l$ {( R- V
  8.                         if(keyValue < 5) //短按) \0 b+ G, D/ q: s) F9 u& O
  9.                         {$ B8 N0 W1 ^/ O; w1 E% K
  10.                                 switch(keyValue)
    4 z$ @* M5 w# c1 q# A3 b0 {
  11.                                 {) Z/ d) e9 X3 S8 ]7 d5 E
  12.                                         case 1:5 ?+ S: H( T/ A6 z/ {
  13.                                                         keyValue = 0;) h) O5 ~& v6 M+ s! U4 F
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);) a0 B: H4 i- c4 h9 S2 ]/ i
  15.                                                         HAL_Delay(100);% i: l; x$ ?( ^6 S# j! o. z. e5 ?- C% w
  16.                                         break;$ [( O4 v  l; {- f8 }' K' N
  17.                                         case 2:
    1 {; b4 a# f8 X; W' e4 k5 N9 }" N+ U
  18.                                                         keyValue = 0;( R- q; p. s, O
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);2 A7 l" N! o/ z2 T0 d$ L
  20.                                                         HAL_Delay(100);
    0 K0 M$ I7 a9 T; C
  21.                                         break;9 w0 C! \0 J' t2 P
  22.                                         case 3:4 ^. j+ A: [3 H
  23.                                                         keyValue = 0;
    ! _# L- m6 i' s; E6 I4 T! `! H
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);5 a# e/ V9 |/ g: }
  25.                                                         HAL_Delay(100);
    ) L) b) z7 r6 I. m8 p! D
  26.                                         break;
    4 x0 F& w" e  w7 ~9 l2 I  o7 @
  27.                                         case 4:* K* A+ [0 u4 D+ Y! ^3 }
  28.                                                         keyValue = 0;: X( S8 b% V/ j& ?: a5 w
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);! s* y5 d2 \$ q* I. h/ i' q
  30.                                                         HAL_Delay(100);4 k0 a; h$ H- r3 n5 U$ z7 \1 R
  31.                                         break;
    1 {6 F* n! S" G* I
  32.                                 }
    & e6 t6 U4 t" c; C
  33.                         }
    4 `1 e, {# T# J2 a$ k6 `: v* F6 @  g
  34.                         else
    , L% T5 Q8 J$ e  H( {8 G  I& k3 c
  35.                         {
    : o( }! l( s. Z
  36.                                 switch(keyValue): K. l# M2 ?# R5 e  b0 p2 C
  37.                                 {
      a5 y- p; z2 P" U+ O
  38.                                         case 5:! i9 L  F8 y! U/ D: S
  39.                                                         keyValue = 0;' L1 g. ]5 A* ?# e* ?
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);$ C. M4 G) u! B$ K3 s, v
  41.                                                         HAL_Delay(100);: Q( {0 z  Z2 A; _0 {
  42.                                         break;
    6 C8 l7 p7 d( s0 d7 e
  43.                                         case 6:" M0 @$ z/ T0 C7 u, w: |) P! F
  44.                                                         keyValue = 0;$ @$ g9 X' E+ e0 }
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    8 s# `; \2 J6 M3 J0 T5 ]6 L* q
  46.                                                         HAL_Delay(100);" j) }, i5 W9 Z* N$ h5 t* C; f
  47.                                         break;
    : G1 h% H8 s' i2 t0 g5 j
  48.                                         case 7:: B7 g. _; K! _; t) k3 y, d
  49.                                                         keyValue = 0;
    1 S5 U- M3 _; V' Q) U& G
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);; `' K+ {# V4 ~7 O
  51.                                                         HAL_Delay(100);
    / w6 d$ a' c% @) X& @
  52.                                         break;
    / _! J% d$ h2 L7 f& O) ]; C0 _
  53.                                         case 8:
    ) x$ ^- m: b$ z+ `( E, N5 U
  54.                                                         keyValue = 0;8 }  C; d9 E; u
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);6 M7 `# v9 ^1 J: {! B
  56.                                                         HAL_Delay(100);
      z/ i) H7 A! p3 N" F" m
  57.                                         break;* B4 G+ K# z: ]6 L. D
  58.                                 }* j/ v3 j" y" a$ ~+ `
  59.                         }2 X$ e0 q  q( i2 H/ A
  60.                 }& j* f3 b6 e2 V8 k" b4 ^: _9 o4 a$ U
  61. }+ ?2 C# G. |% j% A4 {5 R
复制代码
总结
0 C9 P0 a# q5 e" x以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
' Q9 u' v: P) ?  I6 ]* @) i$ g; ]' x0 c6 W9 ^9 c5 q4 E& q7 q! ~7 }

( ]8 ]& Q1 M1 O7 E4 o, x9 j
# F" I% y  Q( |# }, Q+ ^* _

, R1 C# M! X3 I9 h/ W% J4 Z7 O" }( Z% X; X0 I# G
- ]2 |9 o4 `6 b
! T, ~2 ^7 S8 e; i7 ]2 O' Y! K+ Q
2 D9 m* f4 ^9 t: }- v. b% I2 X
9 Z6 B  Q/ b+ E8 x* _7 U. B
赞 收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~  w# V2 d1 _! ?* A; c2 r# I

所属标签

相似技术帖

官网相关资源

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