STM32 GPIO【深度理解】

文章目录

开始GPIO进阶学习吧


📖理论

对于输出电压,GPIO最大只能输出3.3V,因为系统供电是3.3V。

对于输入电压,STM32中部分引脚能够持续承受5V电压。数据手册中, 标注FT的引脚就能够承受5V电压。


图 1:STM32引脚定义


图 2:GPIO结构图

  1. 保护二极管:当瞬间电压进入I/O引脚时,若此电压大于VDD(3.3V),则上方的保护二极管导通。

    ​ 当瞬间电压小于VSS(0V),下方保护二极管导通。

    ​ 若输入电压在0~3.3V之间,那么2个二极管均不会导通。

    此结构只能抵御一瞬间的电压波动,长时间高电压接入I/O口依旧会损坏芯片。

  2. 上拉/下拉电阻输入 :为悬空的输入引脚提供一个默认的稳定电平

    上拉 (P-UP) : 内部电阻将其连接到 VDD,使默认电平为高电平。

    下拉 (P-DOWN) : 内部电阻将其连接到 VSS,使默认电平为低电平。

  3. 施密特触发器/TTL肖特基触发器:电压比较器,有效消除输入信号中的噪声和抖动。高于上限输出高,低于上限输出低。

  4. 输入数据寄存器-IDR Input Data Register:存储施密特触发器输出的电平值(0或1),CPU 通过读取IDR得知引脚电平。

  5. 输出数据寄存器-ODR Output Data Register):存储引脚期望的输出电平,ODR 的值会直接控制P-MOS 和 N-MOS,CPU 读取 ODR👉 读取"期望的输出值",而非"引脚的实际电平"。

  6. 位设置/清除寄存器-BSRR Bit Set/Reset Register:快速地设置或清除 ODR 中的某一位。

  7. N-MOS和P-MOS

    ​ 在推挽模式下,STM32对IO口输出有绝对的控制权

    ​ 输出数据寄存器为1,P-MOS激活,N-MOS断开,输出接入VDD,输出高电平;

    ​ 输出数据寄存器为0,P-MOS断开,N-MOS激活,输出接入VSS,输出低电平;

    ​ 在开漏模式下,P-MOS管失效,只有N-MOS管工作

    ​ 输出数据寄存器为1,P-MOS无效,N-MOS关闭,GPIO引脚处于"高阻态",输出电压由外部电路决定。

    ​ 输出数据寄存器为0,P-MOS无效,N-MOS导通,输出接入VSS,输出低电平;

    🔍"高阻态":就是悬空,既不是高电平,也不是低电平,引脚上的电压未定义,易收到电磁信号的干扰。



图3: GPIO模式 (具体看STM32参考手册)


🚀实战


图 4:RCC 外设时钟使能函数

​ 在STM32内部为了省电,所有外设(GPIO、USART、TIM...)默认是"关机"状态,即时钟被关闭。第一步永远是打开这个部门的电源(时钟)。


图 5:GPIO 配置与操作函数


💡补充

  1. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

GPIO_Init(GPIOA , &GPIO_InitStruct) 为什么第一个参数实际填写GPIOA而不是&GPIOA

stm32f10x.h 头文件中,有这样一行定义:#define GPIOA ((GPIO_TypeDef *) 0x40010800)

所以 GPIOA 本身已经是一个指针,它不是一个变量,而是一个宏定义 ,它代表的就是一个地址。

  1. 这些参数在stm32f10x_gpio.h头文件搜索

图 6:GPIO初始化结构体


图 7:GPIO模式


