
1 GPIO简介 GPIO,即通用I/O(输入/输出)端口,是STM32可控制的引脚。STM32芯片的GPIO引脚与外部设备连接起来,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。4 d4 g; P A- z+ S: t . t( @: `9 C- q/ [ STM32F407有7组IO。分别为GPIOA~GPIOG,每组IO有16个IO口,共有112个IO口 通常称为 PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中x为0-15。 并且F4系列是基于Cortex-M4内核 GPIO的复用:3 Q: @5 _ M, _4 }9 n STM32F4 有很多的内置外设,这些外设的外部引脚都是与 GPIO 共用的。也就是说,一个引脚可以有很多作用,但是默认为IO口,如果想使用一个 GPIO内置外设的功能引脚,就需要GPIO的复用,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。 比如说串口 就是GPIO复用为串口 2 GPIO的工作模式 1、4种输入模式 (1)GPIO_Mode_IN_FLOATING 浮空输入; v5 t+ s5 _( A9 c R" Q (2)GPIO_Mode_IPU 上拉输入 (3)GPIO_Mode_IPD 下拉输入" ~) T7 C/ Y( ?: b$ G (4)GPIO_Mode_AIN 模拟输入 2、4种输出模式 ( U4 z+ \7 D% e; p (5)GPIO_Mode_Out_OD 开漏输出(带上拉或者下拉) (6)GPIO_Mode_AF_OD 复用开漏输出(带上拉或者下拉)5 o, Y' a% U9 B4 a" Z (7)GPIO_Mode_Out_PP 推挽输出(带上拉或者下拉) (8)GPIO_Mode_AF_PP 复用推挽输出(带上拉或者下拉)3 l- Q, \8 T: t- H) r9 | 3、4种最大输出速度 (1)2MHZ (低速)+ h7 U/ o0 Z! j7 @- r9 T9 X, n (2)25MHZ (中速)6 S/ G; m% @ w8 F8 R (3)50MHZ (快速)4 u8 K2 F" M1 @! A5 n, P (4)100MHZ (高速)5 F4 p9 B# x+ D/ ]8 S8 P3 k W2 ? : |) F7 X$ W' O7 S) ?" h 关于他们的定义,都在 stm32f4xx_gpio.h 中,都为结构体形式的定义 9 q6 \: S# G! l" `2 X: X 3 GPIO框图剖析 - u! X+ T E' n% k/ [ ![]() ( A: T t- h D, T& Z4 L 我们所用到的每一个GPIO其内部结构都是这样,分别对应着GPIO的八种模式 这里我们简单的介绍下:$ I' S) f/ z8 a: m' S 保护二极管: IO引脚上下两边两个二极管用于防止引脚外部过高、过低的电压输入,当引脚电压高于VDD_FT时,上方的二极管导通,当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁 & F/ r0 ?& q! l7 `5 t& ?% k 上拉、下拉电阻:控制引脚默认状态的电压,开启上拉的时候引脚默认电压为高电平,开启下拉的时候引脚默认电压为低电平, h, Y( X) c7 k6 W TTL施密特触发器:基本原理是当输入电压高于正向阈值电压,输出为高;当输入电压低于负向阈值电压,输出为低;IO口信号经过触发器后,模拟信号转化为0和1的数字信号 也就是高低电平 并且是TTL电平协议 这也是为什么STM32是TTL电平协议的原因; J. M/ V9 Q' _0 D! v I5 z1 ~! M P-MOS管和N-MOS管:信号由P-MOS管和N-MOS管,依据两个MOS管的工作方式,使得GPIO具有“推挽输出”和“开漏输出”的模式 P-MOS管高电平导通,低电平关闭,下方的N-MOS低电平导通,高电平关闭 注: VDD_FT 代表IO口,兼容3.3V和5V,如果没有标注“FT”,就代表着不兼容5V 2 V1 f6 ?" U; G6 I 在芯片数据手册的引脚定义中,会看到有“I/O电平”一列 有FT即为支持5V " R0 O, f! x, G" ^! o# U ![]() 6 T9 {8 r l% _' ], S% B 4 GPIO的八种工作模式剖析: 浮空输入模式) j$ r4 H: W$ S3 O4 t1 H ! w# ~+ c* \! e$ }! K8 j: L ![]() 6 J# F! W( r! r: v4 G( d* u$ q' } 浮空输入模式下,I/O端口的电平信号直接进入输入数据寄存器。MCU直接读取I/O口电平,I/O的电平状态是不确定的,完全由外部输入决定;如果在该引脚悬空(在无信号输入)的情况下,读取该端口的电平是不确定的。 (接用电压表测量其引脚电压为1点几伏,这是个不确定值) 以用来做KEY识别0 j0 X1 b" j# y# M , ?4 e x) A" i- Y! C) i 上拉输入模式: c1 W, O! e( q' v/ `8 C4 b ![]() $ w, c4 {& D. d* s. o t+ Y; o IO内部接上拉电阻,此时如果IO口外部没有信号输入或者引脚悬空,IO口默认为高电平 如果I/O口输入低电平,那么引脚就为低电平,MCU读取到的就是低电平 ( X; @+ \' K4 X STM32的内部上拉是"弱上拉",即通过此上拉输出的电流是很弱的,如要求大电流还是需要外部上拉。 下拉输入模式 ![]() IO内部接下拉电阻,此时如果IO口外部没有信号输入或者引脚悬空,IO口默认为低电平 如果I/O口输入高电平,那么引脚就为高电平,MCU读取到的就是高电平 模拟输入模式 . B; X) ~6 L' L2 A# c& X ![]() 当GPIO引脚用于ADC采集电压的输入通道时,用作"模拟输入"功能,此时信号不经过施密特触发器,直接直接进入ADC模块,并且输入数据寄存器为空 ,CPU不能在输入数据寄存器上读到引脚状态 当GPIO用于模拟功能时,引脚的上、下拉电阻是不起作用的,这个时候即使配置了上拉或下拉模式,也不会影响到模拟信号的输入输出0 F" G. v7 C/ f8 R3 m2 | 7 B% i; w( ]- J) a 除了 ADC 和 DAC 要将 IO 配置为模拟通道之外其他外设功能一律 要配置为复用功能模式, 开漏输出模式(带上拉或者下拉) ![]() 0 g0 U; f# A- q5 {: h 在开漏输出模式时,只有N-MOS管工作,如果我们控制输出为0,低电平,则P-MOS管关闭,N-MOS管导通,使输出低电平,I/O端口的电平就是低电平,若控制输出为1时,高电平,则P-MOS管和N-MOS管都关闭,输出指令就不会起到作用,此时I/O端口的电平就不会由输出的高电平决定,而是由I/O端口外部的上拉或者下拉决定 如果没有上拉或者下拉 IO口就处于悬空状态 % I- x% z' N) L S5 H: A3 r 并且此时施密特触发器是打开的,即输入可用,通过输入数据寄存器GPIOx_IDR可读取I/O的实际状态。,I/O口的电平不一定是输出的电平 : j: m2 Q5 L+ m2 H9 m8 U* n ![]() 在推挽输出模式时,N-MOS管和P-MOS管都工作,如果我们控制输出为0,低电平,则P-MOS管关闭,N-MOS管导通,使输出低电平,I/O端口的电平就是低电平,若控制输出为1 高电平,则P-MOS管导通N-MOS管关闭,使输出高电平,I/O端口的电平就是高电平, 外部上拉和下拉的作用是控制在没有输出时IO口电平 3 k# S) s1 H" D( X/ l 此时施密特触发器是打开的,即输入可用,通过输入数据寄存器GPIOx_IDR可读取I/O的实际状态。I/O口的电平一定是输出的电平 ) E2 v6 o- X; g- T9 ~ 6 Y# m5 F4 D* M% R7 U1 s8 R 复用开漏输出(带上拉或者下拉) 8 z8 S. ~# u4 i ![]() ( w- |+ o) P" L; W GPIO复用为其他外设,输出数据寄存器GPIOx_ODR无效; 输出的高低电平的来源于其它外设,施密特触发器打开,输入可用,通过输入数据寄存器可获取I/O实际状态 除了输出信号的来源改变 其他与开漏输出功能相同' f) O# G1 r' @) v" y 复用推挽输出(带上拉或者下拉) ![]() GPIO复用为其他外设(如 I2C),输出数据寄存器GPIOx_ODR无效; 输出的高低电平的来源于其它外设,施密特触发器打开,输入可用,通过输入数据寄存器可获取I/O实际状态 除了输出信号的来源改变 其他与开漏输出功能相同, ^: ]( O9 g9 Q7 l+ g8 F4 ^ 开漏输出和推挽输出的区别: `4 B* v# }' S$ P$ T6 t 推挽输出: 可以输出强高低电平,连接数字器件 推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 4 g: I8 k) ]" ^3 t9 e T' p* N 开漏输出:" A4 g9 J, }; U# B7 O3 y; x # U6 C) A' H7 R5 X6 j3 I6 L; v6 e 可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极. 需要外接上拉电阻,才能实现输出高电平 合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内);1 d0 l5 S, d3 ^6 T5 X4 K 在使用任何一种开漏模式时,都需要接上拉电阻,否则只能输出低电平 ![]() 推挽输出电路: 其中IN端输出高电平时下面的PNP三极管截止,而上面NPN三极管导通,输出电平VS+;当IN端输出低电平时则恰恰相反,PNP三极管导通,输出和地相连,为低电平 * Q3 A; `" f4 p( A; `9 l 开漏输出电路:IN端输出低电平时,三极管导通,使输出接地,IN端输出高电平时,三极管截止,所以引脚既不输出高电平,也不输出低电平,为高阻态。为正常使用时必须接上拉电阻,8 z0 W& p/ W+ Z7 t# s9 y) g5 q2 U + d: w" o3 H) }. `4 Z 在STM32中选用IO模式: 1 V/ u; p6 Z% w9 p$ v 上拉输入、下拉输入可以用来检测外部信号;例如,按键等;4 `2 ]* T- E# R# g 模拟输入 ——应用ADC模拟输入,或者低功耗下省电 开漏输出一般应用在I2C、SMBUS通讯等需要"线与"功能的总线电路中。% Z4 a$ ?7 J) Q } 推挽输出模式一般应用在输出电平为0和3.3伏而且需要高速切换开关状态的场合。在STM32的应用中,除了必须用开漏模式的场合,我们都习惯使用推挽输出模式。 复用功能的推挽输出_AF_PP ——片内外设功能(I2C的SCL,SDA) 复用功能的开漏输出_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS) F4系列与F1系列区别:1 s1 b* V1 H1 t7 I5 j 本质上的区别是F4系列采用了Cortex-M4内核 而F1系列采用Cortex-M3内核; d7 F. ~, Z9 r4 `* \" G1 b ' @; M8 i( t, u% ^0 O F1系列(M3)IO口基本结构:- C4 E! R9 |- F5 E+ |/ e ![]() B" t# Z9 V5 i2 f$ Y0 r F4系列(M4)IO口基本结构:: R& B4 u$ [1 N ![]() F4系列设计的更加高级与人性化,他将外部上下拉电阻转移到了输出/输入驱动器外部,使得输出模式下也可以实现内部上拉与下拉,方便了用户的使用,增加了灵活性8 I" z& M d) i( b! h4 N 5 o# m- Q6 v, w; A1 i GPIO的初始化(F4) 这里我们以初始化LED为例/ Y$ ^" p' b8 _* O* w* D7 k 1.定义一个 GPIO_InitTypeDef 类型的结构体
![]() 5 G1 t) l. s2 u3 a& ?# h' j ; ^3 m# ]2 s" C4 s 2开启 LED 相关的 GPIO 外设时钟5 J6 ^9 o! K( Z" `2 V9 C8 o
Q:为什么要设置时钟?$ c' [. f* T: O9 V: K' e4 V# f4 j* } 任何外设都需要时钟,51单片机,stm32,430等等,因为寄存器是由D触发器组成的,往触发器里面写东西,前提条件是有时钟输入。stm32是低功耗,他将所有的门都默认设置为disable(不使能),在你需要用哪个门的时候,开哪个门就可以,也就是说用到什么外设,只要打开对应外设的时钟就可以, 其他的没用到的可以还是disable(不使能),这样耗能就会减少。 $ V2 ~7 n9 e7 T5 Z$ J5 N Q:为什么 STM32 要有多个时钟源呢? 1 M1 p7 n2 ~2 Q& b; x, { } 因为首 先 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率, 比如看门狗以及 RTC 只需要几十 k 的时钟即可。同一个电路,时钟越快功耗越大,同时抗电磁 干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。2 B( M- J! {( m" z8 N + O6 i3 c4 M8 E8 z& W 而相对应的外设功能所使用的时钟 在stm32f4xx.h 中即可查看到 * E& j& j8 k5 Z; R: f2 Y RCC_AHB1 ![]() RCC_APB1 ![]() 3选择要控制的 GPIO 引脚
可选引脚为0-15 一组IO口有16个引脚" G8 B/ T/ j! A9 D2 y E* X8 ~ L* f ![]() 4设置所选引脚的模式+ P# p2 w6 M. Q; }. D# N/ T
引脚的模式共有四种,分别为输入,输出,复用,和模拟模式$ [7 A- l- p7 z% B& v ![]() 3 M& b$ U* x1 J9 W 9 E- {/ g* m8 m) |: r% M! O- B 5 设定所选引脚的输出类型- V5 F6 W3 J0 P; m/ Q- j
输出模式有两种:推挽输出和开漏输出 # ^; v- q) Y7 M, S5 ` * n; f, ?# B7 | + c( d* z8 u9 K2 k2 k$ ~* A) } 只有输出模式才需要配置,输入模式下不需要配置: A' K K- a5 t" {: U + s8 e; b# r3 J @/ C: R% s, _3 j 6 设定所选管脚的速度
![]() N0 E3 e2 E" v2 v. @ 7 设定所选管脚的上拉与下拉
可设置为:上拉,下拉,与浮空; V" R2 g6 h9 }; ~ 6 X8 n& U" O( u% h. d6 a ![]() 8 Q& y" ~% c% }- q6 }. b) Y7 e 8初始化GPIO % c$ _: @, b: v1 D7 e
GPIO_Init() 是官方配置的初始化函数 第一个参数是GPIOX 第二个参数是结构体所对应GPIO各种参数的配置 3 i& R$ J5 s* f% W GPIO的初始化(F1) F4的初始化相较于F1系列有了很大的改变,在配置F1系列时,结构体只有三个参数 0 V; x9 \* E2 s- A GPIO_InitTypeDef 类型的结构体 * Z: N8 z2 u+ I ![]() 所选管脚的速度 ![]() 所选管脚的8种模式 * D2 b5 q9 w3 ^0 E( l ![]() : b# B# |8 ~0 e9 f 区别: ' q2 A' F: \% L. b F1(M-3)系列管脚速度只有三种模式 并且管脚的模式配置八种模式全部都在一起定义,直接设置即可9 a" f5 u2 ?9 }' [9 x" m 总归还是大同小异,不做过多介绍,看下下方配置即可
1 I( ~+ Z1 w( n5 u. w |