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

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

[复制链接]
STMCU小助手 发布时间:2022-5-25 19:00
1. 什么是GPIO:# T* @. H0 @" L7 |. U
GPIO(General-Purpose IO ports,通用输入/输出接口),用于感知外界信号(输入模式)和控制外部设备(输出模式)。: p+ \7 u/ J2 w* ]/ x
STM32F103C8T6一共有48个引脚,除去电源引脚、晶振时钟引脚、复位引脚、启动选择引脚、程序下载引脚(大部分为最小系统必须引脚),剩下的则是GPIO引脚。
7 N# A% c4 y2 u1 F+ ]2 W, `1 E下图为STM32F103系列GPIO的基本结构,左侧连接MCU内部,中间上半部分为输入,中间下半部分为输出,右侧为MCU引出的外设I/O引脚。
- s" _" d" c- V$ H- o: i8 N  E
$ x; y) ^  D+ Z0 W %E)YA3FE%7L4T6Z9YE_9.png
# X; G0 A" P5 N4 w& U: A& L. O" s' l1 Q( p% c  h
2. GPIO工作模式( N0 R. S- j% n4 ~/ r
STM32F103系列的I/O引脚共有8种工作模式,其中输出模式有四种:推挽输出、开漏输出、复用推挽输出、复用开漏输出;输入模式有四种:上拉输入、下拉输入、浮空输入、模拟输入。
/ B' D, M6 e0 O& {7 }; W( j0 a" d 1FIUO9A1RM`VI]1IY(Z4$(4.png 6 W; p1 T5 A0 c+ W
2 F. S+ o3 O; p% ^1 M8 n( a
1. 推挽输出(Push-Pull,PP)2 W9 Y$ Z5 l: D" G3 z: h- `5 S
5 y, r8 s1 n3 A# ~+ D1 j
推挽结构由两个MOS管按互补对称的方式连接,任意时刻总是其中一个三极管导通,另一个三极管截止。
& F4 f: ^# G# W( C/ [如上图①所示,MOS管作为开关使用,“输出控制”向两个MOS管栅极加一定电压,P-MOS管源极和漏极之间导通,VDD经过P-MOS管的S->G->D输出,N-MOS管处于高阻态(电阻很大,近似开路),整体对外为高电平;“输出控制”取消向两个MOS管栅极施加电压,P-MOS管源极和栅极截止,P-MOS管处于高阻态,N-MOS管源极和漏极导通,整体对外为低电平。. K- f; d( U# z- u+ `2 R0 F6 U
推挽模式,让“输出控制”变为了VDD/Vss输出,使得输出电流增大,提高了输出引脚的驱动能力,提高了电路的负载能力和开关的动作速度。2 F' \& H. g3 Z, w$ P

: `  H* b( f# T* {2. 开漏输出(Open-Drain,OD)% ~! l* j5 C* l! }+ P: S
" d: C" v5 k5 K) {" ~
开漏模式下,“输出控制”不会控制P-MOS管,“输出控制”只会向N-MOS管栅极加一定电压,两个MOS管都处于截止状态,两个漏极处于悬空状态,称之为漏极开路。“输出控制”取消栅极的施加电压,P-MOS管依旧处于高阻态,N-MOS管导通,整体对外为低电平。  o5 k' ^- z  s- n. S0 l, i
开漏输出模式可以等效将下图中灰色框的P-MOS管看作不存在。即该模式下只能输出低电平,若要输出高电平,则需要外接电阻,所接的电阻称为上拉电阻,此时输出电平取决于此时上拉电阻的外部电源电压情况,如下图中蓝色框的外部电路。
2 M! _' p/ S' G7 N
4 e7 u: _5 S  [0 z) I PC@21P$}@%M$`IUJZOFS_DE.png ! t" I+ U$ X7 x
2 m0 Z* u4 m2 O' G$ w5 b- Z! k
推挽输出模式可以直接输出高电平,开漏输出模式需要外接上拉电阻才能输出高电平,但开漏输出拥有一些推挽输出不具有的特性:
% P0 w. E, [) O8 s6 s# Y# K5 z) r$ g/ M! p0 ?
1.利用外部电路驱动能力。如图 8.1.2 所示,“输出控制”只需要提供一个很小的栅极驱动电流,VCC 经过上拉电阻为外部负载提高驱动电流;2.实电平转换。推挽输出模式由VDD提供,即只能提供3.3V电平。使用开漏输出模式后,VCC可以为 5V,从而实现了电平转换的效果。- Y( u/ y- _) v. \: {7 i
3.方便实现“逻辑与”功能。多个开漏的引脚可以直接并在一起使用,统一接一个合适的上拉电阻,就可以实现“逻辑与”关系,即当所有引脚均输出高电平时,输出才为高电平,若任一引脚输出低电平,则输 出低电平。在I²C、SMBUS等总线电路中经常会用到。, x3 i( a( L  o  A

5 g8 V* G4 G6 ]3 j" q- l6 I
5 H) ~+ b1 N  a7 |' w3. 复用功能推挽/开漏输出(Alternate Function,AF)) R7 c6 Q2 z, @, V' p/ ]* H! m; v

6 x7 V; p3 ]' t, dGPIO引脚除了作为通用输入/输出引脚使用外,还可以作为片上外设(USART、I²C、SPI等)专用引脚,即一个引脚可以有多种用途,但同一时刻一个引脚只能使用复用功能中的一个。/ c. C/ ^- R3 \* y/ f& d7 f6 J: ?
当引脚设置为复用功能时,可选择复用推挽输出模式或复用开漏输出模式,在设置为复用开漏输出模式时,需要外接上拉电阻。
" R8 [9 P8 {9 {! D. V. w& w  n- A* p! y& H
4. 上拉输入模式(Input Pull-up)2 D2 y* ]. ?7 g2 H5 e8 |0 }$ G' A
如上图中②所示,VDD经过开关、上拉电阻,连接外部I/O引脚。当开关闭合,外部I/O无输入信号时,默认输入高电平。该模式的典型应用就是外接按键,当没有按键按下时候,MCU的引脚为确定的高电平,当按键按下时候,引脚电平被拉为低电平。# O# n9 Z. j8 J& t$ `2 H1 a

