请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
5 t$ }8 Y. }2 t. I8 D  ^1 z$ p
4 ]7 _4 |; y7 F前言
( @8 H; b5 W: d+ P我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。
* k/ o! c& h. Y/ g! M2 |注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。3 R% ^5 [0 n7 p* J
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
0 ~9 O6 f5 ]" y+ K/ ~" r4 w
  e5 o8 z3 j9 q7 @" \* L

& H/ w9 c- w; I' E1 V先放一张开发板的实物图,它长这样~, X0 r: w* U* H* B
15.png
一、硬件操作- k' z+ ]3 y2 Y" a0 {: |9 Z4 W
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
/ v6 Z7 R) c9 s: @
! i1 d; h4 N$ y% Q8 C

" k3 t8 A+ L: |1. 原理图
" {+ J# d$ S, Q9 P8 W
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。5 Z9 Y) n. ?$ `$ ]
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
3 X  v: i1 B' F1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
' L- h5 r5 i) Y$ F  z2.按键相关的IO口:PB0,PB1,PB2,PA0。
) L, [4 T3 ~/ j3 i* @( P4 _3 K5 J# }5 i, E

, \5 X, y9 b; s1 J$ U2. 硬件分析
) o: A% y/ j1 T" @2 k1 H- c0 w* ^& k从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
) F  L' X( N4 C$ _3 k2 Z: o& L* m/ ~9 J9 {* e
! c* z8 z* g2 [- i' j
3. 初始化代码# e; T2 u. h2 [
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */# O( t* L7 D" D
  2.   HAL_Init();//使用默认配置即可/ L  w5 I& }7 s& `" v! h2 ?
  3.   /* Configure the system clock */+ h" L& e/ l/ a# {, j
  4.   SystemClock_Config();% z( L( P% p0 B/ b  V3 P1 Z4 H0 p. K) I
  5.   /* Initialize all configured peripherals */8 U/ P" ]& h4 T3 m3 E& x% a
  6.   MX_GPIO_Init();
    ' j, x  P9 ]$ Q/ j$ B
复制代码
(1)时钟设置" j# M% M7 e. c6 t% r
这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
1 x- x" O# Q+ v: x% g
  1. void SystemClock_Config(void)& {; D3 D% U) Z' `$ |* x9 t8 Z  O
  2. {
    : }; X) \; i1 y+ b
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    ' L+ H* X  @9 e  ^( v' C. T
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    + L4 i  ?: C$ ?2 Z2 ?

  5. % O/ k. T( \% y* W6 C
  6.   /** Configure the main internal regulator output voltage 5 O- @1 y! _* D/ _. A  m5 |7 T( |0 p
  7.   */
    / {; K' o: i# n& x1 N& |
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);0 O, x! z( b; S; J
  9.   /** Initializes the CPU, AHB and APB busses clocks - Q+ @3 U) K. R9 D( X
  10.   */
    + N' G6 X# M2 f) f
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    $ T; b" T  ?6 B' |
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;9 s. L3 I+ F4 y  \
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    - Q# p7 v1 c1 T. g
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    - r* e( K. Y+ ?% v  C4 b  H
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    ; q; t6 \8 D0 Y; i" _  V2 ?# j6 [5 l% X
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;7 r5 t+ d! X' M* H# |
  17.   RCC_OscInitStruct.PLL.PLLN = 20;* p8 e! D( b: S: G
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;; h2 V! U  ~; z1 l: f: A* l$ Z( ?
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    & r% G  i$ A4 v; d& o+ @9 S' g4 C
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;1 p6 N4 O2 M% j( \6 B' A- ~
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)7 B+ G% `  M7 B! Y# g5 G
  22.   {
    + M0 a: P1 H! ~/ J
  23.     Error_Handler();+ A6 v" m  |+ f5 J& w/ O* m1 q
  24.   }
    1 x- j  K3 f/ }4 U. ~9 i, Z& ?) N
  25.   /** Initializes the CPU, AHB and APB busses clocks * _- U2 s# a* l; {! g" Q8 X2 K, U
  26.   */
    + d* l% m2 m* [1 d
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK1 l' I" v1 X0 `" p: z# m
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;( @6 g2 l* {+ X4 t. }% s
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;. b$ t( o( d# v& ]! }+ g
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;. e  y- r7 @; E8 I' I! R- i
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    : I+ [1 L9 H7 B
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    6 L  n' e7 t9 @' k

  33. ; }  ]& p2 r1 {) ~# j, t$ i
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)3 d1 Q# f% S! ~9 k6 F2 ?7 e
  35.   {
    0 i- _2 a6 a7 Y& F
  36.     Error_Handler();1 H" ]$ {% V! ?) i7 q, W
  37.   }8 d" @" e# ?4 S1 M5 U' P: m/ X: p
  38. }' j6 ?, _2 }8 x. S9 E9 J
复制代码
(2)GPIO初始化
* e5 E1 H4 q$ }3 a
  1. static void MX_GPIO_Init(void)
    , I8 y, {* L0 W6 L. m. V3 C
  2. {6 y/ f3 J4 T) f6 T: D; |
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    : l) r% M2 e7 F: d2 z
  4. * S7 j$ v6 d# Y9 G+ \
  5.   /* GPIO Ports Clock Enable */
    ) {: D' H. J) ?4 N7 [$ y1 D0 S
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();# c  {+ S0 ^7 ?# S# o) r2 u
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();1 G5 c7 l( z3 Q, v/ r
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    ; A) e- N' l9 L3 T) M( g4 Z0 l" h" J
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
      m- r7 \* u8 p6 A4 ]7 t9 P5 d
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();
    1 h& b4 A: N3 x

  11. ( P1 ^, n3 z( B) n: W
  12.   /*Configure GPIO pin Output Level */; w% D" F! X: C0 T9 C- @" ]
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    3 T. l7 q+ \+ l' A, `9 H( b, L
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);% t& K" ~: w5 d% @# }

  15. + K7 ^, v7 Q$ y9 |- z' t
  16.   /*Configure GPIO pin Output Level */
    + \- `4 x2 w9 f) c8 c
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    / X/ c6 {" M; v/ Y$ w. q! R3 u1 R$ ]
  18. ) P2 s/ `0 W8 ^- W
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    ) S2 B8 v. \: W* p
  20.                            PC9 PC10 PC11 PC12 */
    9 i8 q, h. x& o4 \3 f" N
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 4 Y6 R* e0 `) p; j
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;0 t+ v: x6 m7 Y, F% U1 `" @
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;8 W+ r6 H$ A7 M/ J: ]
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;" J: l) U( y8 ?# x% e/ T! U" {! W
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;; J/ W" {/ a0 L$ }( g, t1 a" ]
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    0 l$ I, D- h2 l$ X, Y7 c6 B

  27. ; W8 s5 T% I% Q9 u
  28.   /*Configure GPIO pin : PA0 */
    6 A6 ^% b5 a! _" ?5 b
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;# U  Z, c1 B( k2 E, o3 y
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    ! B  C, H; w* q. f
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    3 ^* i& j6 g) N' U( s8 G2 ^9 d
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);( j# r' [8 x6 S: j5 M+ ?5 G' i

  33. . g; d0 b; P, X% E, \
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */' l2 R1 ~* @0 K( [( Y9 [
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;5 k$ A( L$ o/ [4 L' F; A
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;: @$ Q5 z; C5 u* d& H1 `
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;8 o9 K3 p  Q3 Y
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);* I2 d4 e' ^6 T6 z
  39. 2 w: G1 ?: R! V( q
  40.   /*Configure GPIO pin : PD2 *// i, y2 W! n4 a4 ~1 t) B
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    - f  u" _5 o. r+ f  _
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    7 o( C! l+ ?+ u! X4 y
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;( {/ ]- G( G  b& I/ X) X* a
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ( ~! j% O* `4 F/ {! u
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);! |1 y. e- T8 e2 b
  46. ; F8 s$ W2 w  k
  47. }2 v, `+ ^1 M8 V+ i* l& P2 ?- G$ D
复制代码
二、按键模块的驱动层实现  }  S; c4 J; z: H. Z, J
1. 硬件框图
( U6 P! @. n4 U  q4 g在这里插入图片描述
/ B& X; e# M' [( f/ d- q 11.png / s6 u' y3 S( y" ~3 _( _
避坑点:
- r* f6 v3 k  U! Y短按:按键释放时判断时间
: r' D' W# P/ B. R长按:直接判断时间1 j# J0 B3 t% U4 s* ]
/ r: x1 e# k: s  l4 M' c# U6 K" c
  j; }; ?# o0 b4 J
2. 按键驱动层代码实现
( i  l  F7 a3 w: Y0 G4 P$ l, Q下面直接上C代码:
8 k% p# K& J# a  M, r7 h2 n
$ Q  J& E/ l+ K
- ]3 ?% F' H7 ?3 _3 B* a
(1)key.c  u# o- F% }! V6 W# @3 j
  1. extern unsigned int keyCount;9 a) w. Z0 K$ t& {6 `8 X# o
  2. extern uint8_t keyValue;; [& H5 S) ^8 N9 Y2 ^  `
  3. uint8_t keyflag = 0;
    3 I) x9 M4 X* U* `( ]0 c) G
  4. void Key_Scan(void)
    $ K! G) J) ]* J( T5 A
  5. {3 J9 S4 u6 x! |# l. }- Y
  6. //keyState  按键状态;
    : K. P* `# `! g: r5 ?' L. B. O
  7. //keyPass   记录哪一个按键被按下; a" ^6 z: w2 u3 X% n
  8. //keyCount  记录按键按下时间
    8 M4 y  c$ B2 J
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时# z* w2 w+ T4 x0 M& d7 H
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件' ~. @! P1 A! J' Q
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按; l* M/ e8 k$ k7 r+ N
  12. //ShoutKeyx 短按x键值,
    2 i- @( [& g- _2 X: T' ?2 P) v
  13. //LongKeyx        长按x键值' z+ W2 F4 ]( Z$ p' ]9 r1 h- E  W
  14.     static uint8_t keyState = 0,keyPass = 0;
    1 O$ U8 v4 [! U
  15.     switch(keyState)
    2 U# I- e9 C/ g' ~/ l
  16.     {
    3 X, l* J1 M( m2 n1 i* M+ G
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)
    ' {  r: G( Y5 k
  18.                 {% v" J- {0 n& o( {% O: N
  19.                     HAL_Delay(100);//消抖
    1 G! p( x$ g& Y# V, l2 {- {5 H
  20.                     keyState = 1;1 x+ f# u% X' l
  21.                     keyPass = 0xff; //初始化按键1 c/ o8 }! w; X; p- f
  22.                 }   ' z( P6 p3 O) J2 z2 e8 Y
  23.                 break;
    ( s) d" A; J- P# }* _  E
  24.                     5 d1 C. D" f8 p8 Y1 [8 O( _
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)" d/ X: l8 ?! W! Y9 C9 l: \7 S
  26.                 {
    ' d' Y4 b! x, |# m
  27.                     keyState = 2;
    3 r2 n+ w6 D  M9 `
  28.                     keyflag = 1;//开始计数
    , X  s: O! Y+ V: n- ^  Z& N9 Z, N
  29.                     if(KEYB_1==0){
    % F- L+ O3 ?3 o% e  U2 _
  30.                         keyPass = 1;//返回对应键值
    ; t6 q) S. `3 T+ v0 w. |& j
  31.                     }   ( H/ E5 C4 [5 b/ ~) u; o8 }9 k& M# `
  32.                     else if(KEYB_2==0)keyPass = 2;& E: Z1 A6 b4 m( N
  33.                     else if(KEYB_3==0)keyPass = 3;
    9 V% d) t% l) m6 o. t9 Y
  34.                     else if(KEYB_4==0)keyPass = 4;% E9 v/ J' U6 p) K2 x+ n* R
  35.                 }   : ~) Y9 p4 t. n
  36.                 else keyState = 0;//返回检测按键      $ W0 H& ]5 `+ E6 _/ z
  37.                 . j, o7 }0 n7 ?) r" t8 F7 K( u% ~* j
  38.                 break;- D) a! p: h# V4 x
  39.         case 2:
    8 H! `  V( `$ w: V" G% B5 Z& D
  40.                 switch(keyPass)
    - ?3 f. r* @; X' \& N
  41.                 {              9 N% |3 e/ g/ X
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    5 c3 Z$ i5 z$ s, w, p0 t: v4 w5 i
  43.                             {
    - ^. X( o  H1 F' N! ^
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按; _3 B7 _) ^9 |, ]* ?' f6 R) R
  45.                                 {
    ! H6 z+ W& {# b9 m
  46.                                     keyCount = 0;
    - H% ?) U0 r0 r4 V$ F0 Q
  47.                                     keyflag = 0;, F$ j+ N& a/ I: }/ j
  48.                                     keyValue = ShoutKey1;
    : M1 N4 w( q" M: X
  49.                                     keyState = 0;% a. l$ u- |3 Y5 {4 n0 X
  50.                                 }   7 |% C% R( x7 B" R6 H
  51.                             }       ; M/ s' ~: `; m" ~7 x( s
  52.                             break;
    7 @+ s- c& [6 H& \% |0 X. |0 B. `
  53.                     case 2:if(KEYB_2!=0)
      v" |. r* \# u  ~" k
  54.                             {, X8 @1 G5 @2 P; J+ T  W/ {7 R! x2 F
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按5 y" v8 b, `$ r8 h
  56.                                 {
    8 G8 J, G9 u+ Z4 S  \; x1 G# ~
  57.                                     keyCount = 0;! e) X) Q! n0 `, ]% b
  58.                                     keyflag = 0;
    5 O3 w7 T) V' b% e+ ^
  59.                                     keyValue = ShoutKey2; * R- w( ]2 w1 v- k) l  Y8 X
  60.                                     keyState = 0;( w7 l, F: M( p: O! p) D
  61.                                 }   
    / V5 t1 Y9 F0 O- v
  62.                             }       # Z. H) \& F9 P1 N
  63.                             break;+ N0 L! K- ~+ r/ i) L9 R
  64.                     case 3:if(KEYB_3!=0)3 M4 m6 F* T+ Z. }& `
  65.                             {
    * J% }4 e0 h/ W: M* @% c
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按$ a1 F3 ], A, w; C
  67.                                 {
    ! L  Q) b6 b8 r: h/ j2 q7 G7 {
  68.                                     keyCount = 0;& q6 [' Y* J+ @' r; C, }. I% w
  69.                                     keyflag = 0;
    4 c6 i6 {/ l, C' z
  70.                                     keyValue = ShoutKey3;
    , y" N+ o  W5 j6 I$ Q. R, v
  71.                                     keyState = 0;
    ! r3 A, S# n- r8 {6 s
  72.                                 }   
    7 Q* U( v1 U; H' W  f7 k2 m
  73.                             }       - w; D3 \# [* a" k
  74.                             break;* `2 a0 j* |) d6 H% ~
  75.                     case 4:if(KEYB_4!=0)
    % U. Z  N+ l8 |% \7 x- ^- b
  76.                             {/ \+ W2 R7 H8 a; M/ a  h- L3 U4 e  H
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按: }) w2 ^' n) M: O
  78.                                 {: X0 ]7 K9 q! n" D' V# ]
  79.                                     keyCount = 0;8 I* R& _0 b- F5 \
  80.                                     keyflag = 0;5 d' ~1 h/ x! T0 {) P. y4 c1 k
  81.                                     keyValue = ShoutKey4;
    ' q% M3 @" E6 d( u/ Z% g
  82.                                     keyState = 0;. z% F9 F1 k9 g1 @+ ^
  83.                                 }   # u7 n4 V: B% r$ O0 t
  84.                             }( c1 I& U' X) d2 m
  85.                             break;
    6 `( c/ w2 L- ^* d- ?1 s
  86.                 }, d7 x" f: f% F9 G$ W  u
  87.                 if(keyCount > 800)//长按
    & c( C4 d2 `# N# J/ y. O8 ]$ k
  88.                 {   0 V/ j. z% ]7 W: l' g0 b. ]! w
  89.                     if(KEYB_1==0)keyValue = LongKey1; " ]& g! @; d3 r3 Z9 K
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    ( L1 \3 Y0 i/ p" T& S/ H$ R2 Z
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    9 x5 o  M- C, @+ l
  92.                     else if(KEYB_4==0)keyValue = LongKey4;2 m1 h. M( o2 A2 `

  93. + `- X" Q6 u9 o9 B" X0 Z
  94.                     keyState = 3;$ \4 t5 E: @, E* \
  95.                 }6 b' Y) F; T7 l0 m
  96.                 break;& a1 f) `& B: l3 q0 [. w' y! |) o
  97. 8 g4 S* S7 g+ Z. |2 K; p5 U
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)' v% `% }1 _/ K5 G! C$ s  u$ J: C/ \
  99.                 {7 f( Y" S8 T9 K% `
  100.                     keyCount = 0;
    1 d+ S( g, |; `: i: u
  101.                     keyflag = 0;1 Q; Q0 b, M; X
  102.                     keyState = 0;
    2 C0 Q% D/ i# T- n3 ~
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    8 o6 T2 F5 o; Y' @9 M/ U4 m, Y
  104.                 }
    ! ~+ q2 R/ U* }6 C1 n
  105.                
    6 K0 _  n; K  o9 ?( O% S8 }3 l7 p& G
  106.                 break;
    : |% q7 f5 O  h8 Y3 R1 o
  107.     }" J! ^) c' z! r* m3 G  T# r
  108. }
    2 G' G, c1 S& i* A) v
复制代码
(2)key.h& {) G' Y9 V- ]5 y8 l
  1. #ifndef __KEY_H
    # l( u) F! Q) w5 v: F
  2. #define __KEY_H, R& R9 O4 M% w1 C  ?9 D# a" q
  3. #include "stm32g4xx_hal.h"  ^4 w8 \, H: _2 P$ k/ S
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    ( ?/ a/ B2 ?: g! O' M& v
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB13 b* I6 V. A/ u0 X0 I
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2. G* B! K( R. C
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0' Z* p! ^/ D0 R
  8. #define ShoutKey1             19 J! `; z& H: s( ?0 q; Z
  9. #define ShoutKey2                2
    4 K! x6 U( A1 t( z
  10. #define ShoutKey3                3! {2 T) m" I3 n$ l  P
  11. #define ShoutKey4       4
    $ n& Q8 j' Q# |) I6 W" W
  12. #define LongKey1             5
    ' }& s" F9 f" I; ~; |
  13. #define LongKey2                6
    $ v- V/ {+ X- I5 u& a0 `- G
  14. #define LongKey3                7
    1 a3 z2 q+ B' H; d# l
  15. #define LongKey4        8
    . @" J8 F- X3 Z6 E
  16. void Key_Scan(void);; c( U; J  E- u; L7 _2 {
  17. #endif
    + I) O6 f5 A0 B9 M+ @+ Q/ p
复制代码
3. 计时操作
" I2 n( `- w% j" N我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。( S9 [5 C# K/ S- n6 J
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~1 Z5 M4 t4 x( v
  1. extern uint8_t keyflag;
    * L! D: o9 g9 E0 {. L' U
  2. unsigned int keyCount = 0;# ?1 y0 i0 h: y8 `: w
  3. void SysTick_Handler(void)6 ]( a* ]7 T& A- A7 K6 s
  4. {
    $ }' B6 d0 H9 r7 I
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay). x. {# y: V7 L: L: O
  6.         if(keyflag == 1) //若有按键按下就开始计时
    $ s. J+ b7 U1 T; e
  7.                 keyCount++;       
    6 a+ p4 ?7 o; x; A0 [
  8. }
    3 X' ]2 C4 M% U$ [: @9 k/ @
复制代码
三、应用层简单逻辑实现
8 e* m8 V& Q, o6 r应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~0 |+ D7 Z6 _9 G/ F$ R! m
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯
    6 X- ]+ Z7 v$ I+ ]: A! p
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器) K" Q5 D1 e2 I
  3. while (1)( @6 j/ L8 x* H& @
  4. {
    6 T# k: }% x5 H& Q4 K) R, K6 R# Q2 D
  5.                 Key_Scan();
    4 ?" a# v1 H( P9 C
  6.                 if(keyValue) //有按键按下- ?: G" E" t$ K9 o1 d% s
  7.                 {
    $ l0 \. [' l( \& u& r) {
  8.                         if(keyValue < 5) //短按# k- ^! b, K% N
  9.                         {
    " |  G+ u' j2 d( ]4 |: }
  10.                                 switch(keyValue)
    $ m7 |( E) t* {% }) K
  11.                                 {) ^  n( d7 d) k6 g
  12.                                         case 1:- x+ B9 Y2 Q6 e- X
  13.                                                         keyValue = 0;" u, Y* @/ N1 n+ B" ~- L
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);0 |8 T  M8 C" \' u. E2 S
  15.                                                         HAL_Delay(100);5 Z. n9 T. y& A6 G1 G" y
  16.                                         break;! y' h+ Y3 b' \& d( j
  17.                                         case 2:/ D/ g* N$ V4 n* R
  18.                                                         keyValue = 0;" T" _* W3 A9 S8 F' s9 X5 j
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);5 J. h/ S+ Z( y) Q. R
  20.                                                         HAL_Delay(100);
    + h1 r$ [7 _4 @' Y4 I$ T4 Y! A4 E
  21.                                         break;" ?# f7 l& W4 g, `5 G" D& z8 E) _' X
  22.                                         case 3:, g' s% j9 J9 E$ w# v- C
  23.                                                         keyValue = 0;
    + W  q  H0 U6 m9 y- w( R
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    ' m3 n1 y. L4 n2 ^, U/ K3 R! h9 x8 ?
  25.                                                         HAL_Delay(100);
    & D( y& Q; v" K$ f8 X1 q1 Y0 T
  26.                                         break;
    - O2 O$ f. W' y6 _; G2 f
  27.                                         case 4:& R, |5 L. l( `/ d4 Z5 M8 q+ S
  28.                                                         keyValue = 0;
    # X9 k/ t5 o: q, V1 a) R) u
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    - ]9 l0 z# E, Y/ P$ _) e9 Y; F1 i
  30.                                                         HAL_Delay(100);
    9 u  ]' Q' a* T) w2 h& K
  31.                                         break;
    6 X  v7 D& x! ]! H% H
  32.                                 }* S/ i( E: \# ~: ]- Y: f
  33.                         }
    3 g/ D, f# f+ ~" ], {$ d
  34.                         else0 b+ x. `" m! l1 T# W
  35.                         {
    - p' a0 T4 ?% {* f; Z0 s
  36.                                 switch(keyValue)
    9 r2 I& u6 i4 ?" a
  37.                                 {4 Y$ V5 p! O0 ~8 p5 {  N" X* U& j0 e4 ^
  38.                                         case 5:
    1 n( V- A- [; A; x
  39.                                                         keyValue = 0;
    6 C+ u4 g. s2 [* U0 j  {0 H
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);. U9 r7 a6 J7 K6 K
  41.                                                         HAL_Delay(100);1 F; k; P% n- r, l) l
  42.                                         break;
    ) S6 W* N& ]7 f, A6 z; _( X$ ]
  43.                                         case 6:
    / T7 ~8 L/ R4 }
  44.                                                         keyValue = 0;5 L# K: F1 |. B
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    + X. i4 X+ m7 F# Z
  46.                                                         HAL_Delay(100);5 Q) `; `9 j8 \4 y" j5 a
  47.                                         break;
    # m4 M. i4 T+ a7 R1 n
  48.                                         case 7:- K# t. i/ R9 s# T; `
  49.                                                         keyValue = 0;1 O* B, B& ^8 G- j
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);* t; k" N" l! k
  51.                                                         HAL_Delay(100);7 Y0 M+ _! ~) Y
  52.                                         break;
    6 X. f6 k. Q5 ~
  53.                                         case 8:
    $ ?4 o9 t* G! G! a6 W4 w
  54.                                                         keyValue = 0;
    / Y- M" S$ B) R/ j
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);# R) z- l; E, K& N; e. L+ m
  56.                                                         HAL_Delay(100);* [# k  P! y: |2 ?
  57.                                         break;6 A  W) }. B7 f  j1 C. h
  58.                                 }
      b( n& G, T% K) D# r5 r" t+ V: P
  59.                         }
    0 e1 ~% \+ y8 k6 j  {/ M
  60.                 }
    / I, Y8 r" Q1 B7 g7 a; L& y
  61. }( V" Q7 J/ b  @. F. T" c. h
复制代码
总结! {# R& e( _9 {4 _; p
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。
' [( [7 f0 M$ V* M
! j6 G# h3 }& j, l/ S2 T

' t4 N( L% x. Q* X
7 N! d( v  v; S( s/ M/ D; c

* [% N* X8 K, x4 s/ e9 W! l5 j5 J& a5 f, n

. \" y- ]) b  S: S& B% z# s2 s' s/ K. ], s8 Z

4 g5 F0 s2 Z9 m  v
, K" b9 e# n9 {6 g8 T
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~* S0 J: @7 R! W; F" v; G
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版