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

【经验分享】HAL库 STM32CubeMX教程三----外部中断(HAL库GPIO讲解)

[复制链接]
STMCU小助手 发布时间:2022-3-24 23:52
前言
9 ?6 n& V+ q9 f7 B, {上一节我们讲解了STM32CubeMX的基本使用和工程的配置,那么这一节我们正式来学习CubeMX配置STM32的各个外设功能了
( b3 v3 k' n0 Y% H8 J: a. O( _0 R' c0 H+ _! e. t
今天我们会详细的带你学习STM32CubeMX配置外部中断,并且讲解HAL库的GPIO的各种函数,带你学习不一样的STM32( x3 ]: b" R& S1 b5 s- w/ V
6 y( [6 b" O) u2 G" ]6 l" k, M! Z
那么话不多说,我们开始正式的讲解吧!
+ x5 a: _. Q# b, g+ {8 Y1 b; e! d0 H$ S
4 l7 ]/ @$ K3 k: ?准备工作:
; j. T' b- S% e0 e7 L; I! V  g: e' d: |; b8 X6 D' E" h
1、STM32开发板(我的是STM32F407ZE和STM32F103RC)
! W$ P' w8 Z2 J1 q  l. C) m$ [4 `7 R# e/ y8 x2 H% J& n! Q
2、STM32CubeMx软件、 IDE: Keil软件
" |) }! }( y: z0 ?. Z
1 l. c* N: U/ [: V0 Y3、STM32F1xx/STM32F4xxHAL库  
' J' v1 e: |, D, f5 O
, K5 ~6 i: a/ m3 V) _) U+ q- o1 u4、按键管脚  PA11  PB4   % }1 ^9 x1 l: c' F
6 |9 o; ^* k# f" c& w
5   LED管脚 PC4 PC5 PB0 PB1
* B7 G  j! K" a
. v( r2 ^9 B! c3 u9 {1新建工程
1 R% I3 g7 P8 ]$ N  `' ^1.1New Project

  v$ T' ^; `) I/ }
# m! S  _- T# \ 20190809195826464.png 2 N4 m* C: g/ y" H4 h3 M