( F# {; E9 M2 V2 m+ X5. 下拉输入模式(Input Pull-down)
- [: W: @1 s# ]1 P% i5 X如上图 中②所示,Vss经过开关、下拉电阻,连接外部I/O引脚。当开关闭合,外部I/O无输入信号时,默认输入低电平。& m- @5 @! F0 `
0 w7 K: Z* H, T+ U
6. 浮空输入模式(Floating Input)6 b! O7 E$ }  v- A
如上图中②所示,两个上/下拉电阻开关均断开,既无上拉也无下拉,I/O引脚直接连接TTL肖特基触发器,此时I/O引脚浮空,读取的电平是不确定的,外部信号是什么电平,MCU引脚就输入什么电平。MCU复位上电后,默认为浮空输入模式。% w" T6 x9 R% f1 B0 Z

6 l7 A0 V0 t/ s5 t7 \  N2 w) K7. 模拟输入模式(Analog mode)
' g7 |( n" [2 F* k. V0 L如上图中②所示,两个上/下拉电阻开关均断开,同时TTL肖特基触发器开关也断开,引脚信号直接连接模拟输入,实现对外部信号的采集。" t" G  ~; A* r) y( S- M4 O
$ ~# l, V  e, o% G1 h. Y% n
GPIO 输出速度( `0 s( h/ b. R0 e; D0 U6 D+ A
1.STM32的I/O引脚工作在输出模式下时,需要配置I/O引脚的输出速度。该输出速度不是输出信号的速度,而是I/O口驱动电路的响应速度。% ^7 G2 f8 F2 ~! P! ^. I2 B, {  h
2.STM32提供三个输出速度:2MHz、10MHz、50MHz。实际开发中需要结合实际情况选择合适的相应速度,以兼顾信号的稳定性和低功耗。通常,当设置为高速时,功耗高、噪声大、电磁干扰强;当设备为低速 时,功耗低、噪声小、电磁干扰弱。) u! ~* V6 d; @4 A# @) W3 t8 F: B
3.通常简单外设,比如LED灯、蜂鸣器灯,建议使用2MHz的输出速度,而复用为I²C、SPI等通信信号引脚时,建议使用10MHz或50MHz以提高响应速度。
" a7 n' [8 s: {% T. [6 C0 ^6 ?- @* B- [. q* J) U" F* a
3. 硬件方面
* U0 F. f0 }5 G
3 ~1 ?9 o* G/ n  U 81faa0dc718f421bb15ce16f30100ea4.png # h/ [* O# C, P4 W- \: y

% R( t/ N' c# y5 p2 \0 z常见LED灯(图片来源百问网)
/ ]! R9 S9 {$ H. Y! s$ x. e9 U! J+ b* j- ~$ f4 P' k# Z8 S
319ee626bdc74581af12526d997915aa.png
7 c$ B' `* [% ?# O
: S3 T3 m0 k. \- a- H6 Z/ i1 G# tLED灯原理图(图片来源百问网)' o% u& ]& P) G2 {, z$ z
3 Q1 H+ ~! M6 W2 p) `# A2 r
4. 软件方面
4 \; v! o- M; }4 d4 R* @driver_led.h6 F( S$ Y, A! N: E7 _  N0 g. Y
: c: Y# G- ~$ D: w- }
  1. #ifndef __DRIVER_LED_H
    9 k$ O/ ?: u  V- N* T4 `7 t, G% {) J
  2. #define __DRIVER_LED_H
    # Q. r) T. I1 h
  3. " @- _6 ?4 E3 v: i+ n( O* x/ e* v4 {6 @
  4. #include "stm32f1xx_hal.h"0 F: h* E( S: M6 |( [% V3 h( d& O
  5. + X( }: I4 O7 y% q# T
  6. /*********************
    : x: v* J. }$ m4 L3 Y  }# |
  7. * 引脚宏定义8 M3 N6 d! l, c8 Y
  8. **********************/
    1 M% d: Y7 d4 E# M, H0 c0 d. `% b' w
  9. #define B_LED_GPIO_PIN        GPIO_PIN_13 [+ g( D1 {  l6 f/ D. v
  10. #define B_LED_GPIO_PORT       GPIOA- c# u( E  z' G% R0 N- n) A+ r* a( O
  11. #define B_LED_GPIO_CLK_EN()   __HAL_RCC_GPIOA_CLK_ENABLE()
    ! t5 P& f+ b3 p0 h$ A: j& ~+ b! ^
  12. 3 [' {" D" |& ^0 y4 N
  13. /*********************
    - n3 z! w; ]+ C- [
  14. * 函数宏定义
    , M6 B4 {3 D4 Y# r6 i/ [( E2 Y
  15. **********************/  e0 ?2 Q. W4 c+ u, j
  16. /*
    ; u: t) ]% v6 N% G4 Y
  17. * LED亮灭函数宏定义' c) d* M9 h9 P* _
  18. */; i) B) w6 c9 w. ?8 I
  19. #define ON  GPIO_PIN_RESET1 \% B" q4 A% g' x2 F0 B3 o1 p% c
  20. #define OFF GPIO_PIN_SET
    7 }7 W- C% l7 B* B$ ]0 E* A
  21. 0 e' s4 B" }6 ?( D/ J
  22. #define BLED(flag)        HAL_GPIO_WritePin(B_LED_GPIO_PORT, B_LED_GPIO_PIN, flag)     
    3 ~  y* N0 a6 J5 o6 f7 T

  23. 9 k7 k, n+ H5 k/ D3 H" ^
  24. /*
    9 {( T' k1 X! d9 i, ~' Q8 _
  25. *  函数名:void LedGpioInit(void)8 T/ u0 |+ g, P# j+ e3 F! \
  26. *  输入参数:无: F( e3 n5 P7 A+ l- M3 e$ b
  27. *  输出参数:无
    # {: v1 r+ O4 V* x& s  }
  28. *  返回值:无2 o4 _- J6 O2 h" Z3 \6 L( @
  29. *  函数作用:初始化LED的引脚,配置为上拉推挽输出
    0 m. j+ T& }3 m$ H9 P8 W
  30. */
    3 N  h8 l$ e! B: H$ ?+ s
  31. extern void LedGpioInit(void);6 L/ U; W3 U& ~& R! B

  32. $ E9 N' o9 A" V5 Z7 E) ?  H
  33. #endif
    5 c* C. t  `1 U# G
复制代码

' X! O' \/ v/ Wdriver_led.c
! B+ ]3 n: G7 G" m0 P: E7 \
: G! p- T& G( n# F7 p( z" _5 o$ K
  1. #include "driver_led.h"8 T7 d* Q, q& y: g8 F8 I2 {) Y

  2. + F. `; p  m# {' U2 v: q4 f6 ^/ b7 c
  3. /*
    ; f+ W: [0 I6 \1 o0 W3 Z
  4. *  函数名:void LedGpioInit(void)/ f$ Q+ R6 Y& y5 M5 N5 @. z' H" d" z
  5. *  输入参数:无$ R& g7 A* r% H3 H) n
  6. *  输出参数:无0 O; W2 j! Q+ `
  7. *  返回值:无, H1 r. m# M# Y% J4 }. N8 c4 s
  8. *  函数作用:初始化LED的引脚,配置为上拉推挽输出4 a* V5 O1 P- p7 D- U
  9. */& r4 ~, t' {* m+ S2 z5 {  b
  10. void LedGpioInit(void)
    ( J' s& Q; N. e) O0 H3 `# P& U
  11. {
    * W/ B0 Y& C; u& H- S5 |8 \
  12.     // 定义GPIO的结构体变量  e, N3 y+ @( ]. m+ {# b, @
  13.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    2 A9 ^5 |. o1 n0 u
  14.     // 使能LED的GPIO对应的时钟; e& Z4 K, B% z/ f) Z: K* C6 M, b
  15.     B_LED_GPIO_CLK_EN();0 `$ J* T- K2 N1 y8 g2 J

  16. / G& Z2 n( S' V9 D+ k! l6 |" a! u
  17.     GPIO_InitStruct.Pin = B_LED_GPIO_PIN;         // 选择LED的引脚4 @7 f: v. G4 y. b6 R" \
  18.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;   // 设置为推挽输出模式
    ) N) I; f( C2 p0 e) K( T- u
  19.     GPIO_InitStruct.Pull = GPIO_PULLUP;           // 默认上拉2 v. I) ~/ x4 @: s" d
  20.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;  // 引脚输出速度设置为慢
    6 _* T# O7 ], }- }0 Y$ b* P* a

  21. 4 F0 \  E5 e' D/ q# g5 I' m) ^
  22.     // 初始化引脚配置
    * }9 r- T: ~' A, O5 d; r
  23.     HAL_GPIO_Init(B_LED_GPIO_PORT, &GPIO_InitStruct);
    . e$ j! L1 W/ e3 y$ a
  24. ( p! s+ A0 W9 L7 M. M) U
  25.     // 默认LED灭:OFF-灭,ON-亮
    % K9 ^) I0 b9 O. Z! d+ T( I
  26.     BLED(OFF);0 ^1 c' n1 z1 o1 w2 B, X* \- v& ?/ c
  27. }
    ( s* R. [7 A* w, ?' ]
复制代码

7 ], O2 `! [" W$ Hmain.c: f) i( k! N& n7 h5 J2 i2 r  J
( L: q/ Y* q6 U* B' b7 z, p
  1. #include "main.h"
    : J2 r# X. ]) Z" @( q' L" v
  2. #include "driver_led.h"  r4 i, a4 C3 C( j2 m' Y( v5 Z/ C

  3. * r3 L- X: k+ g9 ]$ X9 N( [
  4. int main(void)
    ! ~6 B/ k4 ?" t/ l, F
  5. {    : E, C, I3 n- J7 Z
  6.     // 初始化HAL库函数必须要调用此函数
    2 o1 m' G4 j/ G0 b) q7 j
  7.     HAL_Init();
    + M. |8 z3 t! F# s  f& r5 M* M- g
  8.     // 系统时钟即AHB/APB时钟配置  u# ]* w, E8 B
  9.     SystemClock_Config();  / l7 a/ z  X9 }, B: `1 }: A
  10.     // 初始化LED: v0 K4 |9 e; n9 O, ^
  11.     LedGpioInit();
    * k( x* Q: w1 C
  12.         // 循环闪烁/ k: x, O. D( O1 J1 ~' _
  13.     while(1)7 a& k* \6 x7 i6 I) Z) R4 _% s
  14.     {
    2 @0 `2 d- p6 v2 A. ]7 e
  15.         BLED(ON);
    . R: _" K: e! V. |4 }
  16.         HAL_Delay(1000);
    * N& Z4 m1 u& o* Q1 o/ c5 c
  17.         BLED(OFF);
    # F6 |! ?( I- }3 V% J7 Y
  18.         HAL_Delay(1000);: n* v8 k  ^6 [  @2 ^& j7 h
  19.     }
    % e: {. N6 K: ^
  20. }
复制代码
0 X& q2 l2 W( D* f; {1 u1 q+ W* E
9 `( U1 y& R9 d/ Y+ ]1 _9 D
收藏 评论0 发布时间:2022-5-25 19:00

举报

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