STM32 GPIO详解
什么是GPIO
GPIO(General Purpose Input/Output)= 通用输入输出端口,就是单片机引脚。
- 输出:控制引脚输出高低电平(点亮LED、驱动蜂鸣器)
- 输入:读取引脚电平(检测按键、读取传感器)
STM32F103C8T6有37个GPIO引脚,分布在GPIOA~GPIOB(部分GPIOC),每个引脚都可以配置成多种模式。
GPIO的8种模式(☆)
核心模型:MOS 管 = 受电压控制的开关
输出模式(4种)
| 模式 | 特点 | 用途 |
|---|---|---|
| 推挽输出(Out_PP) | 能输出高也能输出低,驱动能力强 | LED、普通输出 |
| 开漏输出(Out_OD) | 只能输出低电平,高电平靠外部上拉 | I2C总线 |
| 复用推挽(AF_PP) | 引脚交给片上外设控制 | PWM、串口TX |
| 复用开漏(AF_OD) | 外设控制+只能输出低 | I2C(外设模式) |
输入模式(4种)
| 模式 | 特点 | 用途 |
|---|---|---|
| 浮空输入(IN_FLOATING) | 电平完全由外部决定 | 串口RX |
| 上拉输入(IPU) | 内部上拉,默认高电平 | 按键(按下接地) |
| 下拉输入(IPD) | 内部下拉,默认低电平 | 按键(按下接VCC) |
| 模拟输入(AIN) | 直接进ADC | ADC采集电压 |
GPIO结构框图
展示了 GPIO 内部从寄存器→驱动器→MOS 管→保护二极管的完整结构
推挽输出和开漏输出的区别
推挽输出
内部有两个管子(上管+下管):
- 写1:上管导通,引脚输出高电平(3.3V)
- 写0:下管导通,引脚输出低电平(0V)
优点:既能拉高也能拉低,驱动能力强。
开漏输出
只有下管,没有上管:
- 写1:引脚悬空(高阻),什么也不输出
- 写0:下管导通,引脚输出低电平
所以开漏输出必须外部接上拉电阻,高电平靠上拉电阻提供。
为什么I2C要用开漏?因为开漏模式多个设备可以线与,任何一个设备拉低,总线就是低电平,方便多个设备共享一根线。如果用推挽,高低都是强驱动,多个设备同时驱动会造成电源短路
GPIO配置
GPIO输出
使用推挽输出,可点亮小灯
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// 开时钟(☆)GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;// 推挽输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;// PA0GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;// 速度GPIO_Init(GPIOA,&GPIO_InitStructure);// 写入寄存器GPIO输入
上拉输入(按键检测)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;// 上拉输入GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_Init(GPIOA,&GPIO_InitStructure);按键电路核心规律
按键接哪边,就用"相反的那边"的上下拉。
- 按键接 GND → 配上拉 → 没按读 1,按下读 0
- 按键接 VDD → 配下拉 → 没按读 0,按下读 1
为什么按下读 0 还是 1?由电流流向决定:按下 = 引脚被"短接"到按键另一头连的电压。连 GND→0V→读0;连 VDD→3.3V→读1。
为什么要上/下拉电阻?没按时引脚悬空会乱跳,配电阻给个稳定的默认电平。
GPIO 控制函数
| 函数 | 作用 |
|---|---|
| GPIO_SetBits(GPIOA, Pin) | 引脚输出高电平 |
| GPIO_ResetBits(GPIOA, Pin) | 引脚输出低电平 |
| GPIO_WriteBit(GPIOA, Pin, Bit_SET/RESET) | 按参数输出高低 |
| GPIO_Write(GPIOA, 0x0001) | 一次写多个引脚 |
| GPIO_ReadInputDataBit(GPIOA, Pin) | 读输入电平 |
| GPIO_ReadInputData(GPIOA) | 读全部输入 |
时钟是什么
时钟是一个方波信号,时钟频率=每秒有多少个脉冲
为什么每个设备都需要开时钟?
STM32 所有外设默认都是关电的,要先用 RCC 开时钟给外设上电才能用。
- 不开时钟 → 外设不工作,写寄存器没用
- STM32 低功耗设计:不用外设就不给电
类比:电器要插电才能用,时钟就是电。
踩坑记录
| 问题 | 原因 | 解决 |
|---|---|---|
| 灯不亮 | LED低电平亮,写反了 | ON用ResetBits,OFF用SetBits |
| GPIO_WriteBit传1不亮 | 1≠GPIO_Pin_1(它=0x0002) | 传GPIO_Pin_1 |
| 引脚没反应 | 忘了开GPIO时钟 | RCC_APB2PeriphClockCmd |
| 按键读数乱跳 | 没配上/下拉,引脚悬空 | 配IPU或IPD |
总结
GPIO配置四步:开时钟 → 配模式 → 配引脚 → GPIO_Init写入寄存器。
输出用Out_PP,外设控制用AF_PP,输入按需选上拉/下拉/浮空。