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

【经验分享】STM32开发,使用HAL库函数实现按键(中断和普通扫描)控制LED灯

[复制链接]
STMCU小助手 发布时间:2022-5-5 17:53
1 概述; t4 T$ b5 }# g' r! H5 B- l
1.1 资源概述
2 [2 g9 K3 v+ K1 v- k1 {* q2 |5 `4 O
开发板:ST官方NUCLEO-F103RB开发板) W* W- l7 w2 L5 Q1 V: E+ N  {
CUBEMX版本:1.3.0
9 [* w. [/ G& pMDK版本:5.23
6 F$ l2 [. Q0 p4 b# |/ r3 \7 A7 C主控芯片型号:STM32F103RBT6
3 V. \# T6 S  ^: M2 I- f. O
# d$ ~% Y  ~+ P6 [* V F{C)~SJWP7}$~(J$SM$Y.png
5 U' z4 U% W$ o8 s
; ]: \6 J$ ~9 B0 s7 e$ i/ v1.2 引脚资源分配  h$ S5 c/ v: |$ P* u* B. O

8 D% D+ x, J1 T  ]5 r) @  T 5 ]9 I. _5 V: R
4 I+ P  Z  |; x
1.3 中断概述

6 u2 @. h& R- O外部中断/事件控制器框图
  ?  P( V* s( p! V* |& _ @L3V_IE(XDFPI22)9~FDPKT.png
6 N& ~% O8 D9 F; @$ G. g4 b/ F2 d: V- U- n2 g, n/ D
优先级分组可以设置为5种方式。分别是1个抢占优先级/16个子优先级到16个抢占优先级/1个子优先级。( @% S5 p2 t3 P% T' w
. n' [, H& A( h
20200408210416610.png
/ D* K9 ?% Q4 l& T/ E. C5 s- G& ~+ [* M
1.4 实现功能4 K% E% B$ k  ~
实现功能:
9 `. w1 D, V" C' Q! D1、上电初始化后,LED2灯亮。  [, k7 `! J7 w2 N* f( f
2、若按键被按下,触发外部中断,则将LED2灯状态翻转。
# N  i: r! T1 m) b
1 u; B- _# a2 Q! {5 ~
2 软件开发,使用中断的方式" p" Y# c$ g& D. S# H  U1 H
2.1 CUBEMX配置
! E0 W$ o6 }  y- p% C# D
Button部分原理图如下,PC13为低输入有效。电路中与按键并联的100nF是按键消抖用,使用正点原子的开发板没有此电容,会出现按一次,LED灯亮灭各一次的现象,说明抖动了,执行了两次中断。
* I% p+ j5 |. f: M* m
8 ~$ v* t2 K) |* Z! l L2[}}(5QY4R%)2]5@LN%@_H.png 8 h! r  ?9 [! f2 m( B. c. E
: o3 `. B1 O) R
PC13配置为中断模式,下降沿触发,上拉。; V% t: Y' w! D9 [" h! k

' e! s  k$ p- p/ [; u 20200408203015489.png
4 x5 C' s5 V( ~: y! x
- m4 X$ c& h% I- p2 G中断分组设置,采用默认设置,抢占优先级0,子优先级0。
+ g; L! X! m- _
; T4 a2 Q; a4 I 20200408203043659.png
$ l  Y2 u0 y! `5 R. N
0 ^2 }* f- A- J3 }2 J" }9 `中断优先级说明,线10到线15使用同一个中断优先级,PC13对应的是线13。' W2 q, w5 ]# I1 [8 l' G; g) P

3 L5 V. C% Q, B `SQGKO$NU~~`JXN60CV5~]I.png 2 n; a$ z. T' E6 `2 e6 F/ U
' r( r  `% C' T) F
2.2 程序代码/ {+ }) w1 c  w. F7 D  c7 H1 U
生成程序代码,系统自动对LED2和Button进行了初始化,并对Button对应的中断进行了分组和使能。9 B4 A2 c, a& O- n

  ~# u' b& L) D2 T) C7 z) h4 k
  1. void MX_GPIO_Init(void)
    * I8 ]/ I4 T9 b6 U# }+ j: n; u
  2. {
    # |# x+ ?, P4 H9 E# ^
  3. $ G! v' K: U5 c" u- i
  4.   GPIO_InitTypeDef GPIO_InitStruct = {0};/ {  V$ e. K$ X" N- o
  5. - t9 U* F8 P& q9 q, d
  6.   /* GPIO Ports Clock Enable */
    : m  `' D0 o( V/ d  @
  7.   __HAL_RCC_GPIOC_CLK_ENABLE();
    1 D6 \6 n) e. G! t) W1 j
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    / u8 Z7 i; j  _
  9. ! ~% f- ?' e# x5 K7 ?
  10.   /*Configure GPIO pin Output Level */
    6 @9 x- E; t: j. d
  11.   HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);  ~2 P) o9 Q+ P1 V/ E4 s

  12. + ~4 M% d1 s8 D5 @$ b0 w
  13.   /*Configure GPIO pin : PtPin */
    0 R  j& l; n# x) Z
  14.   GPIO_InitStruct.Pin = Button_Pin;* P& L0 n- u3 ~% k
  15.   GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    9 u) g+ Y& `" T" I5 `- v
  16.   GPIO_InitStruct.Pull = GPIO_PULLUP;
    6 t! M! p1 A3 b- D1 t9 m. e8 @5 I
  17.   HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);
    0 |# J, ~; N9 E4 o7 D; T

  18. 8 B" V* ?% K7 X4 n- A5 W
  19.   /*Configure GPIO pin : PtPin */
    * K+ I/ o- o7 N& O) S! M; C* [
  20.   GPIO_InitStruct.Pin = LED2_Pin;
    ) t, Q6 c) Q: c
  21.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;( l6 j2 S. u9 p, y0 x* w
  22.   GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    $ n* n1 r0 q8 X0 X( M) c
  23.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    6 P  y6 z! U0 T* l) F( y
  24.   HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
    7 [- R( t5 j! a4 B; ]- P" y
  25. & o+ A' N  u1 }5 T( `2 X  i+ C  h
  26.   /* EXTI interrupt init*/5 h& ^" w! u  U- @
  27.   HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
    & R& M& y) ^$ b8 H
  28.   HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
    : r+ ?% W# C. i9 z7 y
  29. 1 v- l  B* S% B) _' n) k7 H
  30. }
