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

【经验分享】STM32控制GPIO完成点亮LED灯

[复制链接]
STMCU小助手 发布时间:2022-5-25 19:00
1. 什么是GPIO:( D5 B3 J' m/ e! D1 ?% F
GPIO(General-Purpose IO ports,通用输入/输出接口),用于感知外界信号(输入模式)和控制外部设备(输出模式)。  W% G. M7 W- z1 f% b$ {: m
STM32F103C8T6一共有48个引脚,除去电源引脚、晶振时钟引脚、复位引脚、启动选择引脚、程序下载引脚(大部分为最小系统必须引脚),剩下的则是GPIO引脚。
6 R+ ?$ K) n' ]0 A下图为STM32F103系列GPIO的基本结构,左侧连接MCU内部,中间上半部分为输入,中间下半部分为输出,右侧为MCU引出的外设I/O引脚。2 a- @' b  C- c

! n. R& G% P' @( L$ h. y %E)YA3FE%7L4T6Z9YE_9.png 6 g2 x3 a- o; {5 U: S2 i

0 S) ^1 p$ k, L5 u. K* b2. GPIO工作模式
8 P7 u0 W7 g1 @1 f# t7 {& h# }STM32F103系列的I/O引脚共有8种工作模式,其中输出模式有四种:推挽输出、开漏输出、复用推挽输出、复用开漏输出;输入模式有四种:上拉输入、下拉输入、浮空输入、模拟输入。  C' G4 h! ?  z6 J
1FIUO9A1RM`VI]1IY(Z4$(4.png $ D" O& K, \+ @+ Y$ H6 Y+ z* A

, |2 l* G0 b0 f& L4 e/ V( Y' b& @1. 推挽输出(Push-Pull,PP): J/ ?: \. F# T

$ A4 N( I, o0 g/ A推挽结构由两个MOS管按互补对称的方式连接,任意时刻总是其中一个三极管导通,另一个三极管截止。
- _# \. }% [0 t, o$ C! x* ]$ F如上图①所示,MOS管作为开关使用,“输出控制”向两个MOS管栅极加一定电压,P-MOS管源极和漏极之间导通,VDD经过P-MOS管的S->G->D输出,N-MOS管处于高阻态(电阻很大,近似开路),整体对外为高电平;“输出控制”取消向两个MOS管栅极施加电压,P-MOS管源极和栅极截止,P-MOS管处于高阻态,N-MOS管源极和漏极导通,整体对外为低电平。
' m# K( b; M. B4 \推挽模式,让“输出控制”变为了VDD/Vss输出,使得输出电流增大,提高了输出引脚的驱动能力,提高了电路的负载能力和开关的动作速度。( u' j- j% Q6 }, m$ C: [

1 @2 T) Y8 x' Y) E" ~; e2. 开漏输出(Open-Drain,OD)
- u. m9 q/ K  K" @% h
! W: i$ k3 E3 j开漏模式下,“输出控制”不会控制P-MOS管,“输出控制”只会向N-MOS管栅极加一定电压,两个MOS管都处于截止状态,两个漏极处于悬空状态,称之为漏极开路。“输出控制”取消栅极的施加电压,P-MOS管依旧处于高阻态,N-MOS管导通,整体对外为低电平。
8 r+ r- {" o6 C; x& h6 n6 M开漏输出模式可以等效将下图中灰色框的P-MOS管看作不存在。即该模式下只能输出低电平,若要输出高电平,则需要外接电阻,所接的电阻称为上拉电阻,此时输出电平取决于此时上拉电阻的外部电源电压情况,如下图中蓝色框的外部电路。
0 q! O; A/ P  R7 k- j# y$ ^: c5 Q
* G3 H  A( U) V* U! @6 w; s4 \ PC@21P$}@%M$`IUJZOFS_DE.png
6 h! m0 J+ S, g) x/ L" g2 F4 [
8 a9 F8 C' |* g. }" y. O推挽输出模式可以直接输出高电平,开漏输出模式需要外接上拉电阻才能输出高电平,但开漏输出拥有一些推挽输出不具有的特性:  H/ F$ k/ C6 v2 Y

