文章目录
一、GPIO简介
- GPIO(General Purpose Input Output)通用输入输出口
- 可配置为8种输入输出模式
- 引脚电平:0V~3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等。
二、GPIO基本结构
-
模块组成:
-
模块组成:
- GPIO 端口(A/B 等):每个含 16 引脚(如 PA0PA15、PB0PB15),通过寄存器(配置模式、控制输出)和驱动器(硬件驱动引脚信号)实现功能。
- APB2 总线:连接 GPIO 与 CPU,负责高速数据 / 控制信号传输(双向箭头表示配置与状态反馈)。
-
功能逻辑:
- 配置:CPU 通过 APB2 总线写寄存器(如模式、速度),驱动器按配置驱动引脚(如推挽输出、上拉输入)。
- 数据传输:输出时寄存器→驱动器→引脚;输入时引脚→驱动器→寄存器,CPU 读取状态。
-
总线与外设关系:
GPIOA/GPIOB(图中示例)挂载于APB2 总线(高速总线,适用于高频外设),确保引脚配置和数据处理的高效性。
核心知识点:
- GPIO 架构:寄存器 + 驱动器 + APB2 总线,实现引脚的灵活配置(输入 / 输出模式、速度、电气特性)。
- APB2 作用:连接高速外设(如 GPIOA/B 在 STM32F10x 中通常为 APB2 外设,具体以手册为准),支撑 GPIO 的高速操作(如 50MHz 输出速度)。
- 引脚独立性:每个引脚(如 PA13、PB5)可独立配置,满足多外设(LED、按键、通信接口)的复用需求。
三、GPIO位结构
- 输入路径:
- 模拟输入:直接连接引脚,用于 ADC 采集(无施密特触发,避免数字噪声干扰模拟信号)。
- 复用功能输入:引脚作为片上外设(如 USART_RX)的输入,经TTL 肖特基触发器(施密特触发,抗噪声,将模拟信号整形为数字电平)后传输至外设。
- 通用输入:通过输入驱动器(含上拉 / 下拉电阻,可配置浮空、上拉、下拉模式),数据存入输入数据寄存器,供 CPU 读取。
- 输出路径:
- 通用输出:CPU 写输出数据寄存器,经输出控制模块(配置推挽 / 开漏模式),驱动 P-MOS(高电平)和 N-MOS(低电平)组成的输出驱动器,控制引脚电平。
- 复用功能输出:片上外设(如 USART_TX)直接控制输出驱动器,实现外设功能(需配置引脚为复用模式)。
- 保护电路:
引脚两端的保护二极管(接 VDD 和 VSS),防止静电、过压损坏芯片(ESD 保护)。 - 寄存器操作:
- 位设置 / 清除寄存器(BSRR):快速置位 / 复位引脚(原子操作,避免中断冲突)。
- 输出数据寄存器(ODR):存储引脚输出电平(0/1)。
- 输入数据寄存器(IDR):读取引脚输入状态(0/1,反映外部信号或内部外设输出)。
关键知识点(若为考点):
- 输入模式:
- 浮空输入(无上下拉,IDR 直接读取引脚电平,易受噪声影响)。
- 上拉 / 下拉输入(通过配置上下拉电阻,稳定输入电平,如按键检测)。
- 模拟输入(无施密特触发,专用于 ADC,禁止数字电路干扰)。
- 输出模式:
- 推挽输出:P/N-MOS 同时工作,高电平时 P-MOS 导通(接 VDD),低电平时 N-MOS 导通(接 VSS),驱动能力强(如 LED、电机控制)。
- 开漏输出:仅 N-MOS 工作,高电平时输出高阻态(需外部上拉电阻),适用于 I2C 总线(线与逻辑)或多设备共享总线。
- 复用功能:引脚映射到片上外设(如 SPI_CLK、USART_TX),需配置为复用模式,由外设直接控制输出驱动器(如 USART 发送数据时自动控制引脚电平)。
应用场景:
- LED 控制:推挽输出模式(GPIO_Mode_Out_PP),直接驱动 LED(低电平点亮时用 GPIO_ResetBits,高电平用 GPIO_SetBits)。
- 按键检测:上拉输入模式(GPIO_Mode_IPU),按键按下时引脚接地(IDR 读取 0),释放时上拉为 1。
- I2C 通信:开漏输出 + 上拉电阻(GPIO_Mode_AF_OD),实现总线的线与逻辑(多设备共享时钟 / 数据线)。
四、GPIO模式
通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式
模式名称 | 性质 | 特征 |
---|---|---|
浮空输入 | 数字输入 | 可读取引脚电平,若引脚悬空,则电平不确定 |
上拉输入 | 数字输入 | 可读取引脚电平,内部连接上拉电阻,悬空时默认高电平 |
下拉输入 | 数字输入 | 可读取引脚电平,内部连接下拉电阻,悬空时默认低电平 |
模拟输入 | 模拟输入 | GPIO无效,引脚直接接入内部ADC |
开漏输出 | 数字输出 | 可输出引脚电平,高电平为高阻态,低电平接VSS |
推挽输出 | 数字输出 | 可输出引脚电平,高电平接VDD,低电平接VSS |
复用开漏输出 | 数字输出 | 由片上外设控制,高电平为高阻态,低电平接VSS |
复用推挽输出 | 数字输出 | 由片上外设控制,高电平接VDD,低电平接VSS |
-
浮空/上拉/下拉输入
-
模拟输入
- 开漏/推挽输出
- 复用开漏/推挽输出
五、LED和蜂鸣器
简介
- LED:发光二极管,正向通电点亮,反向通电不亮
- 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
- 无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
硬件电路
5.1LED灯闪烁
5.1.1接线图
5.1.2代码
#include "stm32f10x.h" // 包含STM32F10x系列设备的头文件
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA外设的时钟
GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO初始化结构体
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 配置GPIO模式为通用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // 配置要初始化的引脚为PA0
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 配置GPIO输出速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); // 应用初始化配置到GPIOA
GPIO_ResetBits(GPIOA, GPIO_Pin_0);// 将PA0引脚设置为低电平(点亮LED,对于大多数开发板上的LED是低电平点亮)
while(1) // 进入无限循环,保持程序运行
{
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);// 将PA0引脚设置为低电平
Delay_ms(500);// 延时500毫秒
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);// 将PA0引脚设置为高电平
Delay_ms(500);// 延时500毫秒
GPIO_ResetBits(GPIOA, GPIO_Pin_0);// 将PA0引脚设置为低电平
Delay_ms(500);// 延时500毫秒
GPIO_SetBits(GPIOA, GPIO_Pin_0);// 将PA0引脚设置为高电平
Delay_ms(500);// 延时500毫秒
GPIO_WriteBit(GPIOA, GPIO_Pin_0,(BitAction)0);// 将PA0引脚设置为低电平
Delay_ms(500);// 延时500毫秒
GPIO_WriteBit(GPIOA, GPIO_Pin_0,(BitAction)1);// 将PA0引脚设置为高电平
Delay_ms(500);// 延时500毫秒
}
}
5.2LED流水灯
5.1.1接线图
5.1.2代码
#include "stm32f10x.h"// 包含STM32F10x系列设备的头文件
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOC外设的时钟
GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO初始化结构体
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 配置GPIO模式为通用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All; // 配置要初始化的引脚为PC13
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 配置GPIO输出速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); // 应用初始化配置到GPIOC
GPIO_ResetBits(GPIOA, GPIO_Pin_0);// 将PC13引脚设置为低电平(点亮LED,对于大多数开发板上的LED是低电平点亮)
while(1) // 进入无限循环,保持程序运行
{
GPIO_Write(GPIOA, ~0x0001);//0000 0000 0000 0001 // PA0输出低电平,其他引脚高电平
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0002);//0000 0000 0000 0010
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0004);//0000 0000 0000 0100
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0008);//0000 0000 0000 1000
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0010);//0000 0000 0001 0000
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0020);//0000 0000 0010 0000
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0040);//0000 0000 0100 0000
Delay_ms(500);// 延时500毫秒
GPIO_Write(GPIOA, ~0x0080);//0000 0000 1000 0000
Delay_ms(500);// 延时500毫秒
}
}
在 STM32 的 GPIO 操作中,PortVal
是 GPIO_Write()
函数的参数,用于指定 GPIO 端口的全部 16 个引脚的输出值。以下是详细解释:
1. 参数含义
-
PortVal
(Port Value):一个 16 位无符号整数(
uint16_t
),每一位对应 GPIO 端口的一个引脚。
- bit0 → 对应 PA0(或 PB0、PC0 等,取决于调用函数时指定的端口)。
- bit1 → 对应 PA1,以此类推,直到 bit15 对应 PA15。
- 值为 1 表示引脚输出 高电平(逻辑 1);值为 0 表示输出 低电平(逻辑 0)。
2. 函数作用
GPIO_Write()
函数用于批量设置 GPIO 端口的所有引脚状态,例如:
GPIO_Write(GPIOA, 0x000F); // PA0~PA3输出高电平,PA4~PA15输出低电平
- 二进制表示:
0x000F
=0000 0000 0000 1111
,对应 PA0~PA3 为 1(高),其余为 0(低)。
3. 与其他引脚输出函数的对比
函数 | 作用 | 示例 |
---|---|---|
GPIO_Write() | 设置整个端口的 16 位值 | GPIO_Write(GPIOA, 0xFFFF); |
GPIO_SetBits() | 单独将某些引脚置为高电平 | GPIO_SetBits(GPIOA, GPIO_Pin_0); |
GPIO_ResetBits() | 单独将某些引脚置为低电平 | GPIO_ResetBits(GPIOA, GPIO_Pin_0); |
GPIO_WriteBit() | 单独设置某个引脚的值 | GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); |
优化:
// 依次点亮PA0~PA7(假设LED为低电平点亮)
for (int i = 0; i < 8; i++) {
GPIO_Write(GPIOA, ~(0x0001 << i)); // 每次仅第i位为0(低电平)
Delay_ms(500);
}
5.3蜂鸣器
5.3.1接线图
5.3.2代码
#include "stm32f10x.h" // 包含STM32F10x系列设备的头文件
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB外设的时钟
GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO初始化结构体
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 配置GPIO模式为通用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; // 配置要初始化的引脚为PB12
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 配置GPIO输出速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStruct); // 应用初始化配置到GPIOB
while(1) // 进入无限循环,保持程序运行
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);// 延时100毫秒
GPIO_SetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);// 延时100毫秒
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);// 延时100毫秒
GPIO_SetBits(GPIOB, GPIO_Pin_12);
Delay_ms(700);// 延时700毫秒
}
}