图 8:GPIO引脚宏定义

  1. GPIO_InitStruct.GPIO_Pin

    GPIO_Pin是``GPIO_InitTypeDef结构体中被定义为uint16_t` (无符号16位整数),是一个 16位 的"坑"。

  2. C语言编译器默认0x0001 这样的数字当作 int (标准整数)。在STM32中int32位 的。

  3. 问题 (类型不匹配):16位 ≠ 32位

    编译器会发出警告:"你正把一个 32位 的值塞进一个 16位 的坑里,这不安全!"

  4. 解决方法 (强制类型转换):(uint16_t)

    (uint16_t) 是一个C语言语法,意思是"请把后面的数字强制当作16位处理"。

  5. 最终结果:16位 = 16位

    赋值变成了 uint16_t = uint16_t,类型完美匹配,编译器不再警告。


图9:GPIO 寄存器地图 (GPIO_TypeDef)

STM32 寄存器地址与C语言

  1. 核心原理: STM32中每一个硬件寄存器 (ODR, IDR...)都对应一个固定的物理内存地址 。CPU 通过读写固定的物理内存地址来控制硬件(寄存器)。

  2. 基地址 (Base Address):

  • 每个外设 (如 GPIOA)都有一个起始地址。
  • GPIOA 基地址 = 0x40010800
  • GPIOB 基地址 = 0x40010C00
  1. GPIO_TypeDef 结构体:
  • 它是一个C语言的 "地图"定义了 GPIOA 内部所有寄存器(CRL, CRH, IDR, ODR...)的排列顺序和偏移量
  1. 偏移地址 (Offset):
  • 寄存器在"地图"上相对于基地址的位置。
  • 因为寄存器大多是 uint32_t(4字节),所以偏移量是 0x00, 0x04, 0x08...
  • ODR 寄存器的偏移量 = 0x0C
  1. 绝对地址 (Absolute Address):
  • 绝对地址 = 基地址 + 偏移地址
  • 举例 (GPIOA 的 ODR): 0x40010800 (GPIOA 基地址) + 0x0C (ODR 偏移量) = 0x4001080C
  1. C 代码翻译:
    • C 代码: GPIOA->ODR = 0x0001;
    • GPIOA 是一个指向基地址 0x40010800指针 👉 #define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
    • ->ODR是C语言语法,告诉编译器去 GPIO_TypeDef 结构体"地图"上查找 ODR 的偏移量(0x0C)。
    • 编译器操作: 生成机器码,将 0x0001 这个值,写入到最终的绝对地址 0x4001080C

✅个人理解:STM32 正是利用了 struct 结构体能自动处理偏移量的特性,来满足了访问硬件寄存器时"基地址 + 偏移地址"的需求。

c 复制代码
GPIOA->ODR = 0x0001;

GPIOA :获取基地址 (0x40010800)。

>ODR:查找 ODR 成员对应的偏移地址 (0x0C)。

= 0x0001:将值 0x0001 写入到算出来的绝对地址 (0x40010800 + 0x0C = 0x4001080C) 中。


🎉代码

c 复制代码
int main(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	GPIO_ResetBits(GPIOA, GPIO_Pin_4); //等价于GPIO_WriteBit(GPIOA,GPIO_Pin_4,Bit_RESET);
}

⚠️ 注意:如果把GPIO_Mode改成GPIO_Mode_Out_OD开漏模式:GPIO_Mode_Out_OD (开漏输出) 只能拉低,不能拉高。所以只能用于低电平驱动的LED(LED接VCC)。

相关推荐
国科安芯3 小时前
核电厂执行器控制系统中的抗辐照MCU选型:为什么需要150krad(Si) TID指标?
服务器·单片机·嵌入式硬件·fpga开发·架构
云数据构建师3 小时前
TB62262FTAG芯片应用和设计电路图
单片机·嵌入式硬件·fpga开发
XINVRY-FPGA3 小时前
5CEFA9F23I7N Altera CycloneV E(Enhanced)FPGA
人工智能·嵌入式硬件·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
乄夜4 小时前
嵌入式面试高频!!!C语言(十四) STL(嵌入式八股文)
c语言·c++·stm32·单片机·mcu·面试·51单片机
编码追梦人11 小时前
从零入门嵌入式系统:核心概念 + 环境搭建 + 传感器实战
单片机·嵌入式硬件
椰壳也可12 小时前
06_作业基于CubeMx实现按键控制LED灯(裸机)(立芯嵌入式笔记)
笔记·stm32·学习
dqsh0613 小时前
树莓派5+Ubuntu24.04 LTS CH348 / CH9344 驱动安装 保姆级教程
linux·c语言·单片机·嵌入式硬件·iot
点灯小铭13 小时前
基于单片机的16位逐次逼近AD电路设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
猪八戒1.015 小时前
智能家居项目-搭建工程
stm32·智能家居