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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
2 o! \* N' k5 a( N; h. o! t- |. M
3 H* B3 Q0 f' i) @' l" |" q前言# {4 B. z9 f7 `
我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。& \: n1 P" ?) G: w3 g, C5 A
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。7 P; d, P' l! |# |- \" E1 B
由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
% \" M% F  U0 Y& L% L: a- E
! ^: }& m7 K( L" P+ g& N' l
. C4 e% C- Q0 [; s- L3 ~
先放一张开发板的实物图,它长这样~
' K6 j4 n9 M' g
15.png
一、硬件操作+ U  F& u- {6 Z
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
0 {$ _& D) r3 w% p4 J9 v) g" z
* D4 k$ c1 j0 M4 b7 X
2 {, X# p4 G7 I1 n+ b+ I% U6 B
1. 原理图! ?# Z* t" k; G. O5 _
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。$ W, V) `/ d4 b- T
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)) W" C/ J: h6 U' P/ q& q  X- z
1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
5 T: p/ @: c/ o* s) k2.按键相关的IO口:PB0,PB1,PB2,PA0。; {$ K7 x/ O' L  i1 t1 W5 ?! H& u
  h7 o% P7 i  J1 Y; G/ ^

. z  s3 r3 `6 m. U( b' q2. 硬件分析
' }1 m3 B- Q$ w+ l9 b. j* o从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。
" S3 V" R( M% o  Q5 V2 U3 Y' V4 }" W, ?

8 e5 ^1 z- @# X% t2 Q8 V' }4 z2 E9 V3. 初始化代码
7 i; r. O  W1 q! _8 ?" d4 E
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */# z3 l0 C0 R6 y3 w
  2.   HAL_Init();//使用默认配置即可. t6 N. b" }2 Z$ g; d7 E+ K
  3.   /* Configure the system clock */4 P3 \0 q3 A: W- t, L! m7 v5 M  ~5 m
  4.   SystemClock_Config();
    1 K9 A" f$ }9 Z$ U4 e; |
  5.   /* Initialize all configured peripherals */# L. h9 ^  |9 O8 i0 x) l" T. i
  6.   MX_GPIO_Init();5 Q, |2 J! i- x/ z
复制代码
(1)时钟设置
5 R) \& y+ f, X, _1 n+ D这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。  A  D; m9 |4 k/ I: E% h
  1. void SystemClock_Config(void)
    . W6 V% i8 W6 D: S
  2. {5 v4 P1 v+ P7 V9 d
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};$ T5 b! I* @- X, n$ A, h
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    3 ~+ ?7 l9 d2 z  T% t5 X; r5 P

  5. " l& Q4 D3 M' E* g4 U' r
  6.   /** Configure the main internal regulator output voltage # A  X+ _& {# q' Z/ {! y7 Y% g9 N
  7.   */
    & T! H. D4 I5 _; S4 r& q
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);& b& X" [9 Z. C+ `% `% E
  9.   /** Initializes the CPU, AHB and APB busses clocks - p  A! c1 l' z1 h3 V
  10.   */0 ^+ s; t, ^: w/ n: ?/ m& v, {/ V' i
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;2 z0 m, }1 F, v) e( Y& E
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    1 _, b7 \. w! I
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;* a* U8 T2 h. l
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    7 K7 ?% N& ~, v& b6 y) Y
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    4 y  Q6 C* w5 E" o
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
    8 `6 R1 g* I$ A& _
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    , _. Q; ^! Q: V9 A' S# G, G$ p
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;  z! A" S  E. M
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;$ E0 v9 d( E, ]8 l5 F$ s# s, A
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;! U' e2 Z# |$ z4 O0 O
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    1 k# |5 E" [, X4 U* {6 v7 J8 T7 Y
  22.   {0 {! f& s: A( i" Y' P
  23.     Error_Handler();
    # }) S: [+ `- @& F1 h, D/ c
  24.   }
    4 y0 {6 ?: a* d# I+ d( D) T: ~
  25.   /** Initializes the CPU, AHB and APB busses clocks ; m, A, t, I: f
  26.   */& W+ y; X- p6 q) L$ `% H( r
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK- M+ K) _+ }# ?* x( T# f0 n- [
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    - G2 V+ H4 h  i9 F' f4 s# T
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    ! ]/ ?5 V+ g% M- A" A
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    . @+ _( A$ a1 O7 h* i+ L$ K5 P
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;$ g+ f; J: G# t1 M
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    6 L4 |5 B! h* g9 c

  33. 6 e2 A- r7 a+ d6 A$ W9 ]0 f
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)' `( [0 d4 W5 ^& u3 @' w( k
  35.   {- _+ [* K# `0 q  s; X% \, R
  36.     Error_Handler();
    ! e; t. m% [5 c; I; ]
  37.   }2 ]8 ?5 ^) i9 M) @- f9 U+ [! s
  38. }
    5 d  {+ T: A1 t; ^% b( O1 b  W; q
复制代码
(2)GPIO初始化  ~6 K' T- U$ v" J* g8 r4 ?
  1. static void MX_GPIO_Init(void)3 G- n: T  b, z$ I
  2. {
    2 Y# T- q. g3 o, y4 a  Q
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};( M! ^4 F- I1 g9 v0 @$ m0 J0 [

  4. / z' P" j: s3 c+ Y
  5.   /* GPIO Ports Clock Enable */. i( g. O2 h/ U+ v. y8 T
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
    & w. h8 F& y0 _/ Y
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();" M; f! s0 H: H
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();) R7 {1 |) r4 q
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();
    . o; f3 |* d* D8 T1 a( u9 S
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();( w* X1 J' f: J/ S  b5 M! G
  11. ' C+ C: D4 c# {. p- j8 @/ a/ H
  12.   /*Configure GPIO pin Output Level */
    - ^) ]3 V- D% Z
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 ' c+ C; Z/ L7 Q. j: i
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);
    + [5 D" v1 k3 @9 V- u
  15. " t1 u) h# ]4 N" Q$ _0 f. L' D
  16.   /*Configure GPIO pin Output Level */7 M9 |; ^5 [& H7 B
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);' b& Y2 r$ J2 ~2 {- Z; i  }3 ?
  18. ( r' m6 s$ Y$ o
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    5 Q8 P7 m5 b+ m8 \
  20.                            PC9 PC10 PC11 PC12 */. d+ |- G! _8 P) D# a% N
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 & E( y8 t# k" q
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;; j! F6 `) G. Q) B  U
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;0 B9 j) u/ i9 N$ B2 v  ]- \
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;5 O7 O5 w& H) `1 {) i' Q$ w
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    * |, x: F! k. v
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    ' p9 f2 I! V/ t& Y. H

  27. + R' v: n: `. D  U
  28.   /*Configure GPIO pin : PA0 */$ O3 v: H8 N* E
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;- T: m. S+ T1 T+ J
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    7 e' \3 b3 w- j  Q1 i2 {: w
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;6 a7 Q2 M1 R$ _( }& \% m
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);4 ~" P$ Z& c" S

  33. # |6 _' Q. Q% |
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */
    + n+ e! a; Z' X9 c  U! r1 d, I# D
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;  x% T5 y" M# r7 n3 F* k1 @6 W
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;3 K0 m, @- A, M9 }  P5 D
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    ' W) A, {0 K3 e: o" D% e, {
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    8 O3 U/ ^. G" O' @( H2 O+ f  E

  39. " _: E, c1 w. x4 ~) s
  40.   /*Configure GPIO pin : PD2 */0 z' J) e* S6 }- s8 h# b
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
      y7 p8 O4 F* W0 I$ O
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    : R/ o0 p. y) z1 ?# q$ _
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;% d$ l+ u1 J/ H! Z
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    9 G2 A: u# e1 I7 W6 y" t% i7 J
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);8 P8 z8 d$ A; z* `2 h& V

  46. 7 e7 a8 l. ^9 V+ _1 e
  47. }
    2 h7 l4 O$ f6 w5 Y" g- J" k9 m
复制代码
二、按键模块的驱动层实现$ H5 C( X  x1 _' [' k
1. 硬件框图
) K$ [; z1 J( p1 [1 B8 t在这里插入图片描述
! j/ G7 k1 f0 \& Z$ x/ \+ M 11.png
" s# g1 i8 E8 ?0 ^% j% C& {9 i9 G避坑点:
8 i" X+ E; ?3 X; M3 `% _短按:按键释放时判断时间: Q, `  v) I! V( [; ^( ?& f- a1 m
长按:直接判断时间1 |2 S5 q3 d) s, `" D0 m/ a

8 S$ b5 T/ Q7 b

2 W" E" T* `- n8 O/ t& p1 r2. 按键驱动层代码实现$ d/ j6 X& o# Q5 ]; @8 Y, Q
下面直接上C代码:, w) ^0 ^2 H* @6 M4 x) {& a
3 V/ C9 w- m& F

' }  ]9 `2 Y2 Z/ @1 e( W- N. v(1)key.c5 E" }) U8 h7 F; E0 D
  1. extern unsigned int keyCount;
    0 Q! C0 x5 t) h
  2. extern uint8_t keyValue;4 {4 C4 |/ i: R& I
  3. uint8_t keyflag = 0;% j5 @' `# e0 q4 X
  4. void Key_Scan(void)
      u( M7 b7 w# H- ]2 P+ n) e( Q
  5. {
    # J- ^# L/ k  i
  6. //keyState  按键状态;% H+ Y! C* z+ y+ b* \8 {  @
  7. //keyPass   记录哪一个按键被按下, D4 r! s$ M4 z0 Q1 U" y* t
  8. //keyCount  记录按键按下时间4 i# ?0 b/ y2 N. g8 j
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时- M- v- f6 `. R, q
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件8 L5 t8 @' J$ j( g7 t
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按1 J3 q3 G: O" G* a
  12. //ShoutKeyx 短按x键值,
    , p- e+ ^3 Y) h" z
  13. //LongKeyx        长按x键值9 {& I. ]' F2 i* ]/ m! E  z' {
  14.     static uint8_t keyState = 0,keyPass = 0;
    ; A% Q0 @5 H( W# ~6 p6 A$ s
  15.     switch(keyState)  O4 j, m* l8 l" K
  16.     {4 h. C' z" b1 {& q
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)- x9 F! g; O) b+ F! s: O$ d1 N
  18.                 {; U6 l6 ?9 k4 D" T* l- ]
  19.                     HAL_Delay(100);//消抖
    , v3 q( r) c4 R! j: N" Y0 ~
  20.                     keyState = 1;
    ) U- A4 A% {# R' x
  21.                     keyPass = 0xff; //初始化按键
    - f( T/ f- l' |/ ~- t, A- D
  22.                 }   
    ' P7 _' ~3 Z( V. s3 E
  23.                 break;
    2 d4 n5 |1 _1 ]0 X7 `' h% F9 e
  24.                     9 P% i1 B6 ], f" \/ u4 J1 Z$ g
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)& b' s8 \0 w3 t( \
  26.                 {" f5 e) P" m( ?' i( v5 W3 O
  27.                     keyState = 2;
    : ^: T! ^# v: L% j* c" L
  28.                     keyflag = 1;//开始计数
    + D0 k8 l& c9 s6 s
  29.                     if(KEYB_1==0){# p0 J# o( y6 y# }) {# x
  30.                         keyPass = 1;//返回对应键值* ]3 A1 w! i% _" b  S5 ~- H
  31.                     }   9 u% Y- Q* [  ^& {8 E3 P0 o
  32.                     else if(KEYB_2==0)keyPass = 2;$ Q/ }6 c- h; z5 ^
  33.                     else if(KEYB_3==0)keyPass = 3;/ m& P! M" q, u0 C) M- }# g! k4 P
  34.                     else if(KEYB_4==0)keyPass = 4;2 a) H* z: o) K
  35.                 }   ! w( y2 n9 F3 j" a0 }% a$ s4 L
  36.                 else keyState = 0;//返回检测按键      
    $ o2 _2 y9 N5 b& G" P" O7 K
  37.                 - V; u' l  Q" G! d+ }# K5 O) I8 ]
  38.                 break;0 B, l. o" @  j9 E; u8 L
  39.         case 2:
    ! @( F( ^; L, L9 s# N; M7 @
  40.                 switch(keyPass) / ^+ r  M8 s/ p! f$ @
  41.                 {              ' P/ a* V, ?; V  @2 v# _0 N5 ^$ I! s
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键
    2 r) U% u' ~2 w. k' Z& h
  43.                             {/ z& M" Y2 j9 ?: |  `
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    & {( P8 }6 Q: l, g2 ]4 k0 y
  45.                                 {
    ! O, w- z, n4 \2 Q
  46.                                     keyCount = 0;
    6 P! C! f$ U' V! u  V
  47.                                     keyflag = 0;
    % D6 O1 s; @# U$ z# `: a
  48.                                     keyValue = ShoutKey1; ) p9 k( ^! s6 o  e0 p
  49.                                     keyState = 0;" m1 w2 o  i0 D
  50.                                 }   2 {( P+ a( b/ w( {/ y
  51.                             }       + W/ U1 z; L0 H  K; Q5 X$ {: X) e2 K
  52.                             break;2 Q# |& ?: v' ]1 r; D
  53.                     case 2:if(KEYB_2!=0)
    0 B& Y  y/ |* @# V+ C" D
  54.                             {; J9 s4 V8 e/ F# e+ f/ H& Z
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    8 y5 @7 N$ f2 e4 _( C9 H4 r1 P
  56.                                 {" k7 t- f* Z2 W- O/ ]( S' M. a' c) i! D
  57.                                     keyCount = 0;5 z, |+ b' N6 }3 U. w1 B! U
  58.                                     keyflag = 0;
    ; z$ r( @. _1 f1 L3 n* S( ~! A
  59.                                     keyValue = ShoutKey2; $ N8 s7 E% y2 |, C
  60.                                     keyState = 0;% M# G1 M2 R( p6 A1 g3 d
  61.                                 }   
    5 P4 t" u/ k. D* F6 N& q# t
  62.                             }      
    ! s; j& p4 A. r) d) D+ V
  63.                             break;9 @2 y1 {& |2 t$ r
  64.                     case 3:if(KEYB_3!=0)3 W& f5 g5 I0 t% x; D( P$ ~
  65.                             {7 ^  B& `" A3 r
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按* L" W0 \* ~* h+ P; O
  67.                                 {
    - a- ?* C; e$ v/ s
  68.                                     keyCount = 0;& o4 a6 E3 {4 W$ l
  69.                                     keyflag = 0;8 C! c& C, n" M* P2 O1 x$ K
  70.                                     keyValue = ShoutKey3; 2 d3 @! ]' T  s' x7 `/ N
  71.                                     keyState = 0;4 ]6 C& @8 _( i9 o
  72.                                 }   
    0 T; L0 E$ v& h, N, \, J4 r& W
  73.                             }      
    - ^- e7 @$ d+ w0 g
  74.                             break;$ F- J; c2 e9 z6 y/ |7 j. Y* ~2 V( B
  75.                     case 4:if(KEYB_4!=0)- T* Q+ d: ?& z! S) @; c4 a( O6 o
  76.                             {! G+ u* e. V" O
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    # A" t7 P& M" f) L9 a
  78.                                 {, S8 l/ H* i% X4 w+ O" ?, z. `
  79.                                     keyCount = 0;; m7 S, K% e7 D5 G
  80.                                     keyflag = 0;
    * K- u& H6 D8 e5 Q! X6 a
  81.                                     keyValue = ShoutKey4; 0 y" L) G9 b0 K3 a* a6 \6 F% [+ e4 Y2 o
  82.                                     keyState = 0;0 A2 p9 E  x' l
  83.                                 }   
    0 t) Z! [7 m) L2 R) o7 l
  84.                             }9 f6 O3 F( z8 ]/ I
  85.                             break;
    % c3 ]$ C2 N6 K: g
  86.                 }! \3 c/ |6 Q  Y- A" Z9 h) B
  87.                 if(keyCount > 800)//长按+ \# m1 R3 e4 x! }( N6 u; _, A
  88.                 {   
    8 N' I- K) c* P) l3 m
  89.                     if(KEYB_1==0)keyValue = LongKey1; , M! i, t" ?9 l. o4 T
  90.                     else if(KEYB_2==0)keyValue = LongKey2;  a1 W8 G' L) O, j( d
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    % r& y. f+ b2 l- ^3 J
  92.                     else if(KEYB_4==0)keyValue = LongKey4;3 S& F2 ^3 k) k

  93. 2 [% q9 x+ \6 O: q& g# s* M
  94.                     keyState = 3;) Y; q" ]+ F5 d( n- e: d- ^
  95.                 }. @. Q/ m) y! P# ^! Y6 n
  96.                 break;
    , e" B: Z; r* z
  97. ( q6 T1 I4 k: V3 Y. [2 a
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)7 B( P" W( \; N; E
  99.                 {6 B) C' }8 S9 Z' V) m6 F
  100.                     keyCount = 0;
    ' e+ n5 E" ^& M8 b6 K9 `+ Q7 C% u& x
  101.                     keyflag = 0;
    9 Y. t6 s; }% r
  102.                     keyState = 0;# _* A& f. [8 D/ N3 v5 t1 a& o
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  $ M  O/ M5 i- M; M( |& Y2 I" R
  104.                 }5 u! M; h4 E' o% t* e2 ~* }$ G
  105.                
    3 f$ }$ N# B+ B
  106.                 break;. h% U, `$ r4 F0 S& U8 Q/ y
  107.     }$ P: m' l: m: U$ W5 c. O
  108. }/ ^9 i/ d2 ~6 d8 ]; c
复制代码
(2)key.h  y- b1 u7 D1 }
  1. #ifndef __KEY_H
    # b/ Z  k$ c7 H: a
  2. #define __KEY_H$ d$ i* [" y' }  W
  3. #include "stm32g4xx_hal.h"
    ( m, J: o. M; c6 Y
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0
    ' I# n4 c) X$ V4 n. ~
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB17 k% d: _& N- x, f2 m
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2  o3 h" p) ?  U! m& {! T. t4 i
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0: V! y' K; N" W5 K" T
  8. #define ShoutKey1             15 f# i7 ^' E2 Y2 p# [
  9. #define ShoutKey2                2# n  D; j( ^' a2 p- Z! R+ r' k6 D
  10. #define ShoutKey3                3
    5 J2 V6 D( [- r0 x+ u+ z
  11. #define ShoutKey4       4
    6 ~/ c4 J0 F' y1 [7 p3 D4 d9 m
  12. #define LongKey1             5$ `$ c0 {! l1 [8 k2 \+ k6 n+ e
  13. #define LongKey2                69 S7 V* ^" P& c% o, X, O. S$ r' `' q0 r6 K
  14. #define LongKey3                78 c4 D5 G- \0 m1 F, s% f5 {3 l
  15. #define LongKey4        8
    # G2 m  C3 y) Z) L: X5 p  {
  16. void Key_Scan(void);& Y% M% x4 H8 v# _, y: s# m1 h
  17. #endif
    " O5 [, R/ A  t, r7 J
复制代码
3. 计时操作  h1 l5 A: e; k  K% Q( [) n
我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。* t9 ?  `& F) I: S
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~
9 }2 }. s# ?6 T7 _5 t
  1. extern uint8_t keyflag;( r9 c+ {  z3 l% e+ M0 C! Z' B& ]- Q/ [
  2. unsigned int keyCount = 0;
    7 q* S$ w0 C2 r$ R
  3. void SysTick_Handler(void)
    % ]) K( s. u6 ?- J* p3 Z9 d1 q
  4. {
    % F* ~! T" A6 m
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)
    2 F/ R0 T! o# G- [
  6.         if(keyflag == 1) //若有按键按下就开始计时$ y5 I. |/ Y% a( n2 u9 d
  7.                 keyCount++;        " W' p) t6 l  z
  8. }9 S% }( y  z( ^% H
复制代码
三、应用层简单逻辑实现, B8 a* j1 C# h3 H1 T0 A
应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~
: m$ p6 c# O# Q8 O2 K5 n/ `1 v. ]- n
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 9 c( A9 _" L# @) ~& Q  {  P
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器- p, c1 p7 Z- }- Q
  3. while (1)
    , c1 H& r& O$ {3 H1 d3 R
  4. {  ]; w) ^8 n: o5 v8 I. `4 a
  5.                 Key_Scan();
    3 b, i2 O5 \- m1 W
  6.                 if(keyValue) //有按键按下
    " ?1 `- T" X4 A% Y+ A  y
  7.                 {, v) `! Y$ u% R$ T9 Z: |
  8.                         if(keyValue < 5) //短按% @. p2 f9 f4 ?& n1 I$ W) s5 x
  9.                         {
    ( O8 l9 [, r- y! q
  10.                                 switch(keyValue): V+ ]2 T. x/ ]. F# Z5 y" a) a
  11.                                 {
    1 l- x2 b" E+ l( N
  12.                                         case 1:
    : N$ |- z4 j! E/ K( H
  13.                                                         keyValue = 0;
    1 X9 _3 _6 Q3 q5 B( w
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);' u' g" e- r4 F! C0 k# d
  15.                                                         HAL_Delay(100);
    6 t/ g! F2 a, T
  16.                                         break;
    ! I4 K6 U" x* V( M6 _
  17.                                         case 2:3 ?$ w! S3 u7 N& Q/ W
  18.                                                         keyValue = 0;
    5 P6 B1 s" C- ?9 B8 \: y% T
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    2 ]& K% U5 B) ^: y- p4 T; y( J0 T/ P
  20.                                                         HAL_Delay(100);8 M% Y1 N, L. Z
  21.                                         break;/ M# P0 u+ b9 Q5 R
  22.                                         case 3:
    2 T) W" ]9 {0 D
  23.                                                         keyValue = 0;
    ; f# c/ P2 _$ h& P6 z
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    5 n8 ]- g  A: _7 R" D, z9 `4 R
  25.                                                         HAL_Delay(100);
    ( f# {4 q# Z3 q% @8 D" v8 f# i
  26.                                         break;+ L. S+ h0 P" n" m- B
  27.                                         case 4:; c6 C% T1 R8 p8 j  F
  28.                                                         keyValue = 0;; v  A4 B; I  H/ u
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);$ K4 R+ U0 ]; _; E7 K; N) S& i
  30.                                                         HAL_Delay(100);
    * T3 {3 }. M* g* U) |
  31.                                         break;$ N" c8 M" |" c+ }/ f
  32.                                 }
    9 l) L$ f8 E& ^
  33.                         }2 r7 e( @8 Y/ _! ]$ Y. ?4 ?. ~. `
  34.                         else
    ) K, T% |" q$ F2 Q' T& E+ h
  35.                         {
    7 L9 A8 U* @1 n* g$ I7 G! @
  36.                                 switch(keyValue)& w  A  x7 \; P9 T1 I9 T; u4 z
  37.                                 {
    * r+ x" T) K+ l4 N
  38.                                         case 5:
      t+ A' ~: r2 T5 M* a% @
  39.                                                         keyValue = 0;* l4 n, V* o- |( p
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);! v' s/ V5 ~( O0 ]
  41.                                                         HAL_Delay(100);
    $ G* S; ?% y8 o/ l* p' J6 z" H
  42.                                         break;  m6 x6 C8 m3 f2 C6 n, \
  43.                                         case 6:
    0 b- F: O- Z, o' z
  44.                                                         keyValue = 0;
    8 u/ h6 m- F8 \$ l) |3 H
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
    ( Q' y; k( v) _7 H
  46.                                                         HAL_Delay(100);
    % `2 L; ^# n4 c$ g) T
  47.                                         break;
    2 A# a. i& e! g8 {
  48.                                         case 7:
      u( G$ d+ a. F2 N' n' O
  49.                                                         keyValue = 0;" j( F9 ]% Y" _7 A! G/ [
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);, m, [, b( y# M: h
  51.                                                         HAL_Delay(100);" H$ w+ Z  b; S/ m3 {
  52.                                         break;
    / v, M; M5 [6 S6 }; m, V0 H
  53.                                         case 8:8 C' o4 w+ E& z% a* {
  54.                                                         keyValue = 0;
    . y2 e% v6 y/ I6 L; ]; D
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);0 Y# y* F6 t9 ]. t7 X
  56.                                                         HAL_Delay(100);0 M6 `' K' V3 q& N# ]
  57.                                         break;% `3 z' \& a) Z; O! T2 F
  58.                                 }" W6 \; B2 N. p* G) A8 M
  59.                         }* b' x7 {$ ~, b; R9 ~3 }3 E0 X6 a
  60.                 }
    6 Q9 w' i3 T' w# Z
  61. }. c. k. w* P5 T! z8 x* k$ J
复制代码
总结# O7 r3 v( I9 ^  Z3 _
以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。- J8 s& e' W- g- B& w5 X" ?0 `+ E
+ R4 k2 g7 o: u5 ?* ^6 M
7 x9 {! N2 V$ V9 d! H

5 S# h% m' U5 X* z7 z( g

# c6 F5 |/ i6 [7 q; V+ L, R0 v- j( w
4 {4 s. f& E7 u/ X% x( |; j) {* g$ D

  L! `1 }! q( Y; A. n

3 h7 o7 k. d5 @* U8 m0 b/ r( O9 E7 g; @% C0 W# ?' Y2 x* g6 J
收藏 评论1 发布时间:2021-6-18 16:44

举报

1个回答
landeng 回答时间:2021-6-19 11:09:17
学习了~~9 q+ e. Q6 j' R1 r

所属标签

相似分享

官网相关资源

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