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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块9 _+ U7 O5 c! p

" U/ s% x; J0 {+ b: G1 U$ n+ F前言
7 d/ Z! i: [4 x6 C5 D我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。& J6 q! k1 s! N6 V5 B7 Z
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
/ v/ N/ {# N$ r: N4 X  c$ @由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~/ x0 a% I: a0 K3 [# p0 |. F& E
# F) |/ D- Q3 T( j; }' N1 L
( u% R& g* P1 m' W8 n$ B
先放一张开发板的实物图,它长这样~3 g) U- A# ^/ B" |
15.png
一、硬件操作
' e9 h1 P- ^, p7 N$ K% `& H在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
( s! V" O1 {0 O. W1 F  Y2 u, j0 ?9 l8 B, e/ l- X7 J8 g% {/ l0 p

4 j" G) `. h2 _4 [+ V5 o' A; q! l1. 原理图
' p1 }- ~, i( s: C* [. F
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。" G6 U; j: y3 v' D/ Z
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)' h  ~6 V5 u7 r: Z6 j# g
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;' n, N4 j/ w4 N6 e+ J3 U( O
2.按键相关的IO口:PB0,PB1,PB2,PA0。
6 }* Q9 e- k! o3 v4 j* j
5 N2 z) K3 m2 t8 z+ D) R) k

/ @+ n7 E9 v5 M# Y. J( |& h2. 硬件分析1 d# i9 g- X0 X  g: z! a
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。' C2 U. d+ s/ k' s
7 W; G! r8 S" _9 G7 z3 h& i5 E