. J8 L; v; B! z+ R9 f8 A1.利用外部电路驱动能力。如图 8.1.2 所示,“输出控制”只需要提供一个很小的栅极驱动电流,VCC 经过上拉电阻为外部负载提高驱动电流;2.实电平转换。推挽输出模式由VDD提供,即只能提供3.3V电平。使用开漏输出模式后,VCC可以为 5V,从而实现了电平转换的效果。, ^3 q# {5 y5 c$ F6 o2 G
3.方便实现“逻辑与”功能。多个开漏的引脚可以直接并在一起使用,统一接一个合适的上拉电阻,就可以实现“逻辑与”关系,即当所有引脚均输出高电平时,输出才为高电平,若任一引脚输出低电平,则输 出低电平。在I²C、SMBUS等总线电路中经常会用到。
- v4 u# B5 c! n( X9 X( f  `* Z/ j7 E0 R; \

* J4 b/ p* F/ d! A0 B/ y1 q- N3. 复用功能推挽/开漏输出(Alternate Function,AF)
" e# C  {+ j$ @+ {' _5 g
0 g% ?$ Z3 n) }( q) GGPIO引脚除了作为通用输入/输出引脚使用外,还可以作为片上外设(USART、I²C、SPI等)专用引脚,即一个引脚可以有多种用途,但同一时刻一个引脚只能使用复用功能中的一个。" d; \1 N) C1 c1 o+ ]
当引脚设置为复用功能时,可选择复用推挽输出模式或复用开漏输出模式,在设置为复用开漏输出模式时,需要外接上拉电阻。% x3 r! m) H) S' a! O. L0 X
" b4 j  ?% E$ X! C; T
4. 上拉输入模式(Input Pull-up)* h; t7 _' o! Q& }
如上图中②所示,VDD经过开关、上拉电阻,连接外部I/O引脚。当开关闭合,外部I/O无输入信号时,默认输入高电平。该模式的典型应用就是外接按键,当没有按键按下时候,MCU的引脚为确定的高电平,当按键按下时候,引脚电平被拉为低电平。0 D; P0 P" s( A. r, l
8 W" L+ m: u" q) R
5. 下拉输入模式(Input Pull-down)
- }  B9 X/ @( i; g! \如上图 中②所示,Vss经过开关、下拉电阻,连接外部I/O引脚。当开关闭合,外部I/O无输入信号时,默认输入低电平。. w" S! r' c+ d( y8 N

+ I' _7 ^+ {/ I& V. Z4 t/ @6. 浮空输入模式(Floating Input)
, k  e, W" ^. r% Q4 \9 F" w0 [如上图中②所示,两个上/下拉电阻开关均断开,既无上拉也无下拉,I/O引脚直接连接TTL肖特基触发器,此时I/O引脚浮空,读取的电平是不确定的,外部信号是什么电平,MCU引脚就输入什么电平。MCU复位上电后,默认为浮空输入模式。
; Y) o. q' p/ U* E* J) l. g! C. x6 D/ [* J& {6 L* {- W
7. 模拟输入模式(Analog mode)
. S8 _. a- `8 o" `如上图中②所示,两个上/下拉电阻开关均断开,同时TTL肖特基触发器开关也断开,引脚信号直接连接模拟输入,实现对外部信号的采集。
* m' m1 O  G5 M: V! n, _2 F4 ]  ^! d5 v, P0 ~
GPIO 输出速度3 r) O5 f# V0 r6 Y7 x: r
1.STM32的I/O引脚工作在输出模式下时,需要配置I/O引脚的输出速度。该输出速度不是输出信号的速度,而是I/O口驱动电路的响应速度。
! E0 O, {, d& e+ W. r6 y( m2.STM32提供三个输出速度:2MHz、10MHz、50MHz。实际开发中需要结合实际情况选择合适的相应速度,以兼顾信号的稳定性和低功耗。通常,当设置为高速时,功耗高、噪声大、电磁干扰强;当设备为低速 时,功耗低、噪声小、电磁干扰弱。
' n) c  k2 k7 [( F3.通常简单外设,比如LED灯、蜂鸣器灯,建议使用2MHz的输出速度,而复用为I²C、SPI等通信信号引脚时,建议使用10MHz或50MHz以提高响应速度。
' q7 ]2 o2 E. [) f
/ R; b# B( h2 I) Y  r8 m3. 硬件方面1 f% Q, n' P9 Z6 H

, t2 D, Z! j8 U; w1 `/ u% v 81faa0dc718f421bb15ce16f30100ea4.png + z4 V0 I2 m2 P! d

+ k8 y$ k0 ^1 Q$ h+ m6 u+ n( I  f常见LED灯(图片来源百问网)
/ y9 o) U* y) B! j' v8 I* A& ?" O6 q
319ee626bdc74581af12526d997915aa.png / h' E- Z2 g9 h) F" c& D

  J! r3 c1 y2 s7 J6 w. g* M4 W; G+ JLED灯原理图(图片来源百问网)
8 R  y4 r% I1 T* Z' \" U, c' P6 R
8 G7 A3 T- \- p( Y3 W# U9 n8 D4. 软件方面
2 z% g+ L7 U3 H+ H7 Z, i9 ddriver_led.h/ j0 M$ g- a9 }8 f+ l. Q
! m* Z' k# `% v8 k6 O
  1. #ifndef __DRIVER_LED_H
    , m# m' g$ N- V1 s6 V
  2. #define __DRIVER_LED_H
    / y- _" q+ }: f0 s2 _

  3. 0 Q* X4 ~; G5 ?* c0 u
  4. #include "stm32f1xx_hal.h"7 h4 z7 s. z+ Z" r' t$ j7 E

  5. $ x" _6 l2 z( q) C
  6. /*********************, F. j7 U6 x$ s
  7. * 引脚宏定义7 P/ S( \# S& O
  8. **********************/6 p/ R; z) B- v1 C9 S( R
  9. #define B_LED_GPIO_PIN        GPIO_PIN_14 F8 p- Y* t6 F$ d; `, c4 W
  10. #define B_LED_GPIO_PORT       GPIOA
    ' g  k3 }+ n; H3 S
  11. #define B_LED_GPIO_CLK_EN()   __HAL_RCC_GPIOA_CLK_ENABLE()
    $ u& i, G4 y/ N+ K% H! p. Y

  12. 9 y. {6 X) Y3 [! `4 ~( s* T2 f  X
  13. /*********************
    , B9 `2 N/ k/ ?# g
  14. * 函数宏定义+ I8 A; |6 ^1 r
  15. **********************/
    . Q& o* P7 ?. \# w1 t" y( v8 I
  16. /*2 ^! Z/ [9 b$ S  V  d$ j/ F& [
  17. * LED亮灭函数宏定义
    1 ?* b. e; v2 Z
  18. */
    : k2 i2 \! l5 m! K
  19. #define ON  GPIO_PIN_RESET
    0 C1 o- R8 M5 q' K# v, }
  20. #define OFF GPIO_PIN_SET
    / s* ^( o! ~# v; _
  21. # a9 S3 D3 S& [0 U5 V
  22. #define BLED(flag)        HAL_GPIO_WritePin(B_LED_GPIO_PORT, B_LED_GPIO_PIN, flag)     ; ]- X0 f1 }- c" S6 d# g4 |9 P
  23. 7 ]$ W8 A' J" t2 t' q8 a
  24. /*
    ( W7 o1 G+ Y; S
  25. *  函数名:void LedGpioInit(void)
      M8 F( [) ?" t4 b. T- B8 H
  26. *  输入参数:无
    - j( M$ Y+ ~5 f1 j% W) E- J
  27. *  输出参数:无
    9 t2 d+ Q5 @  ~4 A
  28. *  返回值:无
    : C- M+ `3 i: o) h# T0 T
  29. *  函数作用:初始化LED的引脚,配置为上拉推挽输出
    + d# F6 ]4 n( j; w) ^' |' c" h2 ~) u
  30. */& K8 q# h4 g; E: F. l7 c2 u
  31. extern void LedGpioInit(void);
    9 h+ b1 J) I; T, s7 E) K
  32.   D2 Q& s9 P! q- ^
  33. #endif0 b  Z! T; z' v" {# h% g3 v1 O
复制代码
+ p1 W7 `/ X, `4 d" C' x! |
driver_led.c  H+ A( H- q8 u! G" c3 ~* e8 ^

$ G# {8 l+ N  ]3 a% n6 L
  1. #include "driver_led.h"
    . l+ z' M( S3 c# t: d) b  O* g
  2. 3 e: _- s3 t$ U. f1 \0 V
  3. /*
    9 p7 J" q: F+ A( `. ~) }8 g2 R% u. E
  4. *  函数名:void LedGpioInit(void)
    ; w, z' e. ^& K9 I" K: N1 Z7 ^0 C
  5. *  输入参数:无, ^, U/ ]+ g1 a; p
  6. *  输出参数:无
    * t" R% h2 V. m' X: Z3 f
  7. *  返回值:无
      }, ~, k3 Y- Z5 `+ J/ m* Z
  8. *  函数作用:初始化LED的引脚,配置为上拉推挽输出
    ) w8 ~/ g! F7 ^1 U3 R, }: i8 V- X
  9. */
    " m2 ?7 l  E1 X. N9 h
  10. void LedGpioInit(void)
    7 D( v! B$ h2 V. l8 U# a' v
  11. {/ O% v$ Z6 S& N5 C$ [8 L& r
  12.     // 定义GPIO的结构体变量0 Q8 q; C1 ~* C  L) g
  13.     GPIO_InitTypeDef GPIO_InitStruct = {0};% }$ N5 r1 d- N+ f$ z! t* B) ?
  14.     // 使能LED的GPIO对应的时钟
      C* H( W- ~  N8 e5 c' @
  15.     B_LED_GPIO_CLK_EN();. N  y1 p7 j" q2 ?0 i0 S* |

  16. , T9 O2 g6 F+ ]/ |
  17.     GPIO_InitStruct.Pin = B_LED_GPIO_PIN;         // 选择LED的引脚' Z+ b: X% ?# }' f) r. a! T7 j: y; S
  18.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;   // 设置为推挽输出模式+ X2 f& a5 c) D/ r" b/ T( D
  19.     GPIO_InitStruct.Pull = GPIO_PULLUP;           // 默认上拉
    6 m! {, R6 k  ?
  20.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;  // 引脚输出速度设置为慢! S; z2 b# c: W/ F

  21. 0 {% t4 N; D" ^+ d/ b
  22.     // 初始化引脚配置
    9 P4 C, @: ]& b+ h
  23.     HAL_GPIO_Init(B_LED_GPIO_PORT, &GPIO_InitStruct);
    % m! X0 N' g5 F2 }2 e' y9 s1 z
  24. $ `, i) A9 k7 |9 {# c
  25.     // 默认LED灭:OFF-灭,ON-亮
    7 n+ Q/ B: b) [! s! c# [
  26.     BLED(OFF);
    % w2 }0 `7 [# ]9 t
  27. }
    % K! V; |* O& }) O& i
复制代码
0 [1 v7 H9 e" T% A3 o4 }. [/ a4 ]
main.c
, i9 y3 C5 J: i4 t. Q6 A4 q3 g/ T  B+ W* g0 D
  1. #include "main.h"$ q+ D) Q( C* N+ i+ g
  2. #include "driver_led.h"2 E3 W. n& l: ^. M1 N& F* G4 Z
  3. " @" w) d1 Y# d! b: t: d
  4. int main(void), ^' T$ @5 u% h" D* k6 [6 v. @) O
  5. {   
    $ t, i4 x" e+ k. M3 n
  6.     // 初始化HAL库函数必须要调用此函数" w0 S( O* j$ a' @, Z+ l9 N
  7.     HAL_Init();
    + D7 k: _; v' ]
  8.     // 系统时钟即AHB/APB时钟配置0 i' q7 L8 ]4 }, {  {8 f8 t
  9.     SystemClock_Config();  
    ' Y: o9 J5 Q  p! |0 T; ^: t
  10.     // 初始化LED
    / J- U' A1 Z6 A5 }: u) E7 B
  11.     LedGpioInit(); ( ?. A# V0 b# f  B$ e
  12.         // 循环闪烁
    9 _: b: N: W8 H4 y
  13.     while(1)  Q* Z$ |# w+ W# t2 H' ?/ H6 o
  14.     {+ _: j- P# r  q4 W; g$ q' a, X
  15.         BLED(ON);
    . r* ]6 K# t# g# c* X, q0 Q
  16.         HAL_Delay(1000);# S4 Z" n# o$ k# a- i( ~
  17.         BLED(OFF);/ u9 F' m4 G2 W3 P8 j
  18.         HAL_Delay(1000);
    + b1 ~4 a/ z9 }8 e" v+ R
  19.     }
    ! I6 W4 V' C$ a7 |9 D. J
  20. }
复制代码

6 k* S6 }9 ^$ ^7 D4 P1 U; Z; n6 z( k1 ?5 V, h7 i
收藏 评论0 发布时间:2022-5-25 19:00

举报

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