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

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

[复制链接]
STMCU小助手 发布时间:2022-5-5 17:53
1 概述% U' }& Z8 I* V$ e% Y: q2 T
1.1 资源概述

2 l4 F. E4 g  Q开发板:ST官方NUCLEO-F103RB开发板  b5 t6 R% \/ r# Q3 V( g
CUBEMX版本:1.3.0
- k, J6 M! o8 A# B% X  MMDK版本:5.23& A) N, f# N7 Z0 ^
主控芯片型号:STM32F103RBT6
% M  z: I( |) K5 X/ L; Y! S
* {; F8 B# Y9 I8 I5 C F{C)~SJWP7}$~(J$SM$Y.png
' {2 @( D9 K/ G/ S. i% o6 c2 Q% N- J" @, G8 v) M9 A
1.2 引脚资源分配
& L! D, m" t" z/ _* v
( ?* M$ t8 A3 E( i* q2 Q3 \
# v, ]5 k" V8 q% \0 Q' i, C5 W
6 Q4 A5 i% ~6 w; y" [$ G1.3 中断概述
5 |! m6 b" B* G8 C) n6 T- ?
外部中断/事件控制器框图' {( P7 o  X3 j& l& V
@L3V_IE(XDFPI22)9~FDPKT.png
/ m) B( [- e% u. O8 E! \0 Q3 c# D8 y- B" v, U4 Y7 B5 x6 h
优先级分组可以设置为5种方式。分别是1个抢占优先级/16个子优先级到16个抢占优先级/1个子优先级。
& P" g  g0 B! Y; i/ [. G- V
5 o" z# w/ F" L 20200408210416610.png 1 J' I/ i# m$ t$ M$ B
, a$ Z$ d9 r* z" f( o
1.4 实现功能
2 B9 N+ Q$ i# Z3 Q实现功能:
+ r% L7 @$ _- [2 G, r1、上电初始化后,LED2灯亮。
5 T: o3 M6 G* s2 Z* R2 z( u2、若按键被按下,触发外部中断,则将LED2灯状态翻转。  f5 G+ g7 C9 R/ p' ]5 I
' z$ ?) c( s& {3 w0 U1 q. I
2 软件开发,使用中断的方式4 X) T: i6 {) f, c* g& }7 `$ p
2.1 CUBEMX配置

/ [' n( n/ ]6 O1 mButton部分原理图如下,PC13为低输入有效。电路中与按键并联的100nF是按键消抖用,使用正点原子的开发板没有此电容,会出现按一次,LED灯亮灭各一次的现象,说明抖动了,执行了两次中断。
- P3 R$ Y4 B2 I/ Y+ o! M# Z9 @7 R6 L, E# J5 o
L2[}}(5QY4R%)2]5@LN%@_H.png 3 E! I! v4 O# R3 N

, r* Y4 Z6 ]$ W0 U5 v$ H& g, [PC13配置为中断模式,下降沿触发,上拉。
* U+ j$ F2 c5 u! a9 U) a4 c3 W- O% E" F- ^% O
20200408203015489.png
7 M6 I& L- J/ ~) E+ O" L: j" k: ?& ?" i8 Z
中断分组设置,采用默认设置,抢占优先级0,子优先级0。
+ ~9 J  n% }" q9 o: x# x" M: J
2 ^% q8 O0 [* \9 z( p1 i- i 20200408203043659.png
" g& Z4 {8 L' J# Q% ?( x" N8 Y) ]3 \' m+ p3 ?  E: v
中断优先级说明,线10到线15使用同一个中断优先级,PC13对应的是线13。! X" Q9 y* p" n! u3 w' a
9 v' ]8 ?/ V9 E+ q$ z' D# y$ W
`SQGKO$NU~~`JXN60CV5~]I.png
* d" g# A' P) d; G
% w: g- O  }( s9 z2.2 程序代码9 ]- ?/ ?* \0 P+ J- f
生成程序代码,系统自动对LED2和Button进行了初始化,并对Button对应的中断进行了分组和使能。$ u3 v! }+ s1 \( R# Q/ e+ B" B
+ ~2 x# x( `7 `6 d" K+ V
  1. void MX_GPIO_Init(void)2 _$ {) h0 d+ o2 W4 I4 K
  2. {9 W, o. s5 S+ D3 ]7 y$ B
  3. 9 u6 t" R  R6 s+ j6 ?, z
  4.   GPIO_InitTypeDef GPIO_InitStruct = {0};$ J3 L( ?) @- p( W: G$ R* w
  5. - }' e1 ~! X1 P: n* p
  6.   /* GPIO Ports Clock Enable */
    8 O3 x4 ?+ C% z8 @4 ^3 f
  7.   __HAL_RCC_GPIOC_CLK_ENABLE();7 V# @) I8 t7 B8 d) V6 }
  8.   __HAL_RCC_GPIOA_CLK_ENABLE();
    ; F1 J! Z9 l- d9 f
  9. % T& p$ x' Y( U$ t- |8 j
  10.   /*Configure GPIO pin Output Level */
      E" F  ^2 ^3 L$ M: g0 s5 ]
  11.   HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);2 Q3 a$ F  u9 x; E7 N1 i/ c0 j& R

  12. . c% e8 S2 s9 S) X/ g
  13.   /*Configure GPIO pin : PtPin */7 S/ n+ N* ]" W: a( ^
  14.   GPIO_InitStruct.Pin = Button_Pin;+ x  r  h) q2 z/ J
  15.   GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;3 r. Y  X6 c9 b
  16.   GPIO_InitStruct.Pull = GPIO_PULLUP;
    ' i- {6 y0 U" w) H% X8 E
  17.   HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);# e4 ]3 {, R1 N) z; ^- t, V+ A
  18. ' D: ]5 {' ?) y; p8 f! h$ ~
  19.   /*Configure GPIO pin : PtPin */
    2 p; O) v6 S) Y* n& ~
  20.   GPIO_InitStruct.Pin = LED2_Pin;6 X' S; T$ i5 e. }6 n
  21.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    - d% D8 O. {' s4 O( w  o  n$ @- `: M
  22.   GPIO_InitStruct.Pull = GPIO_PULLDOWN;' o! ^; o+ e* l% S8 y% u
  23.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    " w# ]4 p' V4 h3 t/ ]
  24.   HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
    4 A- h- B2 o8 b6 R& J7 J  J- I# |
  25. 0 X$ S: E) g' I2 s4 O+ B
  26.   /* EXTI interrupt init*/% _! \7 R( @: E* R5 H, o. m5 k
  27.   HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
    . E' @! o& x$ G0 u
  28.   HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);) n3 @9 _7 t! Q/ W* }6 `# y
  29. 4 H$ P* g% q  K
  30. }
复制代码

  U: E( [4 O7 w) n# C% o在main函数中增加初始化LED2,让上电初始化时亮灯。
7 B2 ]( ^+ ~; |+ r4 \. T3 B( L1 h) ~9 P) Q4 U* S+ q* l' {- k
  1. HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);//上电初始化将LED2灯点亮
复制代码

6 U* {( r8 {2 `& Y- F3 A6 R增加中断回调函数,当检测到中断时执行中断回调函数,翻转LED2灯的状态。
+ r% O7 {7 |- A* e, x* h
/ a3 L" E/ X1 |0 q4 C% @% f
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数,当有中断发生时,将LED2灯进行翻转- q4 K: `. f# a3 H
  2. {                0 s) X& X! O. v
  3.          HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);               
    ) D; ]* \: g' [3 n
  4. }
复制代码
8 K# _( H/ ^) F, Y2 M9 n8 ^
while(1)函数保留为空,编程到此完成。
7 a9 C* O8 D1 t( s实现过程分析。
& q* w4 F, _$ m# o. f7 z# o1、在stm32f1xx_it.c中定义了EXIT15-10中断服务函数。
9 H, n; d+ W9 p3 S
/ S6 O  G4 Y+ Z' z, O
  1. void EXTI15_10_IRQHandler(void)//中断处理函数,当检测到中断,即Button被按下时,检测到下降沿即为有效0 g6 K; I% s& }9 s
  2. {& L3 [) J: D- r1 c! h
  3.   HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
    . X- M% b" b: [# l/ m
  4. }
复制代码

; k5 l& q% U* u; Q& h9 ^2、在stm32f1xx_hal_gpio.c中定义了HAL_GPIO_EXTI_IRQHandler。
, J! @& y) I  {" {) [3 O& d, e/ _1 H% v3 f
  1. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
    & x! s4 g- ~  G+ D2 Q$ d
  2. {- P" n' d- C  @) @
  3.   /* 检测到了中断 */6 x( w6 s  c  ~, k+ F7 @
  4.   if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
    0 v' p6 [+ d! l8 E
  5.   {
    ) A/ O2 ]! X9 f; N" m4 Z
  6.     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);//清除中断状态% s# v+ u$ A4 j5 L$ F" o( r& a
  7.     HAL_GPIO_EXTI_Callback(GPIO_Pin);//调用回调函数        ) O1 A7 q9 ~9 ^2 ~0 O
  8.   }9 O* Y$ K8 k" `0 E  w$ z
  9. }
复制代码
5 Z( O2 @, e! E2 R7 H: s2 ~/ A
3、在main函数中定义了回调函数HAL_GPIO_EXTI_Callback。
2 R# g( y, N8 @6 G1 Q: j4、当Button被按下时,1到3会依次执行。: Z+ d9 _. ~+ M/ T* Z4 S/ M6 R
  T$ w) t2 g3 A: L+ O5 {
3 使用两次检测电平的方式
- L$ V+ Q; @0 S- N
程序源代码如下,使用了gg=G VIm的自动调整格式功能,这个工具是真香,实现的功能是循环,当第一次按时,1S闪烁一次,再按一次时,500mS闪烁2次,按第三下时250mS闪烁4次。在写程序过程中同样用到了ALT +/的补全提示功能。2 R9 r) }4 k  O  g* y
& I4 c: D  Q- X7 o/ m( n% G" ^
  1.         while (1)8 M5 j/ U6 g  `! T$ j6 ]; A
  2.         {! s, v4 V; t& g! G6 i
  3.                 /* USER CODE END WHILE */
    4 _1 K1 n: i! v# \
  4.                 if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==0)
    . L* _* E6 B7 A# @. M- ^+ ]8 k# a
  5.                 {6 F. P( q. k; ?( ?3 {$ \- S
  6.                         HAL_Delay(10);
    0 p( s3 K$ |) K
  7.                         if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==0)
    ( b  S& H7 b5 {; t! w! g
  8.                         {$ t- R; s' ~/ v5 K, h
  9.                                 key=1;! |* b, i% H* G$ ?
  10.                         }
    4 |# o& u( v4 ^! n5 l
  11.                         else6 }3 u7 f3 [2 Q3 \1 M
  12.                                 key=0;$ m* [% ], w4 ^% |
  13.                 }
    : o, _7 W3 q  c: }# k- D
  14.                 while(key==1)
    2 V5 u4 F1 y% z& [% I
  15.                 {! j! O9 H& p' c9 o7 y: V
  16.                         switch(time)4 U! R! t9 R; X+ `7 X$ O5 E
  17.                         {
    . A( l$ R8 ^" T: Z! }% q6 z
  18.                         case 0:
    ; y* e3 G* S- i2 Z9 A0 g
  19.                                 for(int i=0;i<2;i++)
    $ a. Y4 J& v! E6 v, B. H
  20.                                 {+ U$ a' m" \7 ]$ e; g; f, G( N) U1 [
  21.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯
    . ~: t9 l  b8 v8 }, |4 `7 B, B& }
  22.                                         HAL_Delay(1000);//延迟1s3 y% s0 E6 h  m( J
  23.                                         key=0;) R. Z: r* F7 e9 W# q
  24.                                 }
    4 ]/ W& d! O" H; r/ [6 ?
  25.                                 break;
    # R$ Y& Y! c6 b. H
  26.                         case 1:( \: E" x4 G3 k! @* g3 A! C8 R
  27.                                 for(int i=0;i<4;i++)
    ) v1 {( k5 y1 Q: s
  28.                                 {
    # B& b4 J1 P) E- B
  29.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯3 p8 L7 Z/ `" Q" Y$ W
  30.                                         HAL_Delay(500);//延迟1s
    1 h# }$ e" z7 ~
  31.                                         key=0;
    4 }" F; ?4 @5 v2 e% Z! J2 r
  32.                                 }* J5 u- @: T) ^* ~" }# f! p& j
  33.                                 break;
    1 e' J/ T) X& C3 e
  34.                         case 2:6 P, P" z! x* }
  35.                                 for(int i=0;i<8;i++)9 s  s$ M8 z1 K8 o" t
  36.                                 {
    ; \' m1 {6 E4 @/ W0 t
  37.                                         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);//翻转LED灯
    ) O* r) a+ V( {7 u: ?9 f
  38.                                         HAL_Delay(250);//延迟1s
    % v5 w( ~3 i2 f/ N6 [
  39.                                         key=0;, J- k+ K, ^, ]& a, o9 s# b' I
  40.                                 }4 w# t: t, ~. V
  41.                                 break;; {6 w$ Z* a- s
  42.                         default:break;: u4 @3 G5 m/ X; Z$ E: D
  43.                         }
    $ Z7 r/ @1 U: C8 z9 f7 {. B' J
  44.                         time++;
    ) s! u! M  O. G8 a- }
  45.                         if(time==3)2 q( [5 ^8 B# @2 Y9 i* f
  46.                                 time=0;
    0 L* x8 K9 h* U9 B
  47.                 }7 n  U" o/ Y6 x( ^. C) Q
  48.                 /* USER CODE BEGIN 3 */9 t9 [4 i  U2 d, Q# u
  49.         }
    1 c! U7 q( ]; u+ F& _4 i, u
  50.         /* USER CODE END 3 */
    + g. Y9 J8 j1 V  b$ N
  51. }* D  M1 \" I  Y2 y9 K- a5 M
复制代码

% B; s3 ~. l+ a  I: u4 实现结果
# K6 L2 |% V& A9 P+ ~上电后LED灯常亮,当有按键按下时,LED翻转状态。黑色按键是复位键Reset,蓝色按键是用户按键(PC13 Button)。
0 ~6 z+ r. F. ?" _+ K$ I3 \
# m$ c# m8 k* d 20200408211643400.gif
4 G8 z" t; {( i
+ h8 I# \; I+ K3 W1 Q' W% HTips:在使用中断时请务必配置好gpio的上下拉,若为下降沿触发,则配置为上拉。若为上升沿触发,则配置为下拉。否则有可能导致中断不可用。+ j7 t% [6 ~( V3 Q3 O% E3 J- G$ u# q
& x6 l# V) Q* a1 M
6 l1 d8 A$ e3 T( `- H9 m
8 I9 w; f# v5 v9 o% w0 I% q
收藏 评论0 发布时间:2022-5-5 17:53

举报

0个回答

所属标签

相似分享

官网相关资源

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