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

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

[复制链接]
STMCU-管管 发布时间:2021-6-18 16:44
STM32G4系列MCU学习笔记:按键模块
* p; ]. c0 O8 J/ j% C; x
" i( {7 E6 e" V前言
8 Y2 R1 V+ c' N" Y# S! A我所学过的按键模块有独立按键和矩阵键盘两种,其实两者原理类似,本文主要介绍按键模块中实现长按和短按功能。( H, Y- _* p+ E  V6 Y: l
注意了:本文是基于HAL库来进行介绍的,如果你想用标准库实现也比较简单,类比移植即可。
% Q6 Z. {7 W3 G0 W% M1 U; @: F由于作者第一次写博客,且自身水平有限,如文中有误,还请大家指正,谢谢~
5 t1 D* m. F$ M) R$ j" Y& x: D
# |+ B. s* o) `% M
6 L8 [( y% Z% b- o* {
先放一张开发板的实物图,它长这样~7 n" V) q  }+ m2 M4 w& I! |, B; Y
15.png
一、硬件操作5 X" `' l  w: ?, i( W
在应用层中我利用不同的点灯程序来区分短按和长按所进行的操作。所以先来看看该模块所设计到的硬件原理图。
" \& W( ^9 b2 u* j/ z0 B. y5 Q" Z' u: x; s& Z5 W( o
: m/ D1 C) D4 U7 w
1. 原理图+ i& J8 V' j6 a( R
14.png
注意了:点灯的这个模块,我们这里忽略这个锁存器芯片,不用它的锁存功能,着重于分析按键模块。
" N( S; Z' h- v6 G4 B
13.png
我们先把所使用到的所有GPIO口列出来:(方便待会儿看程序更加清楚)
8 l5 n$ c% i! P* u% D1.点灯相关的IO口:PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15;
% D% U% }+ \2 t( p2.按键相关的IO口:PB0,PB1,PB2,PA0。
" O  l2 l% K- Z
; _: k, z& J1 o% n! I# A

$ A  g! V# e$ K2. 硬件分析9 w  h7 l5 [9 Y4 M6 A
从原理图里可以发现,我们如果将PB1设置为输入模式,去采集该GPIO上的电平状态,按键松开时,PB1上的电平应该为高电平,当我们按下按键后,例如:B2按键,PB1上的电平就会被拉低,其余按键类似,所以根据这样一个简单原理,即可实现按键的输入检测。7 M, `& A+ x5 I0 @# x
% T8 A) D, Z" w; s6 n
9 q- q6 t7 n8 Y( l
3. 初始化代码
% X4 K9 U  O0 a4 @. z$ T
  1. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    2 m- X4 U5 T$ V0 T( a. a- |& v
  2.   HAL_Init();//使用默认配置即可1 _( v2 D, p. I0 o
  3.   /* Configure the system clock */
    : h& R- a7 |0 a' O9 p) j, ~
  4.   SystemClock_Config();
    / w9 K2 G" X9 w: e- @" \8 ]
  5.   /* Initialize all configured peripherals */, M, u, C5 \5 G& d) B( _( J
  6.   MX_GPIO_Init();
      Y2 }* \0 `- N& A3 ~8 ~
复制代码
(1)时钟设置
0 _& O& L/ [  j7 r* l这里我使用的内部时钟源HSI = 16MHz;配置HCLK = PCLK1 = PCLK2 = 80MHz。
" I) c/ U9 Z  r$ V
  1. void SystemClock_Config(void)3 [" @  G& S; u7 G$ ^
  2. {
    / H( |) d9 g0 U$ b, ?& p. p# C
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};  ?0 J% z; c" S: `2 l
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    % p$ a- g1 ^% }4 {% O5 a" p

  5. . E# `  E( |7 l! [9 x4 Q
  6.   /** Configure the main internal regulator output voltage
    : E+ h- X4 G5 t
  7.   */
    7 ~) [2 H( p% B& [2 s
  8.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);# D& f' j2 z/ n& L0 y
  9.   /** Initializes the CPU, AHB and APB busses clocks
    2 l( Q0 H; V9 E+ A3 y
  10.   */: h5 M: ?! k9 \* P! c! ^# z! m
  11.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;9 B( o$ j( B& u
  12.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    8 w8 O3 P  ]& \3 W
  13.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;! }$ ?5 E) V/ |* f* i: u, b
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    1 R, E0 `" j( l0 T! I
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;3 [, k( X2 W! e) `
  16.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;; L$ c9 o/ a: W
  17.   RCC_OscInitStruct.PLL.PLLN = 20;
    ; R# X. h5 R4 B. C  z: U" ~
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;# H; K/ q/ S- |, c0 @
  19.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    ( N/ D+ M' I8 b
  20.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;" u' N0 ~, z: e2 [4 t
  21.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)4 U  y+ e3 X, |) C
  22.   {
    1 m- J' _. b  Z1 P
  23.     Error_Handler();
    ! y8 p' @  a# q
  24.   }" z$ K3 j8 R) Z* T' P7 @
  25.   /** Initializes the CPU, AHB and APB busses clocks ) W6 X' J6 U- j! x- I5 y( W' W* l
  26.   */
    % h0 |# A+ K( o. }. y7 `. N" }
  27.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    ' [( N1 n! l8 N* s6 I
  28.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    $ {5 F+ S5 R4 c* W) D4 V) }* F
  29.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;4 w; E- l' ~& F7 S
  30.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    + t/ Z: n$ T8 H5 f+ m: e6 j  N
  31.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;7 T# U' U8 _: ?; K: {
  32.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    ) n1 ]9 y' ]% H) l# }
  33. 3 K# ]0 P$ Z" ^7 V# n! O& A
  34.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)6 _9 b  L3 V8 E7 Y; J
  35.   {0 Q3 ]1 v# r) w
  36.     Error_Handler();
    : p; y9 X! @7 S4 _* @' Y
  37.   }
    / F) ?; z9 Y3 C' ~  E2 ]( c, ?
  38. }
    ) z8 j0 ?! E, @( L/ f
复制代码
(2)GPIO初始化( U5 ~8 y- r3 E- p; ~* L
  1. static void MX_GPIO_Init(void), s* J( J$ m% K1 i  J* E+ S
  2. {
    ' m, [' O) S3 @( u# N- T: ^1 W
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    * O7 g+ a9 C9 g. u% v
  4. , R0 L9 A0 Y4 Z; p. T  m9 ]
  5.   /* GPIO Ports Clock Enable */
    3 @" y5 x5 u9 T2 w0 r
  6.   __HAL_RCC_GPIOC_CLK_ENABLE();
      ?3 ^# ^& V8 h: k0 k
  7.   __HAL_RCC_GPIOF_CLK_ENABLE();* X- T+ U4 ], v% t$ s& Q- k
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    7 d% h2 f; _' |! q3 X
  9.   __HAL_RCC_GPIOB_CLK_ENABLE();/ j; S8 V2 b3 }7 n) v4 d
  10.   __HAL_RCC_GPIOD_CLK_ENABLE();3 D  D! Q4 K9 I) ^$ b+ [
  11. 3 V6 u" U  l+ a! y- T
  12.   /*Configure GPIO pin Output Level */
    4 S: d/ i8 ?) s5 R
  13.   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
    ' e4 T( M" E1 ~( C! O* T
  14.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);/ P* V. J7 g( C2 q/ _9 |

  15. . K7 b6 G" Z7 {5 o8 f5 N, v9 @
  16.   /*Configure GPIO pin Output Level */
    $ B) f2 E6 \! K( c" M* _
  17.   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);( a+ H! G$ K; [' U' u# D
  18. 4 k+ t7 t7 R7 e! |2 D9 w
  19.   /*Configure GPIO pins : PC13 PC14 PC15 PC8
    7 U2 A( M5 P1 |! o6 h# O
  20.                            PC9 PC10 PC11 PC12 */
    / K! B" D, a6 p
  21.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8   O! R) T! i" K# `0 V
  22.                           |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;# Y" z" D( j/ i6 ~1 y3 ~
  23.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    . d! m7 W4 w, M  }# E
  24.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    9 ~1 R& `  B% Z8 {, P* U5 T
  25.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    + Z% U0 A3 N6 r# c: o
  26.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);9 G2 q) ~& w* `$ C/ \. p! m3 P' C2 c

  27.   |8 l8 {6 R" w
  28.   /*Configure GPIO pin : PA0 */( H  u, a4 ]4 ?' n3 i
  29.   GPIO_InitStruct.Pin = GPIO_PIN_0;
    # {# [% t& e! T1 E! v% B
  30.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;. O6 U& b$ z1 F9 y1 y% o8 C. ^
  31.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    : U# [0 W5 v) F6 C5 |( V
  32.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    ! @' d, ?( t9 a; A1 K7 F+ c
  33. $ f% s5 t7 L0 z6 C* W
  34.   /*Configure GPIO pins : PB0 PB1 PB2 */9 M# t8 Z& E, r$ H4 ^- P/ y
  35.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    / E# U  ~2 h3 j4 _8 i/ L
  36.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;; n8 {# Q4 q- f: G  _
  37.   GPIO_InitStruct.Pull = GPIO_NOPULL;6 o% E0 |% u# Z* z3 f) {
  38.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    " U# y, S6 |9 _+ m
  39. 2 M; u0 m' H5 g7 ]
  40.   /*Configure GPIO pin : PD2 */
    ( |$ [+ Q* k$ z9 c& }: y$ J5 i% r4 {
  41.   GPIO_InitStruct.Pin = GPIO_PIN_2;
    ! u2 h5 z- a# O) }" h' |
  42.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;7 S8 F. y9 t6 J" h
  43.   GPIO_InitStruct.Pull = GPIO_NOPULL;6 Q3 B/ ]0 N/ g
  44.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    " s7 j0 T5 b( P$ t2 k( o; @- I
  45.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);$ b* k6 x- y: D5 d! B2 s; }

  46. 8 j' H! a1 H, q  S  H8 ~
  47. }6 `, b1 K  [* ]7 i
复制代码
二、按键模块的驱动层实现4 v9 j: X7 p' m. U1 s* E2 |8 p5 H! f
1. 硬件框图* s4 V6 C3 O# m/ U+ n
在这里插入图片描述
) T$ A& W& S* U% f! b* F# ~ 11.png
- M+ ~2 c4 c2 I% ]; B避坑点:% J& h5 U$ j+ q" L3 C3 u
短按:按键释放时判断时间# X+ e8 o. @# v: ^# i* E) @
长按:直接判断时间: X/ w  z* v1 M. y& [. {7 \

; d' _( f4 S, `+ E/ c+ c% a

) c7 v0 X/ [! A0 W2. 按键驱动层代码实现8 Z5 K; e7 T1 C( z
下面直接上C代码:
6 y5 G2 ~+ h* g4 K. p) d" ?
2 Y' d! L* e9 y; f  g' ~8 M

- ]( y. \# T( n3 p1 T(1)key.c
" ]0 `7 D1 g6 r! P" z" B! Y
  1. extern unsigned int keyCount;5 H+ D, ~7 c+ N4 P+ L
  2. extern uint8_t keyValue;/ q& R) f0 z3 n- f6 k& m& ^( D: e
  3. uint8_t keyflag = 0;
    4 d. |7 B; m5 b4 Z4 `
  4. void Key_Scan(void)2 j% i* e0 S- r1 f9 z
  5. {
    , e: ?' A% I4 v+ Z
  6. //keyState  按键状态;
    1 v4 ], ^3 K5 [* S' k1 ^* p3 V
  7. //keyPass   记录哪一个按键被按下
    ) n( B: Y% O1 M8 z
  8. //keyCount  记录按键按下时间
    1 N3 ~6 u% b8 K& [$ c, l
  9. //keyflag   开始计数标志位,方便在Systick中断中进行计时) R5 b$ b4 Y2 T6 t
  10. //keyValue  返回给应用层的键值,用于判断处理相应的事件! |7 v0 X  K& f5 Y
  11. //ShoutKeyx和LongKeyx是两个宏,为了区分短按和长按# I9 n6 H* l5 p" A: `3 K( b
  12. //ShoutKeyx 短按x键值,# s5 v8 L& E3 v/ T8 l3 w
  13. //LongKeyx        长按x键值
    2 w* d9 Q7 L) _5 m5 P2 F! x
  14.     static uint8_t keyState = 0,keyPass = 0;
    5 ~' e  ]/ f3 G( ]. z8 \
  15.     switch(keyState)5 S, G: |$ X1 x3 X- a: E
  16.     {
    - u; W  `; H  y) A( \
  17.         case 0:if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0). O/ E. T4 h+ J% i6 ~
  18.                 {
    1 U  y/ }+ i& ^5 i2 P
  19.                     HAL_Delay(100);//消抖
      K* X5 P; b! d5 x0 n
  20.                     keyState = 1;& \) t5 ~. o+ Q' O7 W' @7 Y6 c) [' q
  21.                     keyPass = 0xff; //初始化按键
    % P/ V+ t. F% D6 x
  22.                 }   5 `: v" K. ?; J6 c
  23.                 break;% k4 O0 u" s6 n2 q, \6 f
  24.                     & c3 ^9 o# L9 b. O+ W
  25.         case 1: if(KEYB_1==0||KEYB_2==0||KEYB_3==0||KEYB_4==0)7 v- u1 o0 ~7 ~5 i! `
  26.                 {
    : m. X( D$ m" i* E+ [0 P
  27.                     keyState = 2;
    0 ]: H; v3 Z. F- o5 R- [
  28.                     keyflag = 1;//开始计数
    ; \% ?- P5 I8 n8 \) A  s" q: n
  29.                     if(KEYB_1==0){
    7 V) V/ c5 P/ ^; j: E6 s
  30.                         keyPass = 1;//返回对应键值
    7 t7 x9 s  O+ V8 d( \- U5 g
  31.                     }   
    ) i  k. q8 \! f% X  [
  32.                     else if(KEYB_2==0)keyPass = 2;) ^( U2 [+ v3 t
  33.                     else if(KEYB_3==0)keyPass = 3;, Y, ~# b( J0 a+ [: n& ~" Y. N
  34.                     else if(KEYB_4==0)keyPass = 4;
    4 U3 p  H2 U- Z' r
  35.                 }   : ]0 R, ?  [+ j  I0 h1 W3 N) S) @
  36.                 else keyState = 0;//返回检测按键      
    9 ~' B9 Z. s' L! Z8 q3 ~0 g
  37.                
    1 _, S* I' ^% f5 ^! h9 I
  38.                 break;: y" e1 a8 U0 K; N! p' c
  39.         case 2:
    ' b  U# [) R7 ]" [5 U$ h' e$ J
  40.                 switch(keyPass)
    , I* f  u- G. Z# C2 b1 H
  41.                 {              
    ! y" `0 ?4 a  m: z9 h/ x( w
  42.                     case 1:if(KEYB_1!=0) //判断是否释放按键: [  l( E. y9 Y, y; _9 V( p
  43.                             {+ j* _& Z- q! u% H( }% V* y7 Q
  44.                                 if((10 < keyCount)&&(keyCount < 800))//短按0 }2 s% C. E8 ~2 |
  45.                                 {, E# K! A1 u3 e  W
  46.                                     keyCount = 0;
    / c+ i7 t4 H7 X8 _
  47.                                     keyflag = 0;
    & D8 a7 L: g% b
  48.                                     keyValue = ShoutKey1; - ^6 Q% R( Q2 `- Q0 s; c2 S
  49.                                     keyState = 0;/ @  [7 `2 ?' _! n4 {0 u( s; i
  50.                                 }   + j" v4 F! n( u* F- l$ D1 N/ g6 `; n, D
  51.                             }       0 s7 q' I" u9 z6 S* Z* b
  52.                             break;" L; m+ O8 z5 y- F5 c
  53.                     case 2:if(KEYB_2!=0)% [5 X% o' ]. f2 R/ m( I" t8 v3 D
  54.                             {
    1 x1 p6 W; {8 S9 t# u; X
  55.                                 if((10 < keyCount)&&(keyCount < 800))//短按! u; S, S) M  e0 p) Q( T6 F
  56.                                 {
    , m  q! _) D1 |9 X: a
  57.                                     keyCount = 0;0 }  ^9 ^7 }  K% K0 z3 E! V
  58.                                     keyflag = 0;! t5 R& J5 O- X) s
  59.                                     keyValue = ShoutKey2; 0 J3 F2 H+ O. h( b) J6 {
  60.                                     keyState = 0;* {! f' {8 A1 U
  61.                                 }     w7 o, `% m$ R9 u8 h
  62.                             }       - I# S1 |  z) I6 `# K2 h# M
  63.                             break;# }! D2 O9 a) k. z  @" _/ b
  64.                     case 3:if(KEYB_3!=0)7 R7 F  I+ t7 f1 @" {$ i
  65.                             {  j. C( C2 {+ @0 ~
  66.                                 if((10 < keyCount) && (keyCount < 800))//短按
    : p5 A  p8 m' M7 q' E
  67.                                 {. F$ h2 d! v) u& h  J6 ^. E/ J8 N/ [
  68.                                     keyCount = 0;
    + O, ?: }1 A9 C, ]( x$ a
  69.                                     keyflag = 0;5 s, f8 S$ H: ?# F0 m( `
  70.                                     keyValue = ShoutKey3; " P/ p" K7 }2 M) i' U
  71.                                     keyState = 0;' C: {$ ~8 q3 x' G1 X
  72.                                 }   
    % p# D! P0 @% u% h& ~2 F/ n
  73.                             }      
    ' m, p9 g. |0 v6 B
  74.                             break;
    4 }- l( b5 }/ }( W: x0 k3 \
  75.                     case 4:if(KEYB_4!=0)
    2 J+ F/ m4 d6 m  F$ ]6 \+ J
  76.                             {
    1 T2 s6 d- _9 p) s- N
  77.                                 if((10 < keyCount)&&(keyCount < 800))//短按
    4 M: i2 Y6 i! Q7 ^
  78.                                 {
    9 n# I: L6 d9 U3 _: e; N
  79.                                     keyCount = 0;- F4 R4 Q5 c/ |9 E7 e- U, y
  80.                                     keyflag = 0;
    2 i: k$ V) x: t% w6 M
  81.                                     keyValue = ShoutKey4; 1 k& C1 k# {8 V0 J( d# F$ q
  82.                                     keyState = 0;+ B. W: r, v* o! D6 P
  83.                                 }   5 f- _7 `4 Z+ n; I3 z
  84.                             }
    " K1 Q' W( k  m1 ]3 o: X, p# g0 ~
  85.                             break;' S. x+ t" T0 L6 X3 d
  86.                 }/ @" v5 }, U8 b& K0 d
  87.                 if(keyCount > 800)//长按- K$ {9 Q3 J( [2 v* C- J6 m- l. E
  88.                 {   ! w! F- m3 E8 S- u9 x8 W) s
  89.                     if(KEYB_1==0)keyValue = LongKey1;
    " X& r) H4 I1 A( I, h9 G+ e
  90.                     else if(KEYB_2==0)keyValue = LongKey2;
    3 Q0 ~1 W; d; l
  91.                     else if(KEYB_3==0)keyValue = LongKey3;
    3 |; t5 }, y. p7 V! j) H
  92.                     else if(KEYB_4==0)keyValue = LongKey4;
    6 f7 U9 F* j5 [" A7 z4 H0 q# u

  93. ( d( X3 f0 Z0 }  q3 q8 Q& ?
  94.                     keyState = 3;
    % a! a, i% v5 v& r. D6 Y
  95.                 }
    # i* W+ N2 Q) ~- K* w
  96.                 break;3 S/ m6 b% k5 T# A' a

  97. ! W7 j+ q7 q; \6 K& j5 E% l
  98.         case 3: if(KEYB_1==1&&KEYB_2==1&&KEYB_3==1&&KEYB_4==1)
    ( F  ]1 P* K: z- Z2 _
  99.                 {8 S; R6 `3 b# p0 a9 Q
  100.                     keyCount = 0;' ~9 B. v  Q6 h
  101.                     keyflag = 0;
    $ y1 h7 e4 M1 S
  102.                     keyState = 0;5 q  l# H. a; c
  103.                     keyValue = 0xff;//长按之后释放按键代表不执行操作,就没有键值传出  
    ) I8 V; A8 q4 s: @
  104.                 }
    2 i4 B8 V. }' j; e
  105.                 " h1 g! b$ A. W
  106.                 break;
    ) n( v+ G  b8 [9 O: N
  107.     }
    7 i+ x/ j% ?) X
  108. }5 E: n& q  }( S! y9 J! w
复制代码
(2)key.h$ G  @6 {" t: @$ H
  1. #ifndef __KEY_H) R. W' k4 u" n. p1 C
  2. #define __KEY_H
    3 K5 W8 Q" ^; r3 M0 }7 N7 n. m2 p
  3. #include "stm32g4xx_hal.h"2 ]/ W; D0 s7 @; ^1 b, M) r: F
  4. #define KEYB_1                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) //PB0' C2 _9 }$ U8 j* @$ {0 M
  5. #define KEYB_2                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) //PB1
    5 s6 T* h/ Z8 p9 b  g+ ~! @) h
  6. #define KEYB_3                 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)//PB2
    $ \1 U0 a  G8 [& Q9 T
  7. #define KEYB_4                 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)//PA0) K4 T+ N8 y0 e
  8. #define ShoutKey1             10 |' y5 M! E" X/ A' ?: T$ k$ o  a
  9. #define ShoutKey2                2; `* u& m. p: X! Q* `7 n9 _# l+ G
  10. #define ShoutKey3                3
    # W# Q- L! I, N& ~
  11. #define ShoutKey4       4/ `3 Q- j! X5 e
  12. #define LongKey1             51 E- {6 W+ W$ X/ t9 y* ]' A
  13. #define LongKey2                6
    9 n: |; m2 a& ]6 A+ G" Q
  14. #define LongKey3                7
    " g( V4 w& r$ s; i. U- I! ], ^0 i1 u
  15. #define LongKey4        8& `* M2 @) f6 ]. @4 {3 L' x& X/ _
  16. void Key_Scan(void);
    & q- B% A# e& ~* `0 q$ V+ a# }& y
  17. #endif
    + w- c' w3 O+ \- ]
复制代码
3. 计时操作
( \0 j7 J  Q0 d3 k1 N( B我使用Systick写了一个简单的定时中断函数,(触发Systick的定时中断时间是1ms)去处理计时操作,这是为了给按键驱动提供短按和长按的时间,便于在驱动层进行相应的判断,所以我不去深挖Systick模块的细节,本文会用即可,后面再单独来记录学习Systick模块。- r( ~& g3 v: N1 S/ Y* v0 w, b
下面直接来看看Systick的中断服务函数叭,很简单,就这么几句~5 G# s* b5 Y4 ]0 h  Y" y  R& r8 j6 z
  1. extern uint8_t keyflag;* S8 Y6 M, t+ E
  2. unsigned int keyCount = 0;9 \% a, O( L( L: g* z& s8 b' F
  3. void SysTick_Handler(void)
    3 {1 r" w1 |5 Y! U+ l+ Q2 P
  4. {% |( C7 I1 Q; Z" C3 N  V
  5.   HAL_IncTick(); //这个api是用于HAL库的延时函数HAL_Delay(uint32_t Delay)6 e- X( _2 d. Q' ]3 R4 }9 z: }
  6.         if(keyflag == 1) //若有按键按下就开始计时* u  ]9 k* c8 d& `" e6 U
  7.                 keyCount++;        5 m% d8 o4 q* Y3 y
  8. }( _- x8 N0 O( Z  R+ b5 l9 q! y
复制代码
三、应用层简单逻辑实现
4 s7 u8 [% ]9 G5 X8 r! O% G应用层要做的事情在文章开篇其实已经说了,因为逻辑很简单,就是根据长按和短按实现不同的点灯程序,所以直接上代码叭~: |) m# S5 J- K/ E2 \& @
  1. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); //关闭所有灯 5 a2 l4 ~* X: D" y( w4 m
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);        //关闭锁存器1 g' t: c% R4 G6 O
  3. while (1)
    # X1 F+ z" g8 \6 Z3 E
  4. {! h: I6 Y- f2 G
  5.                 Key_Scan();6 h- b  D- B5 O8 Z, [" C
  6.                 if(keyValue) //有按键按下
      O7 Q4 W' f( T3 r: e
  7.                 {
    - L( I- i5 v" K0 u
  8.                         if(keyValue < 5) //短按
    ' x0 w. @4 ^) B
  9.                         {
    ; a' E' Q" Z8 b& t
  10.                                 switch(keyValue)
    . g1 i0 v! r# E: a" K
  11.                                 {
    / w% O: x' O& Y8 e
  12.                                         case 1:/ m) A4 k( L# s8 O$ K
  13.                                                         keyValue = 0;
    9 m  D. @, B( }% t4 `
  14.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);: h2 i3 a( {" x5 V0 x2 T% F) r0 O# q
  15.                                                         HAL_Delay(100);. Q/ |$ p2 ]+ C, i. J! _
  16.                                         break;
    ) p1 v2 p* J( U4 \8 p, L
  17.                                         case 2:0 d0 i5 m! A6 Z3 w- t4 U4 T: v5 h
  18.                                                         keyValue = 0;
    8 J9 R) R! g, p, V5 V. R+ X
  19.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
    0 v9 k' t( e# f9 P9 l
  20.                                                         HAL_Delay(100);
    ; e2 V6 S  Y* Z; L1 ^2 R7 s
  21.                                         break;+ Z) a1 f2 ^: O# D$ Q9 r
  22.                                         case 3:3 @/ R% ]/ C* b6 u8 N$ d) ~
  23.                                                         keyValue = 0;6 O+ V4 E4 X  B' I! C. ^0 N
  24.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    # |8 }) b+ q$ L$ ^8 ^
  25.                                                         HAL_Delay(100);
    : b4 W& B/ F% {3 ^0 R2 T/ h
  26.                                         break;
    , @; c7 B3 ~# ~* W  d
  27.                                         case 4:  s1 L9 S; i* N2 r
  28.                                                         keyValue = 0;  |0 [* O( t3 d% J
  29.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
    3 [' U) f) x& e3 A* _" \. F* o
  30.                                                         HAL_Delay(100);
    $ ]& I- s+ q& Z2 ?
  31.                                         break;. x6 U8 J8 k5 U6 }! e/ E
  32.                                 }
    4 Q" ]; N4 `/ R/ M" B. }
  33.                         }# T- k7 l1 N; l# E' H) ?
  34.                         else5 z+ s) m  T% o9 k: |3 ^% C
  35.                         {% A8 D$ `5 ^  L. f8 W
  36.                                 switch(keyValue)
    $ y( z1 ?* `' [1 F  B
  37.                                 {' z& Q& F' m$ i( [# Q# K
  38.                                         case 5:
    7 E% z! O2 r& T3 q0 _3 i) w1 A5 q, Q
  39.                                                         keyValue = 0;9 P+ F( W% r5 ~/ P: q% t
  40.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);, F. |0 _8 i! A9 \% d+ C
  41.                                                         HAL_Delay(100);
    % b3 f# M' V- v
  42.                                         break;6 q- s* ?! z2 T2 S! H
  43.                                         case 6:
    % J$ [" h! f& o: C6 K# K
  44.                                                         keyValue = 0;2 U  K# \- k7 d7 Q* ~
  45.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);& ]& v2 t  x9 @/ D! |0 H
  46.                                                         HAL_Delay(100);
    7 c" }3 ^% G( w, D. w; k
  47.                                         break;
    ; Q" X3 k' y5 ~- ~) {( G7 j6 t
  48.                                         case 7:* `# |$ _( i5 @
  49.                                                         keyValue = 0;" |8 Z. F  o. E8 k. d
  50.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    3 n& q  U. |; s- V" h
  51.                                                         HAL_Delay(100);
    - C( L% r, R2 V' A5 R( \, S& V
  52.                                         break;
    3 l0 L  {! a, O3 k7 w
  53.                                         case 8:( ?: j& t7 e3 x
  54.                                                         keyValue = 0;
    1 E, L( E. T% a5 q/ \& x
  55.                                                         HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
    - L3 A) e/ H7 O3 r. k
  56.                                                         HAL_Delay(100);
    ' q; X4 H; o9 o0 d% D
  57.                                         break;
    ! v7 ]; C) B4 E' _) ^: J- [
  58.                                 }& ?- X; O: R" w/ |4 R
  59.                         }
    ( S: b; W' e' C. [$ d- ^* g
  60.                 }
    " ]5 B7 Q. J- Y( g7 P
  61. }7 {& z- h# ^; k4 {
复制代码
总结
6 f' x0 S* [/ Y, j8 [6 V4 M以上就是今天要讲的内容,本文仅仅简单介绍了MCU里按键的短按和长按功能,希望能对你有所帮助噢~。8 \3 i! p6 S8 j
; G+ E9 C7 F2 U) h
, d$ C5 y& W( v! `9 T
; v* D4 G! h4 j  N

/ U" Y/ I" x$ c! c8 S; G$ [7 Q" C3 E0 d' g6 k

3 G, H6 l5 R# [; G. x3 ]9 v3 T) w$ w1 z' z5 b; G; L9 I

" P: {7 r; A4 X" {- g& k7 C: [6 Q; C/ ~5 u* [7 |
收藏 评论1 发布时间:2021-6-18 16:44

举报

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