复制代码

" x' @2 e& j( P+ G" v  c$ m在main函数中增加初始化LED2,让上电初始化时亮灯。
% l: E6 [: g! D* Y, ^# o
: y' Y" V! o1 v% J/ V3 ]
  1. HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);//上电初始化将LED2灯点亮
复制代码
. a+ Z: t! l  {5 A% r) p
增加中断回调函数,当检测到中断时执行中断回调函数,翻转LED2灯的状态。2 Y1 j  b2 x+ D, t, i# I8 W
! V" t& M1 T" J6 R2 ]+ ~
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数,当有中断发生时,将LED2灯进行翻转& Q! X& F8 |* ]5 Z- t
  2. {                & K5 k1 {5 m9 {1 F
  3.          HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);                ) u! `# |$ S5 j6 w" a
  4. }
复制代码

6 \5 ]- `" L; c( @: Z& Jwhile(1)函数保留为空,编程到此完成。# b- [9 e+ O; U6 I# ?4 @6 ~
实现过程分析。
8 Z* ~& F$ m: \9 S1、在stm32f1xx_it.c中定义了EXIT15-10中断服务函数。
7 j; b" Y* \" _! y* o. z
1 g% N* I0 r% h: \) y3 E: C
  1. void EXTI15_10_IRQHandler(void)//中断处理函数,当检测到中断,即Button被按下时,检测到下降沿即为有效
    & |% T$ [& P$ [, O) D
  2. {
    . }: {( i/ B3 P4 g
  3.   HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
    / N" j6 A" Q1 U3 H9 a
  4. }
复制代码
! [/ f, O+ u6 i8 b
2、在stm32f1xx_hal_gpio.c中定义了HAL_GPIO_EXTI_IRQHandler。
- c! k, }* J+ ^( l+ B: M1 `6 _: P# |# w" B9 J$ n: t
  1. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
    ' T/ ~1 S0 D5 p7 D
  2. {
    7 {0 n# U3 x  j5 a2 S
  3.   /* 检测到了中断 */
    ; c0 w& j8 e6 K# B/ ^! \
  4.   if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)# e$ \& h& L' I  r( [. Z0 @
  5.   {: ]  q: _1 a' ^% A0 d' Z6 `
  6.     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);//清除中断状态
    ! J: ~$ V" K2 ^
  7.     HAL_GPIO_EXTI_Callback(GPIO_Pin);//调用回调函数        ' @( K4 X% W3 R' r( K
  8.   }
    6 L: M2 [1 Y5 a- l- `' I
  9. }
复制代码
) i/ `) e8 A8 G
3、在main函数中定义了回调函数HAL_GPIO_EXTI_Callback。
* G5 s+ u/ K7 n1 g2 |( n4、当Button被按下时,1到3会依次执行。
8 n& Q' W$ l4 T6 [
8 L- `5 C, b8 h; o  Q0 L3 使用两次检测电平的方式

9 o7 ]2 X1 m, d$ O: |% ]7 o# K+ K" u程序源代码如下,使用了gg=G VIm的自动调整格式功能,这个工具是真香,实现的功能是循环,当第一次按时,1S闪烁一次,再按一次时,500mS闪烁2次,按第三下时250mS闪烁4次。在写程序过程中同样用到了ALT +/的补全提示功能。
  z( T. w! B2 Z% X4 U( V8 ]  |6 g: o
1 z* q' T3 V, z, i7 u: d
  1.         while (1)6 ?. k9 y1 {! t5 u
  2.         {
    5 V/ g5 E  R5 H, S% L
  3.                 /* USER CODE END WHILE */
    & K8 e% U" w' N2 g: {4 W' T
  4.                 if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==0)
    + o; L; f" i' P, Z+ y
  5.                 {# g; G9 o3 |) X% C) J+ g0 {2 J7 a
  6.                         HAL_Delay(10);
      a( d0 E1 L: w# ^. W4 a* P0 D- _
  7.                         if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==0)6 n) h! a; M, D" V. O7 f7 V
  8.                         {
    5 _2 s$ Q8 O! w7 H
  9.                                 key=1;
    2 I& n/ r2 B) X) ]( t
  10.                         }! u9 m  ?" p2 M2 h
  11.                         else
    ' m0 ~7 Q8 F' a# U! V! R) m
  12.                                 key=0;
    " i2 q% P+ _* k. M
  13.                 }1 W/ Z; D* l3 l) D( B- j! t+ i
  14.                 while(key==1)0 a+ t) J. x. N4 f, s1 ]
  15.                 {! V/ B3 T6 i4 z+ R
  16.                         switch(time)
    # N2 z: y. T# {% T, Q* G) ~; }
  17.                         {8 T% {% H$ G- X) A% g  a
  18.                         case 0:
    , [  p/ H% o9 Q. |' P: |' Z
  19.                                 for(int i=0;i<2;i++)
    . H, F; T+ e: I8 M4 X8 y' J
  20.                                 {2 x" {8 i7 {6 R' |# L3 W
  21.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯
    . a& ?5 U3 ^! V8 v9 E
  22.                                         HAL_Delay(1000);//延迟1s& m2 N  D: b2 L1 E. g
  23.                                         key=0;' A" M. q5 B: `$ q6 N/ O" T
  24.                                 }
    1 q1 w7 i3 Z% w- ^- O8 F
  25.                                 break;
    " ^* {; ~! Y( N7 C$ L5 |- l5 h5 M
  26.                         case 1:. P+ W9 L  u2 o1 d$ v/ I, y3 _  R
  27.                                 for(int i=0;i<4;i++)3 t8 n# W3 ~6 {5 j% T
  28.                                 {
    1 ^3 ]4 J3 ~7 S  {, y$ \! L
  29.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯
    & w. q4 |3 f; C& R
  30.                                         HAL_Delay(500);//延迟1s
      @3 k3 j) f; V7 I6 g' [* i
  31.                                         key=0;! q0 U' r. Q6 O; A" V# o
  32.                                 }
    4 c8 m( K7 `) T( T
  33.                                 break;
    % O- G+ f' x' c9 C9 Q
  34.                         case 2:. P' u* }. h( B3 k
  35.                                 for(int i=0;i<8;i++): i( H$ ]* k- S& {
  36.                                 {
    ' K( g* g- k5 U; u  y9 b3 g
  37.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯
    + b7 k7 q  r8 O2 o( \
  38.                                         HAL_Delay(250);//延迟1s  @5 t& z1 t8 A- h
  39.                                         key=0;9 ~, J  M0 w8 \5 m( f. J5 y
  40.                                 }
    & j9 A+ y2 p' H( ^) a3 P0 z
  41.                                 break;
    # O$ w( g. ?3 Z! [  z' F
  42.                         default:break;
    9 m0 O  Q0 S( R  n
  43.                         }) ~: t5 Y0 m/ J9 \
  44.                         time++;
    * x( J8 k) a! ]( @
  45.                         if(time==3)
    4 j# _$ J% C7 w4 J
  46.                                 time=0;
    4 E' y) q5 ?% b; S! i5 j5 G+ @
  47.                 }' K: z' a5 B: L: K& n5 E1 v, M
  48.                 /* USER CODE BEGIN 3 */
    7 f' B& C; d- H+ Q" n1 W( H7 ?! A
  49.         }: P  O- D  u, M$ v: [
  50.         /* USER CODE END 3 */
    & f! C6 A. e, C9 ^1 c6 K/ k
  51. }
    / n# l7 n( ^( _8 c
复制代码

- c: \1 \9 O* z8 {9 w& T4 实现结果. ^* j- H9 r- O1 ?
上电后LED灯常亮,当有按键按下时,LED翻转状态。黑色按键是复位键Reset,蓝色按键是用户按键(PC13 Button)。
7 O) o4 f8 D; P. \( j' F9 M2 E) T, j% E) p# D
20200408211643400.gif
, w! g( T; ?7 K  ]; B2 S8 y( T. J! M, x
Tips:在使用中断时请务必配置好gpio的上下拉,若为下降沿触发,则配置为上拉。若为上升沿触发,则配置为下拉。否则有可能导致中断不可用。
, _2 g8 G! D# M/ A, T- ~2 x1 }3 {" Z! U. j0 U4 x) ^) M4 @
" ]* Q! X5 ^& }5 ]  T4 I$ i9 v! B! v$ n

( M. h# I  }. ^$ s
赞 收藏 评论0 发布时间:2022-5-5 17:53

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版