* o& i9 y8 H; J9 f1 搜索芯片型号9 p* C. N5 Q/ A3 C& f
2选择芯片( b$ z  v2 M: a3 i) x) w6 J" c5 }1 f
3创建工程
! I& c$ a7 L, Z. o: {& H1 ~/ E1.2设置RCC  
/ J+ ]7 F- y' T" p( m9 o- t7 ]6 A* ?5 R4 [( H/ c, o: O
20190809201413410.png ' J+ g) ~% Y- \. A) Q% {7 ], a4 O
6 \$ w- a. ?/ w( k
1 点击RCC/ h8 _% J: l/ H- d+ Z+ x5 g# I
2高速时钟(HSE)选择外部晶振
, B8 {4 `# L+ \& g3 X" _0 F% a3 软件自动配置管脚. z3 p$ w/ ^  o/ ]- x
  A. `8 x: H4 n- o7 e& Y% _0 b
1.3GPIO初始化
, c) K( R, M- m7 `
% P6 _: L0 G4 Q/ M) [' N6 g  i& NLED:4个GPIO_OUTPUT (输出模式)* C- b4 V! w, B2 N( w

2 P) t8 q7 g8 d7 P1 {4 d6 W) N按键:2个GPIO_EXITx(外部中断模式)
6 R: ?1 {) Y$ w( J. b, I
, D) p9 ~! ?3 O$ X# p  K2 ~ 20190809202500547.png ( E0 e( E5 L3 C( @& v& K
8 C8 k$ w: I" y5 P8 i
1 点击对应管脚1 v" o4 A% S! s0 R2 G4 \6 Y) D
2 设置对应模式
- Z9 S: o( K1 F" g$ c
# k0 L2 J) Q( d7 b9 ?$ nGPIO的各种模式设置
) T+ f5 N( b; ]4 p4 c- i% c0 d/ n# L. F0 w$ \) Y. \
20190809204340366.png
" o" a- ~! e! ~- h/ G. M' l4 F$ k  X! G6 t1 q
GPIO output level   引脚电平设置   高/低
: W7 N& [* n, T( ]# tGPIO mode   GPIO模式     推挽输出/开漏输出2 I" B% g& @) }% D0 O" q
GPIO Pull-up/Pull-dowm   上拉下拉电阻      上拉电阻/下拉电阻/无上拉或下拉
; F# U& j! |9 u! S: C; }Maxinum output speed   引脚速度设置   低速/中速/高速
$ k  Q# t% u; D7 ]' m% wUser Label    用户标签   给引脚设置名称  如LED0
) t6 B1 b& ?+ A. L+ [2 L4 X- H- M  E* |" b7 z4 i
这里可以看出看和我们使用库函数的时候配置是一样的,但我们只需要动几下鼠标便可以完成操作,这正是STM32CubeMX的强大之处* b7 u+ D) Q* k

2 W! ?! s7 S% J& r9 i/ @% g0 ~$ AGPIO_EXIT的6种模式
! M+ V9 R6 z9 S( U6 Y) {9 V7 a

7 u$ V6 O4 J" d( h, { 20190809204020820.png
$ _& y" e3 v. t+ e' o9 Q# h! q8 j) w( a% u# h9 B
我们的按键选择下降沿触发7 u2 Y: C: S  K: d
: q" {3 x4 s; M! [0 r
1.4设置NVIC(嵌套向量中断控制器)+ N1 n$ \. N: p2 j+ _. h
" D; p0 T4 {3 k
20190809205728173.png
# A! `/ p$ Y2 c8 t9 p5 f2 I3 `6 I: K  Q9 ?
1点击NVIC2 勾选EXIT Line- l5 p! c1 z- n4 t
2 interrupt 和 EXIT Line[15:12] interrupt 使能中断
  S; O- k, m1 e# Q' b
* T& h* k/ q* ]/ k1.5时钟源设置
$ C3 b% M  F9 U: F: _4 t# F, Y
+ z9 I; X# u* f3 S- e1 e 20190809211230663.png
5 ^4 [* E8 s9 ?# V; e+ O+ i% W
4 i! d% f8 j- I$ X5 @8 ?+ e1选择外部时钟HSE 8MHz   
# F0 e8 l; z. z- C; U. f" Z/ H2PLL锁相环倍频9倍
. [" h& v7 l2 @2 I4 @* U. G/ X3系统时钟来源选择为PLL
; B5 ~" _1 {, R. P4设置APB1分频器为 /2
5 D+ s3 B! |/ h: d32的时钟树框图  如果不懂的话请看《【STM32】系统时钟RCC详解(超详细,超全面)》
7 h& Z2 {0 N2 t: _3 L* X5 v* f( `
2 I0 a# Y# _; D, \. z6 `1.6项目文件设置  z7 y7 n9 X+ E
# ^" H+ r* v& `1 s  h* }8 X  [$ `
20190809210713570.png
' C% \$ W+ }! @. e  e7 N) {6 z$ k
& \* k1 s+ y/ r/ ^1 设置项目名称
5 t" U0 v; M+ o& k6 w2 N2 设置存储路径* p3 r/ i  d" j9 `+ T/ {+ R
3 选择所用IDE
; }" ^% S  {# ?) P3 q; y% e$ z; \) {# i* x/ O2 `5 j
2019080921100765.png " g5 }3 o1 B( O( B; u' i; G' u

/ V" j( I4 O& a+ s1.7创建工程文件8 q7 I8 o4 ^/ r* }- H$ |; v  l
# v! B% k: v$ |$ w& r
然后点击GENERATE CODE  创建工程
: w  u  @% g% m
, F2 `1 _( P5 R 20190809211414833.png % H/ t  Z4 |2 n+ y; t
/ T4 ~7 i4 g' u$ ~
随后我们可以在stm32f1xx_it.c中看到我们所配置的中断服务函数  并且可以看到gpio的初始化分到了gpio.c里面
' _  V% K( x/ U3 F
, I9 W7 A2 M) U! n% }' y 20190809212553423.png 7 J4 y/ g6 k& k) y5 u9 w* x
: _  S/ n% G1 ]
我们看到他有一个HAL_GPIO_EXTI_IRQHandler();函数) Z8 E+ ?' `4 l: _

$ O, P: i7 Q# U1 R0 |' a: iGo To Definition 查看一下函数代码
0 O1 U5 h6 ~: j. {; A/ V* L/ ^$ ^1 f4 {* f& D
20190810093650879.png , u+ O# a( I6 V- \& e7 y4 n
' M# m  W3 v! z
和我们库函数配置差不多,就是清除中断标志位,之后进入中断回调函数中* C, U+ g3 B' r, y) R+ w6 B: u

( A+ d0 s( O; }* G8 Y8 u在HAL库中,中断运行结束后不会立刻退出,而是会先进入相对应的中断回调函数,处理该函数中的代码之后,才会退出中断,所以在HAL库中我们一般将中断需要处理代码放在中断回调函数中,, j- f9 u2 j- `6 i5 ]
- h2 J. s8 \- O% W. z" g7 H" }
配置下载工具
, ?4 A8 @4 g- e- G2 @4 \新建的工程所有配置都是默认的  我们需要自行选择下载模式,勾选上下载后复位运行
/ w- j% [0 \& V6 u% ~" c; X# r
4 |' k, l$ T  V9 Z+ @- a 20190809172359875.png % c) i$ ?) j3 i0 _2 ^9 q# [7 r
) V3 s0 g% O2 M. r( K+ E: }7 H
所有自己编写的代码请放在/* USER CODE BEGIN XXX */   /* USER CODE END XXX */之间 6 {/ B2 O0 @( B

* t" i2 N% u) \& v4 q' R. g  `; b 这样我们修改工程的时候你自己写的代码就不会被删除
& `# f: z8 S5 K- K8 H, r+ F  I
+ s( X7 A9 o$ h# m% Y0 p: Z3 E 20190809175342848.png   P3 r% F0 ]: |- T: A2 X' N1 j. ~
9 l+ j" l5 E/ S) N# b. w
HAL库 GPIO函数库讲解
; @4 F( G+ X" l; d+ v' N# z( N- y在正常使用中,除了STM32CubeMX配置之外,我们有时候还需要自己配置一些东西,学习并理解HAL库,也是我们必须要学习的一个地方
/ J8 t! z0 G3 N$ H. P, N8 T2 |
1 x* X' L+ t/ r: F: P6 Y6 F" x首先打开stm32f4xx_hal_gpio.h  发现一共定义有8个函数
3 |+ k% D: U1 E, _
/ A7 F4 O  `# {
  1. void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);$ F$ s, C% j$ y8 k6 m: z( H
  2. void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);8 w+ m1 `! l; Z4 I+ \  Q' [
  3. GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    4 h9 I' w, [- p+ F+ x  {
  4. void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);# k8 I' U6 e! u# Z+ E
  5. void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    ! L( o( k5 f. j) H
  6. HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    9 j, x' @( G. ]/ p
  7. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);3 K& e3 U1 @4 y  R& `( |) W8 ~4 Z5 z( s
  8. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
复制代码
  1. void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
复制代码
1 v4 I5 y* r, `# }9 f4 W$ B

8 I* V/ Q9 X. f功能: GPIO初始化) G1 O5 f+ d8 b. U1 ]4 U4 A' O
5 E' s$ r( A3 N0 G. a% k
实例:HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  1. void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
复制代码
$ i. |/ o' }: c
功能:在函数初始化之后的引脚恢复成默认的状态,即各个寄存器复位时的值
: x# b+ O$ z1 L1 [% z7 K  p  U9 k) F  G( e9 ^  _  }# w
实例:HAL_GPIO_Init(GPIOC, GPIO_PIN_4);
# i' H3 d$ c% q& Z+ h0 W
4 O9 ]7 z- a( T2 F- C: O, A7 ~
  1. GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
复制代码

5 d' D/ ^5 X2 Y功能:读取引脚的电平状态、函数返回值为0或1) D, R/ w. a8 `" h7 [  `& ^

3 r$ W% T* t0 s, z2 ^# y实例:HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4);
) v% M$ e8 ^* h6 Z  f2 i
9 p/ g: D! [. N/ s% C
  1. void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
复制代码
/ }: p' P0 x5 q/ d8 l
功能:引脚写0或1
& r+ r5 c/ ~" m- [/ a7 I- v
' F. m5 e0 V) g" b* M# m! W6 ?实例:HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4,0);
' W7 g; x. f6 M  Q( G1 h9 P/ v, x/ z  H1 x" V' s) x
  1. void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
复制代码
  x1 H% i9 x2 W$ q' _
翻转引脚的电平状态   
6 D* K7 Z, z6 A/ z- u# d7 k' g9 g4 N2 O/ i( t9 g* }# L- w9 `
实例:HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_4);    常用在LED上
& e' A- j3 w# a2 M: ^9 Z) C; ]
1 z4 h/ K" H, |
  1. HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
复制代码

, ~) G6 I& \+ d功能:锁住引脚电平,比如说一个管脚的当前状态是1,当这个管脚电平变化时保持锁定时的值。
* F- s& {( e, J/ b+ k( v! g# A4 d1 @# d: Z+ u7 m
实例:HAL_GPIO_LockPin(GPIOC, GPIO_PIN_4);   
. V+ x6 S+ Q( P* a% [7 C' E) S' B# x$ V& G2 E2 t! R
  1. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
复制代码
6 U( e) v" A  @+ T% v
功能:  外部中断服务函数,清除中断标志位
& s, Z  H) G8 h8 v0 k: I" J$ v9 E9 V+ L
实例:HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);    + ^$ U7 K1 y4 K" ?1 G8 a
* b3 @4 p" m4 K1 D1 P2 E- ~
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
复制代码
! l4 t1 j! g: ?) I8 ^# `
功能:  中断回调函数,可以理解为中断函数具体要响应的动作。' i* H$ X4 j2 I6 P' g
4 X+ s$ g4 z; p( q$ r
实例:HAL_GPIO_EXTI_Callback(GPIO_PIN_4);   
8 k$ f9 g% ~8 p) b$ m5 F
0 x, ?# u  E! ]# J% e! b
& c4 E1 f+ j* A& S3 c5 i3 ZGPIO_InitTypeDef结构体定义
0 y! G9 B2 y' p8 q. z( F0 u- M$ s
7 Q# l2 G( G+ m7 X4 `/ {+ T
  1. typedef struct9 c' m6 u: x7 s% A" c- u4 G
  2. {: I$ M2 v0 h& v' N' s8 S
  3.   uint32_t Pin;       /*!<   选择引脚. r, c5 A7 I" i" m! k
  4.                            */4 s* h! W5 ?6 q( B: f- H
  5. 3 ?8 E$ o' P6 ?$ d# @6 c
  6.   uint32_t Mode;      /*!< 设置引脚模式
      ^8 s8 f4 L9 q
  7.                             */( G) f! a/ M# y% d
  8. . h/ Z2 @+ u' ~1 i
  9.   uint32_t Pull;      /*!< 引脚是否上拉或下拉
    , }; o; s6 e" g2 U' a
  10.                            */" K' q" M3 y, G1 G( s2 T

  11. 1 s2 h, j7 y+ F+ G& Z
  12.   uint32_t Speed;     /*!< 设置引脚速度
    , n) c$ y$ |! W# R( b/ Z8 |5 _- h
  13.                             */9 |. p4 p8 q7 n6 o8 b; y- {
  14. } GPIO_InitTypeDef;
复制代码

- q4 h6 A( [. `# ]同时,不管是标准库还是HAL库,都是基于寄存器开发的,寄存器编程在哪个库都是适用的$ K) Q! w  H8 t0 q, F
6 i7 O: {4 a& r/ g2 X4 f
GPIO的相关配置寄存器
0 V5 s/ h; \7 B* g/ PSTM32的每组GPIO口包括7个寄存器。也就是说,每个寄存器可以控制一组GPIO的16个GPIO口。这7个寄存器分别为:
+ g' P3 ~5 Y  P% e* t& s& u! R0 `% l4 w2 R
GPIOx_CRL:端口配置低寄存器(32位)) B2 ~+ x/ w/ l$ y
GPIOx_CRH:端口配置高寄存器(32位)
7 w8 B9 S# s7 E, nGPIOx_IDR:端口输入寄存器(32位)
( K  o7 h3 N5 z9 n4 UGPIOx_ODR:端口输出寄存器(32位)
4 a9 M! v7 ^7 x5 J# b5 y3 i- DGPIOx_BSRR:端口位设置/清除寄存器(32位)& I2 i5 z/ c5 |$ n& h
GPIOx_BRR:端口位清除寄存器(16位)
! _' y& c, ?  w* C, ], O0 b' sGPIOx_LCKR:端口配置锁存寄存器(32位). }3 ~. J7 W2 K6 v& Q! n
0 R& q$ t6 m2 b: o6 v+ y
具体我们这里就不讲了,篇幅有限,可以到《STM32中文参考手册》中查看/ M" @" y: H9 L+ R: f7 E6 R

% R' A% O7 d5 n: i关于GPIO的八种模式请参看 《STM32 GPIO八种模式及工作原理详解》, n( Z  L. l: ?, h& |
7 Q; {1 _! `3 D! f& _
按键消抖:
! l" m3 W! d( b
3 X  k; k/ v, J- T! A% i  F) F0 N1 R
  1. /**! T5 A( L( @7 ~' P( e
  2.   * 函数功能: 按键外部中断回调函数% ]& z8 U( D0 @3 g# z. {
  3.   * 输入参数: GPIO_Pin:中断引脚) c3 |7 J) ]) A: z* q# A1 }
  4.   * 返 回 值: 无& r. q6 v0 R) Y) I7 k3 J/ F2 f# }
  5.   * 说    明: 无! G$ J$ p* l; M2 w9 q0 x8 ?
  6.   */( D- a; p" H; z, z7 Q! D* f
  7. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    + x/ h4 W) l3 i! {2 T8 k$ i
  8. {
    3 Y- Y$ {& A$ l
  9.   if(GPIO_Pin==KEY1_GPIO_PIN)
    4 d- s  f) X+ O2 x
  10.   {
    2 M! A4 l, {$ @' K9 {9 M: r
  11.     HAL_Delay(20);/* 延时一小段时间,消除抖动 */
    8 i( G* ]6 g1 q! ]  {5 s6 w
  12.     if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL)
    & `( M: Z! U0 S  c8 L% A- Y3 U8 Y
  13.     {. B* ^$ O' F' ?3 @) u
  14.       BEEP_TOGGLE;
      [" z7 v) z, ], l) f; t
  15.       LED1_ON;+ R- }4 Y7 Y; v* S% ?7 l
  16.       LED2_ON;
    3 [( T7 c5 c6 V: T+ o
  17.       LED3_ON;$ s# A9 m4 j4 x# g2 d( ^
  18.     }
    ( U# r) _# S) s8 |, o( S" c. q
  19.     __HAL_GPIO_EXTI_CLEAR_IT(KEY1_GPIO_PIN);
    : z( {2 E7 l: Q3 {- \
  20.   }
    3 [6 u" s2 E! p  y
  21.   else if(GPIO_Pin==KEY2_GPIO_PIN)
    8 s0 X' r' s$ @# _& b) S2 L* g4 t
  22.   {
    9 Y1 ~! g8 J# u( B
  23.     HAL_Delay(20);/* 延时一小段时间,消除抖动 */3 }2 ]% m+ K; E+ }* d
  24.     if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL)6 S; W, k5 Q8 W6 M2 M! U
  25.     {3 b- Q. K' Q5 j' n" v
  26.       BEEP_TOGGLE;: b8 z$ m% ~9 R1 t
  27.       LED1_OFF;
    4 k: t' T+ |/ q3 E; v% v% P; T
  28.       LED2_OFF;
    2 t. z6 q, w+ t; Z& H
  29.       LED3_OFF;; ?* x0 h7 C! |/ m1 N
  30.     }& S, z- D. x# C" o9 t& e; ]1 @
  31.     __HAL_GPIO_EXTI_CLEAR_IT(KEY2_GPIO_PIN);
    * W  ~: T0 S9 X' F* a6 L( {5 e
  32.   }* c" r" @, G: h
  33. }
复制代码
0 j. r' Q2 x0 R) |% P; @6 D
! k; x0 y5 q, G, `. C: Q
赞 收藏 评论0 发布时间:2022-3-24 23:52

举报

0个回答

所属标签

相似技术帖

官网相关资源

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