% h# v9 L2 w4 O5 _8 ?) J2 n9 C' f3. 初始化代码
; D# N; ^5 R9 F  h9 ?
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    ' `% F; b: Y, E' a) @7 k% V
  2.   HAL_Init();//使用默认配置即可
    " i: D- w  h% y; L
  3.   /* Configure the system clock */
    ' Y5 x  I3 _6 o* t
  4.   SystemClock_Config();
    : [; @9 j' |& H; d7 P6 r
  5.   /* Initialize all configured peripherals */
    ! D! \: c$ W0 |  {9 |" ?; p8 C* u
  6.   MX_GPIO_Init();
    5 O& k! l9 v  _* g( a2 A
复制代码
(1)时钟设置
6 A! D' o0 f& u$ u3 ~这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
) S% r" d7 T0 E) I3 Q/ ~  X  J9 x. O/ o
  1. void SystemClock_Config(void)
    & R/ m5 L: N7 p/ N  l7 G/ P0 ^1 O
  2. {
    6 J  U4 l4 m0 k7 w1 k* e
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    8 f' S1 u5 z$ L/ u2 j
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    * O( L" B# m! @7 M7 U8 q2 ]
  5. 1 C1 H1 |# n8 Y0 U
  6.   /** Configure the main internal regulator output voltage $ N; _1 F: w& U- R: T8 z
  7.   */- u" B8 d; h, d, [2 D
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);$ X4 J$ U( h" t/ l' J. x
  9.   /** Initializes the CPU, AHB and APB busses clocks   U' G2 V+ }# q. p, f
  10.   */5 T: @* S) o( h$ U' `8 t( e
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    + w9 c5 z  w3 V8 [4 v9 e
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    $ f1 d/ g4 @& J
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
      Y+ e$ C4 H0 b; ~% V9 a' K
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    4 J! J. A* M) j2 @
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    % F& t' l1 A8 p* _) J$ W# x
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    3 P1 j' D" ]; t0 A& s, X% G
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    . h+ A( T. ?0 b! f$ `  ?2 J- a
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    7 v1 U& i" j  r7 \5 z
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;' I- g2 G3 |( j  Q# l
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    ) I; {& ?: ~: y  v8 G' w6 B
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)3 ^7 j: n5 M# H" V+ J+ r9 I
  22.   {5 v' G- g; O, t; G9 C6 z; k7 e  B! x
  23.     Error_Handler();
    3 ?! m. A, j0 h3 _% _, a& A
  24.   }
    3 m+ s% ]3 z$ T/ c! |
  25.   /** Initializes the CPU, AHB and APB busses clocks . y( _4 H8 Y, l# s# O. [( Q+ E8 l
  26.   */1 E2 ]+ y, P  n6 p7 i; O
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK2 l* J- S. ]$ q: Z
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;; d' g; V  l: b; T7 M
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;) ^" Q, I  X3 o4 ~$ V, z
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;2 }: O& @& T& Q, ^4 K+ ]
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;: O5 p% ?" k: l5 V7 l: q! @
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    ; ~/ r4 @- S/ U9 N

  33. $ y6 D* w9 S! B+ r" h* C, W% e' P* q
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
    & O& `9 p  X0 L+ t
  35.   {
    8 L0 c! W' ~, D
  36.     Error_Handler();* ~5 h3 u& M' t: \) a; D: s
  37.   }
    4 i- I" Z' |- E$ H( E4 \6 \7 _
  38. }
    ; r' p: b' d# `/ V: E1 \" o
复制代码
(2)GPIO初始化
3 O" s5 @6 X' W1 Y# B! k
  1. static void MX_GPIO_Init(void)
    ' a! p  c* a. C- x0 v
  2. {
    , M; _3 u! T* F* E! C
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    8 e9 m; j' t0 Q6 r, h$ m
  4. ) l* t" S0 j- X8 A8 K- o$ I
  5.   /* GPIO Ports Clock Enable */: O; R( }, ]% U/ h/ w6 G4 q
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
    $ X; q0 p- u  I; L4 o- A
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();. K  Y6 y% c. J+ Y
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    / Q. @6 ]3 }/ q
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    1 c: W' G4 j+ q2 a; A
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();+ _- X  k9 f/ ]

  11. : p% E. e0 N- g+ [. w0 C* K$ w
  12.   /*Configure GPIO pin Output Level */
    0 w. T/ L, \( [  g' Z& }- S
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    ; Q3 }  V  z# ?) l  z( p7 E
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);; c  k: }& N" ~0 P2 p. e

  15. ' R& f, x7 Q4 j% K9 ?7 K0 S
  16.   /*Configure GPIO pin Output Level */: R- u. h; }; [6 Z8 q9 n) |
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    " d1 y( B8 X. x5 g
  18. 4 L7 q* h/ y9 u& Q
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8 . {7 [$ _6 h$ V$ A7 o2 M
  20.                            PC9 PC10 PC11 PC12 */
    1 n) [  R- _- m+ [! a; [! `
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    & Z8 O) P4 w- @$ j0 P
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    * d2 @& i  X8 d$ h$ [5 @
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;% K1 _+ a  S8 ?( y$ n9 e0 v5 b
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;" @: _& N7 G7 G9 z, z+ T6 F: a
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;# c+ a3 o; Z7 z8 [% F* z& \) p
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    7 T9 x6 b9 M" s) f; c5 \3 l
  27. ) i2 V/ q/ w: M& j
  28.   /*Configure GPIO pin : PA0 */
    - I6 ]' _1 N, f7 c: x
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;' ]7 `0 [6 n/ @& L0 M, m6 h, d/ S+ f
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    ! u/ [0 `# n! Q( }
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;, x8 o/ K: @5 }5 x" I$ K
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);8 Y# x( n+ J) J+ u, i) f

  33. ! m' W& q( n- Z, m0 W- P" g
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */- E7 \. ^- F5 G7 m
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    1 }8 x7 j* ]$ E/ v6 W. {9 c1 x
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;& X9 Q% W' c. G7 {% H: ^
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;. G$ t6 l2 l/ p/ J8 S! H
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    ( ?# S2 c. U' z7 o" z9 M) o
  39. * K" }0 e4 B, ~" D* d$ S8 H' G& y  |/ R
  40.   /*Configure GPIO pin : PD2 */
    * a' r/ e* k3 |0 O. E2 `
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    # L+ q. Y9 g3 M! G
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;8 a5 U' Z5 V# Z( T4 L, {, n+ s) X7 l! t
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;% _( b2 J/ t+ @: k3 V+ n7 L
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;% @( P+ n2 V( ]5 [9 e
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    ; N2 D$ z- D5 f# H! D6 V
  46. ( D7 H- I9 W  U- ~2 K
  47. }
    % |: t9 N) n8 m" A! {2 s
复制代码
二、按键模块的驱动层实现
( }' V7 m2 u# K) W9 I1. 硬件框图
; m4 e8 p' e$ C: z; T7 [* @6 \在这里插入图片描述
3 A# ?' M' M" C& q0 v 11.png
: Z$ t; B  Q& w& \7 X, a避坑点:
' I9 G' y5 v* v; U" I短按:按键释放时判断时间. Z# V. O4 {% S# l: a2 T3 a, f
长按:直接判断时间/ ^1 D; s% v. d9 i
( j( ]# O/ Z) ]( ]3 Q4 X- ?
7 I. t3 N" ^5 m- X" b! \
2. 按键驱动层代码实现1 L: [' _* ~$ f. Q5 e! u
下面直接上C代码:
2 L5 v- a+ H2 R! g7 j' H
6 K5 _6 u5 _  N4 P5 q0 O( T* v
" @6 O. ]$ W$ f
(1)key.c
5 {5 `5 d" r+ A4 u6 u, ?
  1. extern unsigned int keyCount;% f; Z, C2 o! u2 b4 M6 S
  2. extern uint8_t keyValue;& ~( G8 X; ]2 G( n* z6 ?5 I
  3. uint8_t keyflag = 0;9 Z* g! S* T% B7 D7 h: Y  j
  4. void Key_Scan(void)4 n) Q) Q; ?, _  g  R: K! T  ~4 t
  5. {
    3 q$ W* t" i: D
  6. //keyState  按键状态;
    ' |2 N# C4 f# ~, \6 ~. `" E/ {2 r: C
  7. //keyPass   记录哪一个按键被按下
      D8 F7 g3 N8 z; j. ^, l# o+ X
  8. //keyCount  记录按键按下时间
    3 S/ |' k, k. C, j/ m3 e, Z. J
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时; ^- X3 p4 k& |9 ]& r1 `" v& a, I
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件
    5 N5 M: t  X' g4 g) C5 ~6 t$ B! _
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按3 z% ^" x2 C$ j' y3 t8 Y  u
  12. //ShoutKeyx 短按x键值,
    $ A/ K  B5 G2 n( Z
  13. //LongKeyx        长按x键值# g# m1 e  A- U) r" L3 ^
  14.     static uint8_t keyState = 0,keyPass = 0;& i9 N0 d- B9 k5 P( f' Y7 ?% _# i
  15.     switch(keyState). b& F) x+ A5 o( `  H
  16.     {
    4 p5 y5 @" S1 I  \! a
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    2 t: o% \9 Q# \$ k* S
  18.                 {
    . x3 b3 h" c0 u& J/ E- u# L
  19.                     HAL_Delay(100);//消抖- q4 T( k& S/ v  B& y- ]
  20.                     keyState = 1;* _- W( o7 a; X6 ]; i& Q5 ]
  21.                     keyPass = 0xff; //初始化按键1 a+ N$ D3 d) @; P
  22.                 }   
    # {2 F& g( [: U3 o: F/ d/ u
  23.                 break;
    9 _; \$ N! B) x+ P
  24.                     
    , \$ u/ q' d' r& z; c
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    9 m( {$ Y/ K% V  n
  26.                 {
    3 S$ B% J. n) w- Y
  27.                     keyState = 2;
    8 ]+ R5 b6 D  S" J" q
  28.                     keyflag = 1;//开始计数
    & T) g  ?: T+ ?+ L/ H  S# E
  29.                     if(KEYB_1==0){
    + X( I5 c1 z9 c, C) X
  30.                         keyPass = 1;//返回对应键值$ @* w; N3 P4 |) }
  31.                     }   ; P3 a% J1 {3 f/ }
  32.                     else if(KEYB_2==0)keyPass = 2;3 q( u! r; [8 B
  33.                     else if(KEYB_3==0)keyPass = 3;
    % b& l  ]! K) ~' a# u  N" E( M
  34.                     else if(KEYB_4==0)keyPass = 4;
    7 p  o* Z! K* y& m4 I0 {
  35.                 }     W/ @. A7 l5 g$ T5 g! K
  36.                 else keyState = 0;//返回检测按键      
    & T9 f3 o, S9 [# U- R
  37.                 9 K- `* n' H1 Q: A% i$ y1 _. S
  38.                 break;) {: ~' R% l! U5 w( y
  39.         case 2:
    . {1 U* X! I; G7 o1 O
  40.                 switch(keyPass) 8 `& `" r5 V* r5 m- }
  41.                 {              0 i' v' C( f9 X9 @. O
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键2 X) \8 D& ~7 X
  43.                             {7 K; w7 E8 _9 Z0 c4 w
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    # f; E7 J, C! o+ F
  45.                                 {! u0 {4 T& y+ x: R( P2 b
  46.                                     keyCount = 0;
    $ @" X* W0 h4 b9 \0 G; ?
  47.                                     keyflag = 0;! X$ s& n( O/ Z$ V
  48.                                     keyValue = ShoutKey1; 0 C/ d0 j9 U3 J- F7 b6 A& f# }, J3 ^6 \
  49.                                     keyState = 0;8 ^: n0 j- ^0 h" f9 p
  50.                                 }   
    4 k+ E' S( N/ d% c/ S
  51.                             }      
    ( c& f8 m, b" H" N5 }8 `$ R& b
  52.                             break;+ v/ L% ], _( F0 O
  53.                     case 2:if(KEYB_2!=0)
    2 Z+ U( {; N2 n' @3 q8 {* k! n
  54.                             {
    ' F: M! I) n& Y* ]8 k; y9 o5 B6 @% O
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    3 t& k$ N: E  X7 I/ \
  56.                                 {
    # v3 h& D) m$ c& o
  57.                                     keyCount = 0;
    & k. U5 |  _- o& E( z
  58.                                     keyflag = 0;
    0 E5 l9 f( v- U3 j7 S9 w2 j
  59.                                     keyValue = ShoutKey2;
      K; e. Y+ I( Z# a! @% j6 Z  L
  60.                                     keyState = 0;5 {1 o( {1 x/ Y' Y. w0 {
  61.                                 }   
    ) A$ F1 h4 [+ V/ V4 C- O
  62.                             }      
      B8 O8 {; M% B* r! `
  63.                             break;" q  L/ F& X9 y* @
  64.                     case 3:if(KEYB_3!=0)3 Q# o8 m% r6 Q! ~& k' W. B# A
  65.                             {
    7 T2 a3 I3 c! y
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按
    . F4 t  W; M4 J& ~" K
  67.                                 {
    2 ~6 R" {- S! @9 Q+ F2 G7 i
  68.                                     keyCount = 0;
    4 |1 s, ~) [8 _5 X4 s6 i* E
  69.                                     keyflag = 0;
    ) S: S" M6 N) H% s
  70.                                     keyValue = ShoutKey3;
    6 N' v5 ~( e* V% v+ B# O! D
  71.                                     keyState = 0;& R2 N9 {6 G! U, q4 J6 d  d1 n
  72.                                 }   
    " O! M" D4 t/ a. w8 ~
  73.                             }       9 ~1 ~" e* A! B6 Y! ~
  74.                             break;  s% j1 \7 p9 ?- W% R/ x
  75.                     case 4:if(KEYB_4!=0)- V1 A6 t; M( W9 q. P  @" I" N2 `
  76.                             {+ [; @- U* k8 ?9 j. o
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按/ Q9 P5 z, o9 p4 P. t7 @2 e) ^4 D
  78.                                 {
    3 `5 k# s& C3 f
  79.                                     keyCount = 0;
    ; ~3 a3 B. N1 Y% F: Y
  80.                                     keyflag = 0;
    6 i' R2 P$ e! B/ b
  81.                                     keyValue = ShoutKey4; 9 f4 n6 p9 @2 h% m! L
  82.                                     keyState = 0;) J+ Y5 ~% K& H3 F# `) u, M
  83.                                 }   
    - D2 a: z4 c+ H" K! T
  84.                             }5 C1 v& t+ s8 y! j( m$ P
  85.                             break;' ^, M2 w0 d9 ?1 P
  86.                 }
    0 I7 }! d0 t/ M
  87.                 if(keyCount > 800)//长按
    & _4 ]8 K' c: S
  88.                 {   - M" M& p  z2 u; |) L4 ]
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    3 O: B6 A. x( A4 S, l- i1 L) j$ {
  90.                     else if(KEYB_2==0)keyValue = LongKey2;& G! h! o- N. R) d- z7 I$ u
  91.                     else if(KEYB_3==0)keyValue = LongKey3;, O% ~: c  a) h
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    & ]% U& p$ u' [" m2 q: Q
  93. ) n1 e1 G  t) C0 c8 j4 u: k
  94.                     keyState = 3;- i1 s! W: o+ b) U: k, K/ F
  95.                 }$ U; b+ a0 D( k- B! p8 n4 y
  96.                 break;# H% d; G4 S& T' ^( h9 \6 n& _
  97. ; `5 {( b. G  A/ l+ w0 {
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)" W# r/ W! k% x5 ^9 I/ v# g
  99.                 {
    8 p2 ~( t: I  P* g
  100.                     keyCount = 0;) ?8 q0 v0 X/ l
  101.                     keyflag = 0;( U4 ~; \0 K0 b# w# |
  102.                     keyState = 0;
    ( y  Y- _+ {5 J8 Y
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  0 d* e& {; M$ C. I, y5 X
  104.                 }# D) [, M% }$ O  P
  105.                
    7 G' d# ?- x0 E3 h% X
  106.                 break;% l+ o% [* @# h
  107.     }6 g. m, l! O: h. E+ b
  108. }
    0 Y/ @0 R0 J  _5 Y$ l* h7 ^
复制代码
(2)key.h
" q# [3 z9 A; s5 e8 o
  1. #ifndef __KEY_H7 M  H8 r  b; v- y: \; N
  2. #define __KEY_H0 `- Z3 Q, Y3 P$ E9 [
  3. #include "stm32g4xx_hal.h"5 `8 O9 z; X4 c$ z/ O; W2 b4 m
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    7 W: W4 A! u$ s9 r, ^
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB19 ?0 F9 G2 t  P0 s8 z' V& G
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    ) M0 o* {; O" h; Z7 T" V# D% Q
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0% w9 |0 G7 q; {9 D! @0 r# ~) n
  8. #define ShoutKey1             15 k- i! L3 ]; w( l
  9. #define ShoutKey2                2
    & a( c/ {5 ~! o) @2 G
  10. #define ShoutKey3                3( |/ a4 p9 e3 b7 F7 Z
  11. #define ShoutKey4       4
    4 l3 ~! H: t' U6 \* k
  12. #define LongKey1             5. F2 e- I8 ~0 k
  13. #define LongKey2                6
    . m8 u; b2 t3 @: r% a. A
  14. #define LongKey3                7
    # _  [; [2 h; A4 K- q6 f3 K
  15. #define LongKey4        8
    ! K7 Q! G' @7 }$ |4 x3 x; @* G
  16. void Key_Scan(void);
    + W9 s+ j# q0 b8 x8 U# f
  17. #endif
    ) A* g" W. m& _! x3 R
复制代码
3. 计时操作" `0 u+ R( L  _: N
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。% T) N3 r. p3 r, w6 B: _4 v7 T" Q
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~2 [* f; i, i& x1 J8 @: X
  1. extern uint8_t keyflag;% r; j% e$ X* j1 ~) @. N
  2. unsigned int keyCount = 0;* \6 Z" L2 ~# \+ X7 }3 `& l9 g
  3. void SysTick_Handler(void)
    * C; _! z# I1 \- _- i
  4. {" ?0 Y6 j, Q# u) x) P
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    7 P2 {' r0 {- i6 Y
  6.         if(keyflag == 1) //若有按键按下就开始计时* Q* G0 G" t0 [5 b9 N7 ~) `
  7.                 keyCount++;        3 Y, u/ s' j/ N% t9 L: S0 Y# Z
  8. }) t4 R; d% h& y- V) m; X( u" {
复制代码
三、应用层简单逻辑实现8 O! o1 R7 v8 g/ m$ n6 p' l
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
" U7 k0 L" V1 B! w
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 * X) ]7 I0 o, M+ B
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器
    0 P& D" X" k0 L, Z
  3. while (1)
    8 b9 b, w. G) V; M, M1 }9 q0 ]+ C
  4. {
    / ]2 Q' W/ L$ {6 Q" b2 A
  5.                 Key_Scan();8 r& Z% X( y; ~. {8 P2 u* n1 X+ {9 @
  6.                 if(keyValue) //有按键按下
    8 g# U+ D# Q: O/ b* _6 Y
  7.                 {
    % g! Q! b: F. ]/ @! y( R
  8.                         if(keyValue < 5) //短按$ G8 t& C1 R$ p8 f1 w' ~
  9.                         {
    & B! z7 Y, [( k. Y
  10.                                 switch(keyValue)( t6 E; e' L( w. m0 m: e
  11.                                 {, J2 C4 M( C" ~9 A7 B
  12.                                         case 1:
    5 }' Z# I6 J  R# p" n
  13.                                                         keyValue = 0;+ W6 A) y/ n) E: R% I' y5 W
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);% n4 n, k. p2 I5 M  [' f
  15.                                                         HAL_Delay(100);
    / ~: v$ B6 n0 d9 U
  16.                                         break;
    / z" ?# d. d" k3 T7 U0 m. z
  17.                                         case 2:8 N# h* N: s( c+ }9 l0 P$ X
  18.                                                         keyValue = 0;
    $ g6 q5 }2 Q  [  @
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);/ W3 k( ?; I* q; m. \/ f6 E5 j
  20.                                                         HAL_Delay(100);2 M5 e0 r4 a2 e! B$ [
  21.                                         break;% h8 w! Y( T" H- X7 E# H# A
  22.                                         case 3:
    / P$ l6 M6 Y2 b- {2 [
  23.                                                         keyValue = 0;
    # p' T5 C  s6 I8 ]. C
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);% X, O$ W# d, |4 u/ E8 j1 q, }
  25.                                                         HAL_Delay(100);8 y4 u5 B. }1 O* v7 W2 n, j
  26.                                         break;$ F! L3 E6 ?' ?3 q% q  U" q4 e
  27.                                         case 4:
    ! W: ^$ O5 f. R7 c* H* {
  28.                                                         keyValue = 0;
    $ {6 `* Y$ P# }( o+ d: v3 C" x
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);2 z3 L, g) t$ d; C. F
  30.                                                         HAL_Delay(100);& _9 S. Q5 G. u$ T1 d1 f3 h8 B
  31.                                         break;
    . S) l* Z7 q. j; ~9 ^
  32.                                 }6 d5 I( H3 ^8 a; f
  33.                         }2 n  x3 x  x/ G8 D* e
  34.                         else
      ^, k6 F2 f1 M7 q
  35.                         {
    & V1 q' ^4 s! G4 l1 P0 n1 H, |/ o- Z
  36.                                 switch(keyValue)
    $ \7 ]. E/ a/ h
  37.                                 {
    " v5 x7 z: `7 D/ Z8 D+ H+ e* D
  38.                                         case 5:
    ; x! ?( i0 [5 V6 E
  39.                                                         keyValue = 0;1 S9 T( F/ I0 u& o' J
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
    ! T; c% N) l* T, |8 l
  41.                                                         HAL_Delay(100);: f4 n* H3 Q1 o/ l; N1 p
  42.                                         break;
    : l! k' M4 y4 I; F1 [# g
  43.                                         case 6:
    ' U1 C% `: r2 U, D
  44.                                                         keyValue = 0;  q# U1 d1 }; w7 t5 y8 n
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
      B, P. K- C7 o- ?# E0 L; G
  46.                                                         HAL_Delay(100);  _/ L9 J0 J% Y& D( r
  47.                                         break;9 r. q/ b$ {. x" e
  48.                                         case 7:
    6 K, c3 G2 f# g& i  W
  49.                                                         keyValue = 0;/ N5 d, m! C' L4 U3 v3 H
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    - `4 ?6 A1 R5 V  H7 o1 L# A
  51.                                                         HAL_Delay(100);2 H$ q2 E  O, C* a; S
  52.                                         break;
    7 A+ O8 f9 J( F! T) c! M& z
  53.                                         case 8:
    # |# N& B. p' |
  54.                                                         keyValue = 0;
    + U& H* w& e( n; @- C* W. \3 C
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    ) o4 `' l  t% z$ Y, {5 U: z( x
  56.                                                         HAL_Delay(100);
    9 N. B- V! b4 l
  57.                                         break;0 e* k3 z! J7 x7 D0 i$ j0 s
  58.                                 }
    " b6 }2 w- |: g( r2 w  Y/ g0 Z  k6 |( C( X1 l
  59.                         }( ^1 e4 O2 ~- e5 m8 Y
  60.                 }
    , g8 `/ K6 `+ s$ H
  61. }
    8 b" Y' T) e9 {1 {# d
复制代码
总结3 _4 f4 I7 a. D8 `3 d1 R% S/ z
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
, g, W& L9 ?  H8 B" R: z# V- R+ p4 j4 T* D; }1 q; j) n

# G. F0 \. [* _- N0 u2 g4 o* I. x, N% G1 D# F, {  }0 X  c
8 s; b* f4 B3 B
+ e3 w0 p- ^! M9 g3 Z" p
1 {( @5 @/ \. \

" j$ A2 N, p3 K% p+ B* ?( I
/ m2 E* Q3 b$ r7 V$ P$ n9 I
, P) S% S  {, B$ V7 y+ C; F$ Z; W
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~
/ |0 Y, r- Y/ I8 e  s" l

所属标签

相似技术帖

官网相关资源

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