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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了