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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
+ _, h" r# o! e# ~: @2 m
2 {  ?9 W  [6 E前言& W- o+ ~9 o" ~9 s  z
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。
! c. y8 n% D; Z. N, p注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
: V' B( a6 F7 v( m由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
/ e2 F6 R, l1 v: r1 B+ t) i* t" N* x3 v: s9 x
$ k% H* Q# o0 R; H8 h) V
先放一张开发板的实物图,它长这样~
* J9 g; O- d, k/ w0 H: ~& ~+ n/ |
15.png
一、硬件操作
2 X4 n, r" y- B: z# ~0 }! e/ R在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。- K. p" q/ F  ^& c2 z8 Q/ V

$ H: }8 d/ B' Z5 s7 B
! f, j9 w6 R" y5 ?7 x
1. 原理图* H7 h/ T5 t# M" S9 n
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。9 ]& g) F+ k$ r& ~# L& a
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
4 q7 [' _* C; q/ O7 J" R1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;' V' q1 c0 K! T" l
2.按键相关的IO口:PB0,PB1,PB2,PA0。9 \" g7 _2 l. ^% ^
& U6 N: z* W8 f& @! k$ ?$ w7 }# D

6 X. j- X1 @' h% w% h0 j3 d* {/ u( z2. 硬件分析. H6 p7 i* x  B
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
+ N. r) D7 v) S" m* q- Y' L, G' ^* }" i( {: ~
7 X% ]) f9 ]$ q& u4 ?9 B# \
3. 初始化代码+ [# n1 d" s$ T6 p* S: k: t' k/ f" m
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */6 h) e+ F. r& }  v' Z5 E
  2.   HAL_Init();//使用默认配置即可
    2 [2 R7 j" j3 \; C) r
  3.   /* Configure the system clock */
    ; I$ z3 f6 u& H4 C6 s
  4.   SystemClock_Config();: T4 |5 i6 t, N* j' F/ b. n4 q
  5.   /* Initialize all configured peripherals */# U+ K" m# G3 l0 Q, O
  6.   MX_GPIO_Init();# T( Q% i: ~- j1 Z! j
复制代码
(1)时钟设置7 C2 q0 ]1 j- k8 V6 U. d
这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
# s, v: l; Y( B  M/ T3 Y* D1 O
  1. void SystemClock_Config(void)8 z+ o# i8 @% ~2 Q" ]
  2. {
    2 W; P$ ?1 A3 m/ E# G
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    ! M4 b" J7 E* p1 C% i
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};2 O! G9 V" Q- z  k
  5. 9 E4 J& b2 K8 b$ Y8 p: P( s
  6.   /** Configure the main internal regulator output voltage ' ]5 ~6 d4 V, [" e& d+ k& |9 P
  7.   */( Q" k0 g, }" r6 R- x
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);, F5 |  Q3 e8 W
  9.   /** Initializes the CPU, AHB and APB busses clocks
    ( y5 J9 B0 ?1 Z" z- T; {
  10.   */
    / U, R0 Y' g# a0 x) j2 P; j, ~6 l' U( s
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    0 B! h8 A' J# a9 u- t2 z
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;- _: l) [3 [; [& [6 E
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    $ v" j9 ]" }& ?
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;; l8 u! [+ a. t
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;( h6 d1 o. N/ ?1 m1 U9 T
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    - X6 v! ?7 G! b6 G% W! r6 ^
  17.   RCC_OscInitStruct.PLL.PLLN = 20;& z% l8 R% m- n) Z' U( A! Y
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    2 ?& \% [' n' U; l
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    ; h, ~* n0 h7 |
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    2 P( I! {5 I1 H
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)* [+ S: x' F1 |( i
  22.   {
    6 V1 R& e- W0 C) ?- B! {
  23.     Error_Handler();& X( B  C6 _% X5 F4 O- Z
  24.   }' r1 p# N, e2 d8 R5 L
  25.   /** Initializes the CPU, AHB and APB busses clocks
    ( ]. Y' v+ q4 R; M
  26.   */
    $ g3 Z5 r! V9 ^8 w! l$ k5 A
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    " w4 x, h6 h; I7 T' h
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;! n* A  Q# o# u" p* h% e+ v( o7 m
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    0 T5 B. M/ ]  f
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;  h  \0 W; ^( M4 U' }) }8 N8 l
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;# ^. z" g9 K( p  @' D0 e+ B, z6 u
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    * S) C: U, {0 ]) a

  33. , l( N- x5 L5 @
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
    ! k3 |7 W+ x  ?! s' o0 U8 A% @# s
  35.   {) P0 A( Q4 j, {' `& w1 o
  36.     Error_Handler();
    % ?, B( K: _' n( a- d: z% ^/ F
  37.   }$ u# ^7 B6 y1 G3 |8 m( o
  38. }
    * f' R* Q" B# N* y* g6 v
复制代码
(2)GPIO初始化
, v5 k2 f& O$ b
  1. static void MX_GPIO_Init(void)
    8 S& s9 L' y3 l) \- [
  2. {
    2 N2 n3 l0 F- T' C  {7 Y0 X4 o
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};  f+ Z: g) T: r
  4. 4 B/ a1 F0 x2 @3 o5 g- w- s( {
  5.   /* GPIO Ports Clock Enable */
      |3 u2 n5 {: G0 ?6 e# ]- e" N
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();9 k$ C2 Z$ x. P1 \$ e# S6 N
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();) ^  q, b( s9 V9 t0 k6 S
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    % E$ V% P3 S8 R
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    ( ]$ ?$ ], Z) _, k
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    7 \0 n) P& ^" k7 v, V7 [
  11. . @7 n& k! B7 I; [& M) O* G
  12.   /*Configure GPIO pin Output Level */
    6 ]' I7 ]5 o  s' t6 e
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    , w; |; }' `5 t$ Z) c9 ^9 @
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);/ W/ V8 ~$ U% E- y5 z" z: [

  15. , ?0 |- z6 [. q5 K5 A. e0 Q9 j
  16.   /*Configure GPIO pin Output Level */
    1 R  f5 n3 q; m6 h( V3 ]+ v8 c, u
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    ; M& w/ `/ B6 I3 }/ s
  18. 7 I& h0 ^+ R6 ^
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 4 _3 @' S- |* W3 K1 Z2 O
  20.                            PC9 PC10 PC11 PC12 */
    6 |0 M5 ~  P1 ?! @# C+ o) ^
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 ) B' H, E, l7 S: V5 C- G
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;* h2 T! }" @( Q* b2 f/ m
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    ; T* b. I1 i; P5 s$ \
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    $ Q+ j' n( o0 C8 A& ^
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;6 w/ f; A7 U/ Z+ R  o
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);& F1 V; W% c! B# y
  27. ; i, _- m  K0 G
  28.   /*Configure GPIO pin : PA0 */; d1 Y2 O0 T) u, v# \
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;& A2 k# Z$ V" |! x5 G/ u1 r+ S
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;; k) \4 ]) r2 _+ ~
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;5 r( h9 z- T% f% V+ i% b$ _8 K5 e1 u
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    + [7 I/ ^: W; T$ n% T

  33. : D$ ~# x% w1 _% }
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */' C9 Q2 J$ \7 l5 }; I9 I, ~" Y
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;; U  H) Q" T: F: Z% ^$ e
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;" M8 h8 H  O9 O2 a. X
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;; Z' o0 X, V& Z  S1 g
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    % E: v: B) X5 G# ~3 Q4 v7 \; t  |

  39. . q8 |- [) p$ ~% A
  40.   /*Configure GPIO pin : PD2 */: s& D+ v, W3 L4 I2 W" w3 a
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;/ |$ n1 I# f5 M0 j4 C0 Q# z
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;+ w6 X/ L+ x' W
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    ' U2 T$ \% u- U" l, v5 g
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    . B0 d# l$ J3 }8 ^1 W; h1 e
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    ( Z% [& |7 J8 E% S# C7 K0 f

  46.   L0 v* c1 X* \% D/ U" Y- u
  47. }
    7 T  C! u" |  M- o
复制代码
二、按键模块的驱动层实现6 o0 X9 o2 H- W! O
1. 硬件框图
! g1 f5 h/ B- ]# M4 Z在这里插入图片描述8 _9 p8 ^  B0 y# U2 Z, @/ R
11.png * i& k9 v2 |, [# u
避坑点:" R/ o/ G- ]3 ^2 _) o
短按:按键释放时判断时间) E4 o% m9 w: W
长按:直接判断时间" P" b( ~3 Q8 n& |3 y) u

3 ^& \& c+ Z$ K! X! \; w, e& b
( R  w5 G5 W; \: d/ k
2. 按键驱动层代码实现
* t  f! S; l+ U$ q& d1 r7 v; j5 ?下面直接上C代码:& o" h) g9 B2 x: s8 g
2 m' O0 ]* n% W
, t" U" J" [2 ?/ q
(1)key.c# O- F7 Q- ]2 u# k- {: m
  1. extern unsigned int keyCount;
    8 `6 ~( N7 j/ R8 S2 d/ }$ \
  2. extern uint8_t keyValue;
    4 |% a( ]0 k7 U, y' n, a! Y& \  A
  3. uint8_t keyflag = 0;
    6 E2 Z0 {( }: s( T% P+ @" o: P
  4. void Key_Scan(void)6 G: F% J: T+ B# O" ~' f+ c4 i' _
  5. {9 P/ E7 `+ g* y( M) m% N
  6. //keyState  按键状态;- g6 a, V* }2 N* v9 Z
  7. //keyPass   记录哪一个按键被按下
    * T3 W2 C- b3 k
  8. //keyCount  记录按键按下时间
    9 a/ D9 U7 _4 F0 m: m6 w
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时( L1 H  M1 S% ?! A- f4 }
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件( E; P8 f' ~% q3 y
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按
    $ M5 L9 k7 v0 G  Z# m
  12. //ShoutKeyx 短按x键值,# L9 P0 K4 N, i# u& W
  13. //LongKeyx        长按x键值6 Z# z/ |- p* X! d2 a
  14.     static uint8_t keyState = 0,keyPass = 0;& D4 S2 |+ ]; b" a- Q) \
  15.     switch(keyState)
    : B; r4 R4 B4 T. o4 X" l3 K5 i
  16.     {* b  _% \7 Y5 u4 j
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)+ [1 p9 e8 I& u8 ^6 v
  18.                 {
    ( I: h9 `5 s% S/ `2 C2 ?
  19.                     HAL_Delay(100);//消抖
    : j+ p& i5 e  Y
  20.                     keyState = 1;
    ( r1 C( K- B6 l5 L
  21.                     keyPass = 0xff; //初始化按键
    2 f4 v: N$ w3 M/ H- m$ o
  22.                 }   0 y. C7 y9 }+ b: Q8 B4 j
  23.                 break;" H# E4 d* n8 G! m  b2 s& ?1 r' [
  24.                     
    $ X* b* [- I1 k3 ~$ T% B% ^
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    4 ]7 {8 W9 z0 t+ `2 {- r" e
  26.                 {
    / Z9 Z1 d. f4 Q; f" H- J
  27.                     keyState = 2;5 t+ M) e( E+ s3 O; t
  28.                     keyflag = 1;//开始计数5 ^" a8 F$ x" O* l- [3 p" F
  29.                     if(KEYB_1==0){+ V" P: @0 m; L
  30.                         keyPass = 1;//返回对应键值
    9 m3 q9 ^, [+ h+ c3 X
  31.                     }   7 s9 h& g5 }4 o% i
  32.                     else if(KEYB_2==0)keyPass = 2;9 M9 d7 S3 l/ M+ s$ Z- G. H
  33.                     else if(KEYB_3==0)keyPass = 3;
    ( l8 K* Z' X/ a; h2 |
  34.                     else if(KEYB_4==0)keyPass = 4;' j6 n% ?) b' U: W0 ~$ p
  35.                 }   % l# ^. ]4 m! @2 N1 G
  36.                 else keyState = 0;//返回检测按键      5 U* J. ?: e( h9 h5 y+ K8 e1 z( I! X
  37.                
    : t. J9 }4 J4 ^% A  r3 ~
  38.                 break;$ H8 ~- a8 h+ P* P+ I4 u) J+ Q
  39.         case 2:- E5 K# Y8 }# x- _2 V1 t1 R
  40.                 switch(keyPass)
    & {% V/ X- i* J6 V& V
  41.                 {                ^. ^1 Z! Z# E' n8 F) ]9 g% V
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    8 w" ~8 Q8 X; k4 w
  43.                             {
    9 `( }  F( r) m. s* b" r% ?
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按$ `- P+ {( `/ Q2 n8 ?
  45.                                 {
    * T3 W& V) s1 w
  46.                                     keyCount = 0;( L2 P  v' o3 d
  47.                                     keyflag = 0;
      Y. R8 A, G! v! E
  48.                                     keyValue = ShoutKey1;
    - l1 K2 j% q4 N( m1 X
  49.                                     keyState = 0;$ {# u  t7 a2 `1 j( Q1 {
  50.                                 }   
    # ^* y8 q# q% C
  51.                             }       : g9 ?0 D+ j6 r
  52.                             break;
    . ]2 d/ g3 y! U+ j3 x
  53.                     case 2:if(KEYB_2!=0)! e" C& v1 J0 b6 P* U( ?6 q+ d
  54.                             {
    0 J6 h3 n, w- R$ C" S: X8 n: [
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    % f9 G& f4 X- X8 Z* j. L
  56.                                 {! M+ Z& J4 Q+ S. r* }" ?1 j+ z
  57.                                     keyCount = 0;6 a9 n) ]3 K4 S
  58.                                     keyflag = 0;. V/ L2 y1 Y) }+ V" v2 N
  59.                                     keyValue = ShoutKey2;
    + ^# [% u. F/ L& I$ ^
  60.                                     keyState = 0;
    ) Z+ V' K" Q% Q, z( K
  61.                                 }     t; x/ {- h7 x; y( u" A1 S
  62.                             }      
    9 w  y! `4 X6 i
  63.                             break;
    2 D. q/ ]# R5 d$ p/ M, n
  64.                     case 3:if(KEYB_3!=0)
    4 ?6 Y8 v, ~8 p  `: J
  65.                             {; H6 |$ ^4 O( l" A
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按3 i  r  d. c+ U: T+ U: _$ r
  67.                                 {) k" D- ?: }5 p+ Q: [+ s
  68.                                     keyCount = 0;0 M% x( S1 m) j/ O/ U
  69.                                     keyflag = 0;6 ?7 k' V- O* V5 A6 o4 D
  70.                                     keyValue = ShoutKey3; * b2 j* v- j9 ]/ F3 N$ v, J$ O- D
  71.                                     keyState = 0;9 `. ]9 M  U: v3 ~* \2 \' e+ D  `
  72.                                 }   
    0 f9 H$ H: L9 C2 B9 t
  73.                             }         [! h$ S( Y: T
  74.                             break;+ }9 ~3 F, h/ K
  75.                     case 4:if(KEYB_4!=0)
    5 \' p) u5 \2 j4 E1 R7 z/ z5 t
  76.                             {
    ' a" x) V9 J& K- C9 N# h
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    ' O* r+ y  A( q* i: c5 z' R
  78.                                 {
    1 Z( N, Y4 N) c# R
  79.                                     keyCount = 0;* N* r9 w  s4 G& N
  80.                                     keyflag = 0;) p/ Q! z8 E/ Y0 k
  81.                                     keyValue = ShoutKey4; 0 `; x2 \! t  p8 ?/ v8 f$ i/ N1 k$ L/ ?
  82.                                     keyState = 0;
      U. J5 ]  M$ q8 Q* Y% @( q
  83.                                 }   
    ; X% h+ [. t* e3 J# V7 M
  84.                             }6 c" |* X! F9 }6 V8 V
  85.                             break;1 X- F* V$ h4 m$ L1 r8 M1 P
  86.                 }0 A' ]- M/ \( F+ H# W# L9 M
  87.                 if(keyCount > 800)//长按
    $ D3 |; W3 M) `
  88.                 {   $ w( R# }3 U2 x
  89.                     if(KEYB_1==0)keyValue = LongKey1; 0 `  q, O5 v& F3 }' s
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    8 c! {, R. d9 ]8 R4 F
  91.                     else if(KEYB_3==0)keyValue = LongKey3;; d7 o7 j3 C4 ^# {' `
  92.                     else if(KEYB_4==0)keyValue = LongKey4;. Y/ @# H8 ^% R3 g$ _* s

  93. 8 v- H4 t  s" q- l! I
  94.                     keyState = 3;* X* i* R- w1 ^5 L/ w1 X  D: r' |
  95.                 }
    ( {7 G& Y; C! I7 e  b: k! T
  96.                 break;; {$ ~9 y; a& ~
  97. . p4 H' ^# k/ U6 S  ^/ Y
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    . @) Z6 H- F) O( [' U, I
  99.                 {
    + N0 c1 U5 d( p0 M& |2 K
  100.                     keyCount = 0;( R" v, u3 a6 n. j6 u/ X; p  C+ F! G3 U
  101.                     keyflag = 0;
    # _9 T  f! _; J* }
  102.                     keyState = 0;
    7 j  X- y- p/ }, D* Z: w
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  " g4 P* Z* i9 c: F" W. z3 Z) [
  104.                 }
    & b8 W( K  G3 @; p4 p
  105.                
    + M3 _  i5 ~" c1 ]& u  {0 m
  106.                 break;
    5 g6 F* f4 x+ [+ i
  107.     }
      [5 B* g# H8 E$ |
  108. }! o0 }" g# d) y+ Y
复制代码
(2)key.h  A) |' i- d( K% x& |* Z! P- L+ e
  1. #ifndef __KEY_H5 P$ Q( @$ S% I! a$ @
  2. #define __KEY_H1 n5 Q- A$ D! X+ M2 `6 }9 t" t3 n7 r
  3. #include "stm32g4xx_hal.h"' ^6 `# ]. N5 F. G
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    # R1 _: p* A" e5 X# o' ]& `4 m
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB14 N; v4 p9 `, m# I( d
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB20 y; d+ [* R" N. U8 G
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA07 D6 u# O& j+ |/ ?. C; X: e
  8. #define ShoutKey1             1
    " S6 Z% F( U, Y& V3 t6 C0 Z' M- g5 X
  9. #define ShoutKey2                20 g- ?' s' a# {
  10. #define ShoutKey3                35 a1 ]- u* A3 A9 i# B7 s5 p" S
  11. #define ShoutKey4       43 S( _/ N7 v# F& R3 d
  12. #define LongKey1             5" j1 g! f" V& t' @$ ?9 w6 N* E
  13. #define LongKey2                6
    $ n% T# o, Z- f2 j# l  e
  14. #define LongKey3                7
    3 o, ]; X- }& u1 Y( s& {
  15. #define LongKey4        8
    + a3 i0 Q0 P" p" ]
  16. void Key_Scan(void);  y' r/ y- T& z
  17. #endif# Z- Z5 m  N1 |% f: p
复制代码
3. 计时操作$ r. T4 m% z5 t! ?8 {* l3 O
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。; `0 z' K+ {: F8 l1 v) M
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~
/ r, |  k  W1 l+ ?
  1. extern uint8_t keyflag;* p; m% m: E' @- I
  2. unsigned int keyCount = 0;
    0 S0 X( x" r# n" e" E6 @) l; O: v
  3. void SysTick_Handler(void)
    , i+ `4 }2 ]6 G# C( l  g$ V9 r6 X
  4. {4 T$ ]& ?! ]8 J5 k) Y; b
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    3 Z2 B4 B! K1 k2 t# Q, x8 V
  6.         if(keyflag == 1) //若有按键按下就开始计时
    " e2 T2 `% p) |# \. ~6 e1 z2 I$ _
  7.                 keyCount++;       
    % }; m; q5 W. z3 ^  F; c
  8. }
    ; l+ M" ~: _5 H! [
复制代码
三、应用层简单逻辑实现. I$ e3 x$ Y0 K& F. o6 j
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
+ r6 M1 _) \$ A0 U
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 6 x8 `2 Y! B/ R4 m1 B/ m
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    ' I% Q) J* b% Y6 m
  3. while (1)1 b9 n9 ?: Y9 O% k6 E9 _1 c5 j; S
  4. {! v6 {6 e8 i, P4 t' X
  5.                 Key_Scan();2 r1 d3 ~. O+ k
  6.                 if(keyValue) //有按键按下" s: J6 W  \. I+ \9 T+ l
  7.                 {
    ' R) V% L8 j2 u* ^# {
  8.                         if(keyValue < 5) //短按7 W- V( J$ `4 h1 F
  9.                         {
    3 w- W" ?3 e! U! H7 b. {' Z, e- \. b
  10.                                 switch(keyValue)
      v7 J, A  D% x
  11.                                 {; ]. `1 Z5 n! F0 a# z7 |6 ?% _7 M  z
  12.                                         case 1:
    $ `. U$ U8 ?2 t; ^: z
  13.                                                         keyValue = 0;
    ) w+ a3 }9 T- f8 a( v
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
    , ]( e; U  \5 r& u' `
  15.                                                         HAL_Delay(100);+ ?$ U& l; \& B4 w/ o
  16.                                         break;% E% I1 d9 Y4 D0 F0 E2 \# ]
  17.                                         case 2:  A. u& s. K7 N0 h
  18.                                                         keyValue = 0;+ [1 ^( H& U9 w$ ~: ^, r! V  }
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    ' g" @# }! H& m
  20.                                                         HAL_Delay(100);& q+ j6 Q! D" o7 Z% ^, O  w: @9 B
  21.                                         break;- C+ m7 h5 U, k& S7 ^3 f' _( @
  22.                                         case 3:
    2 r  {/ h+ i9 y  |- I
  23.                                                         keyValue = 0;. y6 w) i  v2 O! g
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);! a5 w9 E8 n( I- |1 a
  25.                                                         HAL_Delay(100);) R: Q7 \" U; r( y6 K/ ]3 |
  26.                                         break;
    7 [9 ?+ m* B8 x* P$ r" i( ~
  27.                                         case 4:6 ]7 a! d8 {4 {
  28.                                                         keyValue = 0;
    ) a' P8 O+ N+ C' k' n  B2 Z! J
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    0 B" Y: P: y- t6 j: T
  30.                                                         HAL_Delay(100);
    * q) u, F' ~3 [7 A0 t5 H9 l9 ]
  31.                                         break;8 V6 U9 l5 ^! V  P# a9 h8 I
  32.                                 }
    % U+ k6 b5 w9 @: B
  33.                         }
    7 ^3 R0 g$ Z8 \& y5 a" B5 Q
  34.                         else! _  a6 G- K4 [7 W5 c8 `7 j
  35.                         {. _: p2 G( Y$ B+ t' j1 W) c6 C4 }
  36.                                 switch(keyValue)
    % a& D9 D6 y2 b0 d- [( u/ j& n
  37.                                 {
    0 Q" M3 a1 O) F# h4 o9 R1 t2 v) J
  38.                                         case 5:$ o9 k1 g  Y: }- K+ @
  39.                                                         keyValue = 0;
    - z2 Z7 B* i& D& Z1 H) _+ G
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);2 @) f4 k% j/ O, L
  41.                                                         HAL_Delay(100);% L# P: g4 [( q' s7 X' I
  42.                                         break;; }1 C, R  e5 P% ~8 _! o0 x
  43.                                         case 6:
    % k* S8 \( `+ J' N6 h
  44.                                                         keyValue = 0;: `/ }2 V$ V" T, I0 @
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    2 n. }% v: [7 ]9 ^$ N
  46.                                                         HAL_Delay(100);
    : ~) u5 G, X- |1 B* D
  47.                                         break;' a7 @8 Z5 q3 Q+ Y# F
  48.                                         case 7:" N; `( I7 q5 U4 b, ]6 v6 o
  49.                                                         keyValue = 0;
    ! c! o- h& t# `
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    , O' U# a1 g9 b2 y$ G  Y! f
  51.                                                         HAL_Delay(100);3 Z% R$ m8 B3 w- z
  52.                                         break;7 t5 ^* @" N. e( N( a
  53.                                         case 8:
    ) N1 X, `! o# F8 _: p; V- }
  54.                                                         keyValue = 0;
    . E) w1 N6 W% p1 h: T! }7 N
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);; R! M7 i( }! w) Y# t9 S, [
  56.                                                         HAL_Delay(100);
    3 R* \) T' I7 Q* m1 G
  57.                                         break;
    3 k3 x' E7 ^) R2 h; F
  58.                                 }
    7 M. {7 m9 `( l) T
  59.                         }- w: f4 K6 g; j* |4 @% s
  60.                 }5 K! p5 }7 A5 ]* t
  61. }
    ( r0 B) s# h- p
复制代码
总结/ A" v9 K5 Y9 `5 t: ^; \
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。  p' X0 F" B1 T' q2 i

! M/ i" d* H, P% A  u+ a

9 C; U. d; {7 g9 B( ]+ v! F7 }1 f) k, r

: `5 W* K4 \- j5 g9 e  J& c% R6 X' K: g6 N
. n0 {. Y3 m; x1 j
, r& g. ^; P% [0 X2 l& A# i

3 [3 q/ Z. y* C( {! h* [6 c
5 I3 v2 ~* x) }$ }
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~4 _1 u7 \$ \) s

所属标签

相似技术帖

官网相关资源

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