STM32 - GPIO详解
本文以STM32F40 为例进行讲解,其它雷同
1. GPIO简介
GPIO(general purpose input output,通用输入输出端口)
简单来说就是软件可控制的引脚:STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。
1)GPIO引脚分布图
如上图
- GPIO有 PA ~ PG + PH0、PH1 总共114个GPIO pin
- PA~PG:每组包含 16 个IO
2)STM32引脚分类
序号 | 引脚类型 | 引脚 | 备注 |
---|---|---|---|
1 | 电源 | VBAT、VDD、VSS、VDDA、VSSA,VREF+、VREF-等 | VBAT是备用电源 VDD和VSS是数字电源 VDDA和VSSA是模拟电源 VREF+和VREF-是参考电源。 |
2 | 晶振 | 主晶振IO、RTC晶振IO | |
3 | 下载&调试 | 用于JTAG下载的IO:JTMS、JTCK、JTDI、JTDO、NJRST | |
4 | BOOT | BOOT0、BOOT1 | 用于设置系统的启动方式 |
5 | GPIO | GPIOA ~ GPIOx | 专用器件接到专用总线,如I2C、SPI、SDIO、FSM、DCMI等总线需要接到专用的IO。 普通元器件(如蜂鸣器、LED灯、按键灯),使用普通的GPIO功能即可 |
Notice:商标中,1/2/3/4引脚类型,构成了嵌入式的最小系统
2. 端口配置
GPIO的基本电路结构如下:
2.1 基本部件
1)保护二极管
芯片的引脚电平0~3.3V,部分引脚可以5V,超过5V,将会对芯片造成损害。
如上图 ① 标识,主要是保护芯片免受外部输入电平过高或者过低的影响,进而保护整个芯片。
其原理为:
- 当输入电压高于VDD_FT,上面二极管导通,使得电压最大为VDD_FT
- 当输入电压低于VSS,上面二极管导通,使得电压最低为VSS
2)上拉/下拉电阻
用于输定输入电压
3)MOS管
用于实现推挽和开漏输出
4)施密特触发器
具有 稳压 和 滤波 的作用,就是让通过的电平输出稳定的高低电平
输入的电平往往存在着失真、不稳定、波动等,使用施密特触发器,可以过滤掉噪声干扰,最大限度的稳定输出电压
原理:
● 当电压大于正向阈值Vth,输出高电平
● 当输入电压低于阈值Vtl,输出低电平
● 当输入电平处于 Vtl ~ Vth 之间,输出保持不变
2.2 模式配置
GPIO 各个端口位分别配置为多种模式:
模式 | 性质 | 备注 |
---|---|---|
输入浮空 | 数字输入 | 可读取引脚电平 若悬空,则电平不确定 |
输入上拉 | 数字输入 | 可读取引脚电平 若悬空,则电平为高 |
输入下拉 | 数字输入 | 可读取引脚电平 若悬空,则电平为低 |
模拟功能 | 模拟输入 | GPIO无效 引脚直接接入内部ADC |
开漏输出 | 数字输出 | 可输出引脚电平 高电平为高阻态,低电平为Vss |
推挽输出 | 数字输出 | 可输出引脚电平 高电平接Vdd,低电平为Vss |
复用功能推挽 | 数字输出 | 由片上外设控制 高电平为高阻态,低电平为Vss |
复用功能开漏 | 数字输出 | 由片上外设控制 高电平接Vdd,低电平为Vss |
1)浮空、上拉、下拉 输入
输入模式下,输出被禁止,施密特触发器打开。
由于电阻阻值很大,因此这里的上拉、下拉输入都是弱上拉、弱下拉,为了不对外部输入产生很大的影响
上拉输入:给一个默认的高电平,当没有外部输入时,默认输入高电平
下拉输入:给一个默认的低电平,当没有外部输入时,默认输入低电平
悬空输入: 如果输入引脚啥都不接,此时输入电平极易受外界的干扰导致输入电平不确定,完全由外部的输入决定
2)模拟输入
该模式主要为片上外设ADC而配置,从外部读取模拟信号
对 I/O 端口进行编程作为模拟配置时:
● 输出缓冲器被禁止。
● 施密特触发器输入停用,I/O 引脚的每个模拟输入的功耗变为零。施密特触发器的输出被
强制处理为恒定值 (0)。
● 弱上拉和下拉电阻被关闭。
● 对输入数据寄存器的读访问值为“0”。
3)开漏、推挽 输出
对 I/O 端口进行编程作为输出时:
● 输出缓冲器被打开:
— 开漏模式:输出寄存器中的“0”可激活 N-MOS,而输出寄存器中的“1”会使端保持高组态 (Hi-Z)(P-MOS 始终不激活)。
— 推挽模式:输出寄存器中的“0”可激活 N-MOS,而输出寄存器中的“1”可激活 P-MOS。
● 施密特触发器输入被打开
● 根据 GPIOx_PUPDR 寄存器中的值决定是否打开弱上拉电阻和下拉电阻
● 输入数据寄存器每隔 1 个 AHB1 时钟周期对 I/O 引脚上的数据进行一次采样
● 对输入数据寄存器的读访问可获取 I/O 状态
● 对输出数据寄存器的读访问可获取最后的写入值
①. 推挽输出
-
当输出寄存器为高电平时,P-MOS导通,N-MOS截止,Vout=Vdd
-
当输出寄存器为高电平时,N-MOS导通,P-MOS截止,Vout=Vss
②. 开漏输出
-
当输出寄存器输出高电平,则引脚输出高阻态
-
当输出寄存器输出低电平,则引脚输出低电平
4)复用输出
对 I/O 端口进行编程作为复用功能时:
● 可将输出缓冲器配置为开漏或推挽
● 输出缓冲器由来自外设的信号驱动(发送器使能和数据)
● 施密特触发器输入被打开
● 根据 GPIOx_PUPDR 寄存器中的值决定是否打开弱上拉电阻和下拉电阻
● 输入数据寄存器每隔 1 个 AHB1 时钟周期对 I/O 引脚上的数据进行一次采样
● 对输入数据寄存器的读访问可获取 I/O 状态
以串口为例:
-
串口的发送引脚TX
-
串口的接收引脚RX
3. 寄存器
对GPIO的控制,实际上就是对寄存器的读写,不同的配置,产生不同的功能。
GPIO含有10中寄存器:
● 4 个 32 位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR 和 GPIOx_PUPDR)
● 2 个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR)
● 1 个 32 位置位/复位寄存器 (GPIOx_BSRR)
● 1 个 32 位锁定寄存器 (GPIOx_LCKR)
● 2 个 32 位复用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)
1)GPIO 端口模式寄存器 (GPIOx_MODER) (x = A..I)
GPIO port mode register
偏移地址:0x00
复位值:
● 0xA800 0000(端口 A)
● 0x0000 0280(端口 B)
● 0x0000 0000(其它端口)
2) GPIO 端口输出类型寄存器 (GPIOx_OTYPER) (x = A..I)
GPIO port output type register
偏移地址:0x04
复位值:0x0000 0000
3) GPIO 端口输出速度寄存器 (GPIOx_OSPEEDR) (x = A..I/)
GPIO port output speed register
偏移地址:0x08
复位值:
● 0x0000 00C0(端口 B)
● 0x0000 0000(其它端口)
4) GPIO 端口上拉/下拉寄存器 (GPIOx_PUPDR) (x = A..I/)
GPIO port pull-up/pull-down register
偏移地址:0x0C
复位值:
● 0x6400 0000(端口 A)
● 0x0000 0100(端口 B)
● 0x0000 0000(其它端口)
5) GPIO 端口输入数据寄存器 (GPIOx_IDR) (x = A..I)
GPIO port input data register
偏移地址:0x10
复位值:0x0000 XXXX(其中 X 表示未定义)
6) GPIO 端口输出数据寄存器 (GPIOx_ODR) (x = A..I)
GPIO port output data register
偏移地址:0x14
复位值:0x0000 0000
7) GPIO 端口置位/复位寄存器 (GPIOx_BSRR) (x = A..I)
GPIO port bit set/reset register
偏移地址:0x18
复位值:0x0000 0000
8) GPIO 端口配置锁定寄存器 (GPIOx_LCKR) (x = A..I)
GPIO port configuration lock register
当正确的写序列应用到第 16 位 (LCKK) 时,此寄存器将用于锁定端口位的配置。位 [15:0] 的
值用于锁定 GPIO 的配置。在写序列期间,不能更改 LCKR[15:0] 的值。将 LOCK 序列应用
到某个端口位后,在执行下一次复位之前,将无法对该端口位的值进行修改。
注意: 可使用特定的写序列对 GPIOx_LCKR 寄存器执行写操作。在此写序列期间只允许使用字访问 32 位长)。
每个锁定位冻结一个特定的配置寄存器(控制寄存器和复用功能寄存器)。
偏移地址:0x1C
复位值:0x0000 0000
访问:仅 32 位字,读/写寄存器
9) GPIO 复用功能低位寄存器 (GPIOx_AFRL) (x = A..I)
GPIO alternate function low register
偏移地址:0x20
复位值:0x0000 0000
10) GPIO 复用功能高位寄存器 (GPIOx_AFRH) (x = A..I)
GPIO alternate function high register
偏移地址:0x24
复位值:0x0000 0000
AF0-15到底代表什么意思呢,可见下图
4. 代码示例
1)GPIO配置
对GPIO的配置,其实就是根据寄存器功能列表,对寄存器进行配置。
//GPIO 通用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0X0000~0XFFFF,位设置,每个位代表一个 IO,
//第 0 位代表 Px0,第 1 位代表 Px1,依次类推.比如 0X0101,代表同时设置 Px0 和 Px8.
//MODE:0~3;模式选择,0,输入(系统复位默认状态);1,普通输出;2,复用功能;3,模拟输入.
//OTYPE:0/1;输出类型选择,0,推挽输出;1,开漏输出.
//OSPEED:0~3;输出速度设置,0,2Mhz;1,25Mhz;2,50Mhz;3,100Mh.
//PUPD:0~3:上下拉设置,0,不带上下拉;1,上拉;2,下拉;3,保留.
//注意:在输入模式(普通输入/模拟输入)下,OTYPE 和 OSPEED 参数无效!!
void GPIO_Set(GPIO_TypeDef* GPIOx, u32 BITx, u32 MODE, u32 OTYPE, u32 OSPEED, u32 PUPD) {
u32 pinpos=0,pos=0,curpin=0;
for(pinpos=0;pinpos<16;pinpos++) {
pos=1<<pinpos; //一个个位检查
curpin=BITx&pos;//检查引脚是否要设置
if(curpin==pos) { //需要设置
GPIOx->MODER&=~(3<<(pinpos*2)); //先清除原来的设置
GPIOx->MODER|=MODE<<(pinpos*2); //设置新的模式
if((MODE==0X01)||(MODE==0X02)) { //如果是输出模式/复用功能模式
GPIOx->OSPEEDR&=~(3<<(pinpos*2)); //清除原来的设置
GPIOx->OSPEEDR|=(OSPEED<<(pinpos*2));//设置新的速度值
GPIOx->OTYPER&=~(1<<pinpos) ; //清除原来的设置
GPIOx->OTYPER|=OTYPE<<pinpos; //设置新的输出模式
}
GPIOx->PUPDR&=~(3<<(pinpos*2)); //先清除原来的设置
GPIOx->PUPDR|=PUPD<<(pinpos*2); //设置新的上下拉
}
}
}
2)GPIO复用
USART的Rx和Tx,是复用了GPIO的引脚实现的,因此此处有必要介绍一一下GPIO引脚复用功能
//GPIO复用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0~15,代表IO引脚编号.
//AFx:0~15,代表AF0~AF15.
//AF0~15设置情况(这里仅是列出常用的,详细的请见407数据手册,56页Table 7):
//AF0:MCO/SWD/SWCLK/RTC AF1:TIM1/TIM2; AF2:TIM3~5; AF3:TIM8~11
//AF4:I2C1~I2C3; AF5:SPI1/SPI2; AF6:SPI3; AF7:USART1~3;
//AF8:USART4~6; AF9;CAN1/CAN2/TIM12~14 AF10:USB_OTG/USB_HS AF11:ETH
//AF12:FSMC/SDIO/OTG/HS AF13:DCIM AF14: AF15:EVENTOUT
void GPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8 AFx) {
GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4)); //复位该bit
GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4); //设置该bit的功能
}
- BITx>>3:在 MDK 里面,AFRL 和 AFRH 被定义成 AFR[2],其中 AFR[0]代表 AFRL,AFR[1]代表 AFRH。
- AFx<<((BITx&0X07)*4): 设置AF的复用功能到寄存器
因为GPIO在配置AF时候,分成了两组AFL(GPIO每组的[7..0]) & AFH(GPIO每组的[15..8])
BITx&0X07 : 假设bit为10,那么应该在AFH寄存器中的第3组
x4: 每组由4Bit组成
4. 附录
参考文档
- 施密特触发器:https://zhuanlan.zhihu.com/p/524399076
- STM32入门-GPIO端口的八种工作模式: https://blog.csdn.net/k666499436/article/details/123845466