PPT 参考图 -- GPIO简介与基本结构
graph TD
subgraph APB2_BUS
APB2["APB2 (72MHz)"]
end
subgraph GPIO_REG
CRL["CRL (配置低8位)"]
CRH["CRH (配置高8位)"]
IDR["IDR (输入数据)"]
ODR["ODR (输出数据)"]
BSRR["BSRR (位设置/复位)"]
BRR["BRR (位复位)"]
LCKR["LCKR (锁定)"]
end
APB2 --> GPIO_REG
GPIO_REG --> GPIO_PIN
PPT 参考图 -- GPIO位结构
graph LR
subgraph PIN_STRUCT
PAD["I/O Pad"] --> D1["保护二极管\nVDD"]
PAD --> D2["保护二极管\nVSS"]
D1 --> PULL_UP["上拉电阻\n(~40kΩ)"]
D1 --> PULL_DOWN["下拉电阻\n(~40kΩ)"]
PAD --> SCHMITT["施密特触发器"]
SCHMITT --> INPUT_REG["输入数据寄存器<br/>(IDR)"]
OUTPUT_REG["输出数据寄存器<br/>(ODR)"] --> DRIVER["输出驱动器"]
DRIVER --> MUX["复用功能输出"]
MUX --> PAD
OUTPUT_REG --> BIT_SET["位设置/复位<br/>(BSRR)"]
BIT_SET --> DRIVER
end
| 组件 | 作用 |
|---|---|
| 保护二极管 | 钳位电压,防止 VDD+0.3V / VSS-0.3V 烧毁 IO |
| 上拉/下拉电阻 | 约 30kΩ~50kΩ,固定空闲电平 |
| 施密特触发器 | 整形,防抖动,有滞后特性(VT+ ≈ 0.4VDD, VT- ≈ 0.3VDD) |
| 输出驱动器 | 推挽(Push-Pull) 或 开漏(Open-Drain) |
| BSRR | 原子操作,一次写同时设置和复位不同位 |
推挽输出(Push-Pull):输出驱动器由 PMOS(上管)和 NMOS(下管)组成。写入 ODR=1 时,PMOS 导通、NMOS 截止,引脚被拉至 VDD(高电平);ODR=0 时,PMOS 截止、NMOS 导通,引脚被拉至 GND(低电平)。输出高低电平均为低阻驱动,无需外接电阻。
开漏输出(Open-Drain):仅 NMOS 工作。ODR=0 时 NMOS 导通,引脚输出 GND(低电平);ODR=1 时 NMOS 截止,引脚呈现高阻态(Hi-Z),此时必须依靠外部上拉电阻将电平拉高至 VDD。因此开漏输出无法自身输出高电平,外部上拉电阻的阻值影响上升沿时间和总线功耗。
BSRR 原子操作:BSRR 寄存器分为低 16 位(BSx,置位)和高 16 位(BRx,复位)。一次写入可同时控制多路引脚:BSRR = (1 << pin_to_set) | (1 << (pin_to_reset + 16))。硬件在单个 APB2 时钟周期内完成所有操作,无需软件执行"读-改-写"序列,因此在多中断环境中不会出现竞态条件。
输出速度:配置 GPIO_Speed_2MHz/10MHz/50MHz 实际控制输出驱动器的压摆率(Slew Rate)。速度设置越高,输出波形的上升/下降沿越陡峭,信号完整性越好,但 EMI 辐射和功耗也越大。对于低频 GPIO(如 LED 控制),使用 GPIO_Speed_2MHz 即可,过高速度会引入不必要的噪声。
PPT 参考图 -- GPIO模式
| 模式 | GPIO_Mode | 结构特点 | 典型用途 |
|---|---|---|---|
| 模拟输入 | GPIO_Mode_AIN |
关闭施密特触发器,不接上/下拉 | ADC 采样输入 |
| 浮空输入 | GPIO_Mode_IN_FLOATING |
施密特触发,无上下拉 | 外部信号按键(需外部上拉) |
| 上拉输入 | GPIO_Mode_IPU |
施密特触发 + 上拉电阻 | 按键(GND导通) |
| 下拉输入 | GPIO_Mode_IPD |
施密特触发 + 下拉电阻 | 按键(VCC导通) |
| 推挽输出 | GPIO_Mode_Out_PP |
PMOS+NMOS, 高低电平 | LED, 蜂鸣器, 总线控制 |
| 开漏输出 | GPIO_Mode_Out_OD |
仅NMOS, 低=GND, 高=高阻 | I2C SDA/SCL, 电平转换 |
| 复用推挽 | GPIO_Mode_AF_PP |
外设驱动推挽输出 | USART TX, SPI SCK/MOSI |
| 复用开漏 | GPIO_Mode_AF_OD |
外设驱动开漏输出 | I2C(STM32做主控) |
| 速度宏 | 频率 | 适用场景 |
|---|---|---|
GPIO_Speed_2MHz |
2MHz | 低频,EMI 最小的通用 IO |
GPIO_Speed_10MHz |
10MHz | 常规通信 |
GPIO_Speed_50MHz |
50MHz | SPI/高速 PWM |
EMI 随速度增大而增大,不用高频时用
GPIO_Speed_2MHz即可。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
| GPIO_InitTypeDef 成员 | 取值 | 说明 |
|---|---|---|
GPIO_Pin |
GPIO_Pin_0 ~ GPIO_Pin_15 |
引脚号,支持 OR 组合 |
GPIO_Speed |
GPIO_Speed_2MHz / 10MHz / 50MHz |
输出速率 |
GPIO_Mode |
见上方 8 种模式 | IO 工作模式 |
| 函数 | 原型 | 说明 |
|---|---|---|
GPIO_SetBits |
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
指定引脚输出高 |
GPIO_ResetBits |
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
指定引脚输出低 |
GPIO_WriteBit |
GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) |
按 BitVal 输出 |
GPIO_Write |
GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) |
写整个 ODR |
GPIO_SetBits |
用 BSRR 实现,原子操作 | 推荐使用 |
PPT 参考图 -- LED、蜂鸣器与硬件电路
#include "stm32f10x.h"
#include "Delay.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 开启 GPIOC 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// PC13 - PC10 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// 初始全部熄灭 (板载 LED 低电平亮)
GPIO_SetBits(GPIOC, GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11 | GPIO_Pin_10);
Delay_Init();
while (1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // PC13 亮
Delay_ms(500);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
GPIO_ResetBits(GPIOC, GPIO_Pin_12); // PC12 亮
Delay_ms(500);
GPIO_SetBits(GPIOC, GPIO_Pin_12);
GPIO_ResetBits(GPIOC, GPIO_Pin_11); // PC11 亮
Delay_ms(500);
GPIO_SetBits(GPIOC, GPIO_Pin_11);
GPIO_ResetBits(GPIOC, GPIO_Pin_10); // PC10 亮
Delay_ms(500);
GPIO_SetBits(GPIOC, GPIO_Pin_10);
}
}
电路连接:PC9 → NPN (S8050) Base → 集电极接蜂鸣器负极 → 蜂鸣器正极接 3.3V。
#include "stm32f10x.h"
#include "Delay.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC, GPIO_Pin_9); // 关闭 (低电平截止)
while (1)
{
// 有源蜂鸣器: 高电平导通发声
GPIO_SetBits(GPIOC, GPIO_Pin_9);
Delay_ms(500);
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
Delay_ms(500);
}
}
| 开发板 | LED 引脚 | 电平 |
|---|---|---|
| STM32F103C8T6 蓝色板 | PC13 | 低电平亮 |
| STM32F103C8T6 红板(Mini) | PA1 | 高电平亮 |
| STM32F103ZET6 正点原子 | PD2 (DS0) / PG15 (DS1) | 低电平亮 |
| STM32F103VET6 野火 | PB5 | 低电平亮 |
GPIO_Speed_2MHz,过高速度引入 EMI 且增加功耗Out_OD 输出高电平必须加外部上拉电阻,否则读不到高电平GPIO_SetBits 底层用 BSRR — 比 GPIO_WriteBit(用 ODR)更安全BSRR[31:16]=BRx 复位, BSRR[15:0]=BSx 置位