1. GPIO基本概念
-
GPIO(General Purpose Input/Output):通用输入输出端口,是STM32微控制器与外部设备交互的重要接口。
-
功能:
-
输入模式:读取外部信号(如按键、传感器)。
-
输出模式:控制外部设备(如LED、电机)。
-
中断模式:检测外部信号的变化(如按键按下)。
-
复用功能模式:将GPIO引脚分配给外设(如USART、SPI)。
-
模拟模式:将GPIO引脚用作ADC或DAC的输入/输出。
-
2. GPIO端口结构
-
端口组:STM32有多个GPIO端口组(如PA、PB、PC等),每个端口组包含多个引脚(如PA0、PA1等)。
-
引脚配置:每个GPIO引脚可以配置为不同的模式(输入、输出、中断、复用功能等)。
-
主要寄存器:
-
GPIOx_MODER(模式寄存器):配置引脚模式(输入、输出、复用、模拟)。
-
GPIOx_OTYPER(输出类型寄存器):配置输出类型(推挽或开漏)。
-
GPIOx_PUPDR(上拉/下拉寄存器):配置内部上拉/下拉电阻。
-
GPIOx_ODR(输出数据寄存器):控制引脚输出电平。
-
GPIOx_IDR(输入数据寄存器):读取引脚输入电平。
-
3. GPIO配置模式
3.1 输入模式
-
浮空输入(Input Floating):
-
特点:引脚悬空,电平不确定,适合外部已有明确电平信号的场景。
-
应用实例:连接外部传感器(如光敏传感器)的输出信号。
-
-
上拉输入(Input Pull-up):
-
特点:内部上拉电阻将引脚默认拉高,适合需要默认高电平的场景。
-
应用实例:按键检测,按键按下时接地,释放时通过上拉电阻保持高电平。
-
-
下拉输入(Input Pull-down):
-
特点:内部下拉电阻将引脚默认拉低,适合需要默认低电平的场景。
-
应用实例:检测外部信号是否被拉高,例如检测外部设备的使能信号。
-
3.2 输出模式
-
推挽输出(Push-Pull Output):
-
特点:可以直接输出高电平或低电平,适合驱动负载。
-
应用实例:控制LED的亮灭、继电器的开关。
-
-
开漏输出(Open-Drain Output):
-
特点:输出低电平时有效,高电平需要外部上拉电阻,适合多设备共享引脚。
-
应用实例:I2C通信,多个设备共用SDA和SCL引脚。
-
3.3 复用功能模式
-
复用推挽输出(Alternate Function Push-Pull):
-
特点:引脚作为外设的推挽输出,适合高速信号传输。
-
应用实例:SPI通信中的SCK、MOSI引脚,USART的TX引脚。
-
-
复用开漏输出(Alternate Function Open-Drain):
-
特点:引脚作为外设的开漏输出,适合需要高阻态的场景。
-
应用实例:某些需要多设备共享的外设通信。
-
3.4 模拟模式
-
特点:引脚配置为ADC输入,适合采集模拟信号。
-
应用实例:温度传感器、光敏传感器的信号采集。
4. GPIO初始化(基于Keil)
4.1 使能GPIO端口时钟
使用RCC开启GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 启动GPIOA时钟
4.2 配置GPIO引脚
使用GPIO_Init函数初始化
GPIO_InitTypeDef GPIO_InitStructure;
// 配置GPIOA0为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 选择GPIOA的第0引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
4.3 设置输出电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // 输出高电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // 输出低电平
4.4 读取输入电平
GPIO_PinState pin_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
if (pin_state == Bit_SET) {
// 引脚为高电平
} else {
// 引脚为低电平
}
5. GPIO中断(基于Keil)
5.1 配置GPIO引脚为中断模式
GPIO_InitTypeDef GPIO_InitStructure;
// 配置GPIOA0为上拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置中断线和中断请求
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 选择中断线0
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能中断线
EXTI_Init(&EXTI_InitStructure);
// 配置NVIC
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 选择中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
NVIC_Init(&NVIC_InitStructure);
5.2 编写中断服务例程(ISR)
void EXTI0_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_Line0) != RESET) { // 检查中断标志
// 按键按下时的操作
EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
}
}
6. 常见问题
-
电平兼容性:确保外设的电平与STM32的GPIO电平匹配(如3.3V或5V)。
-
上拉/下拉电阻:根据实际需求选择内部或外部上拉/下拉电阻。
-
中断去抖动:按键等输入信号可能需要硬件或软件去抖动处理。
-
引脚复用冲突:某些引脚可能被多个外设共享,注意避免冲突。
7. 应用实例
功能描述
通过GPIO控制一个LED的闪烁,实现简单的定时闪烁效果。
硬件连接
-
将一个LED的正极连接到GPIO引脚(如GPIOC的Pin5)。
-
LED的负极通过一个限流电阻连接到GND。
代码实现
#include "stm32f10x.h"
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 启用GPIOC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 选择GPIOC的Pin5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); // 初始化GPIOC
}
int main(void) {
GPIO_Init(); // 初始化GPIO
while (1) {
GPIO_WriteBit(GPIOC, GPIO_Pin_5, Bit_SET); // 点亮LED
for (int i = 0; i < 500000; i++); // 延时
GPIO_WriteBit(GPIOC, GPIO_Pin_5, Bit_RESET); // 熄灭LED
for (int i = 0; i < 500000; i++); // 延时
}
}
运行效果
LED每隔一段时间闪烁一次。
应用实例 2:LED流水灯
功能描述
通过GPIO控制多个LED依次点亮和熄灭,形成流水灯效果。
硬件连接
-
将多个LED的正极分别连接到GPIO引脚(如GPIOC的Pin0~Pin7)。
-
每个LED的负极通过限流电阻连接到GND。
代码实现
#include "stm32f10x.h"
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 启用GPIOC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; // 选择GPIOC的Pin0~Pin7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); // 初始化GPIOC
}
int main(void) {
GPIO_Init(); // 初始化GPIO
uint16_t led = GPIO_Pin_0; // 从第一个LED开始
while (1) {
GPIO_WriteBit(GPIOC, led, Bit_SET); // 点亮当前LED
for (int i = 0; i < 500000; i++); // 延时
GPIO_WriteBit(GPIOC, led, Bit_RESET); // 熄灭当前LED
led <<= 1; // 移动到下一个LED
if (led > GPIO_Pin_7) {
led = GPIO_Pin_0; // 从第一个LED重新开始
}
}
}
运行效果
LED依次从第一个点亮到第八个,然后循环。
应用实例 3:蜂鸣器控制
功能描述
通过GPIO控制蜂鸣器发出声音,实现简单的蜂鸣器控制。
硬件连接
-
将蜂鸣器的正极连接到GPIO引脚(如GPIOA的Pin0)。
-
蜂鸣器的负极连接到GND。
代码实现
#include "stm32f10x.h"
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 启用GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 选择GPIOA的Pin0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
}
void Beep(unsigned int times) {
for (int i = 0; i < times; i++) {
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // 打开蜂鸣器
for (int j = 0; j < 100000; j++); // 延时
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // 关闭蜂鸣器
for (int j = 0; j < 100000; j++); // 延时
}
}
int main(void) {
GPIO_Init(); // 初始化GPIO
while (1) {
Beep(3); // 蜂鸣器响3次
for (int i = 0; i < 1000000; i++); // 延时
}
}
运行效果
蜂鸣器每隔一段时间发出3次短促的“滴”声。
1962

被折叠的 条评论
为什么被折叠?



