如果有什么不懂的地方欢迎私聊博主,欢迎小白,博主必一一解答。
在 STM32 中,GPIO(通用输入输出)是与外部硬件接口进行交互的主要方式之一。STM32 HAL 库提供了简洁的接口来配置和控制 GPIO 引脚。下面是使用 STM32 HAL 库进行 GPIO 操作的详细教程。
1. 环境准备
确保您已经按照以下步骤准备好开发环境:
- STM32CubeIDE 已安装。
- 创建了 STM32 项目,配置了目标 STM32 微控制器或开发板。
2. 配置 GPIO 外设
在 STM32CubeIDE 中,我们通过 STM32CubeMX 来配置 GPIO 引脚。
步骤:
- 打开 STM32CubeIDE,选择新建一个 STM32 项目。
- 在
Pinout & Configuration
页面,选择您要使用的 GPIO 引脚。例如,选择GPIOA
上的引脚如PA5
(通常用作 LED 灯),并设置为GPIO_Output
,或GPIOA
上的引脚如PA0
设置为GPIO_Input
。 - 在 Configuration 选项卡中,设置引脚的模式、输出类型等。
- 对于输出引脚,选择
Push-Pull
,并设置速率。 - 对于输入引脚,选择
Pull-up
或Pull-down
,以决定输入信号的默认状态。
- 对于输出引脚,选择
- 在 Project 设置中,选择项目名称和代码生成选项(选择 STM32CubeIDE 为 IDE,选择 HAL 库作为中间件)。
- 点击 Generate Code,STM32CubeMX 会生成初始化代码。
3. HAL 库的 GPIO 操作
生成代码后,您可以开始在 main.c
文件中编写应用程序,利用 STM32 HAL 库操作 GPIO 引脚。
GPIO 输入输出操作
1.初始化 GPIO
STM32CubeMX 会自动生成用于初始化 GPIO 的代码,您只需调用 HAL_GPIO_Init()
函数。例如,在 main.c
中可以看到类似这样的初始化代码,我以注释的方式,解释了代码。
// main.c
#include "main.h"
int main(void)
{
HAL_Init(); // 初始化 HAL 库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化 GPIO
while (1)
{
// 在主循环中进行其他任务
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 GPIOA 时钟
// 配置 PA5 为输出
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 设置输出速度
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化 GPIOA5
// 配置 PA0 为输入
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // 上升沿中断模式
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化 GPIOA0
}
GPIO 输出操作
要设置 GPIO 引脚的输出状态(高电平或低电平),您可以使用 HAL_GPIO_WritePin()
函数。例如:
// 设置 PA5 为高电平(点亮 LED)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // 高电平
// 设置 PA5 为低电平(熄灭 LED)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 低电平
GPIO 输入操作
要读取 GPIO 引脚的输入状态,可以使用 HAL_GPIO_ReadPin()
函数。例如,读取 PA0
的状态:
GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
if (pinState == GPIO_PIN_SET) {
// 引脚 PA0 为高电平
} else {
// 引脚 PA0 为低电平
}
GPIO 中断操作
STM32 HAL 库还支持 GPIO 中断。通过 STM32CubeMX 配置中断模式,例如将 PA0 设置为上升沿触发的中断。下面介绍中断的概念。
额外(中断是什么?)
中断(Interrupt)是微控制器(单片机)处理外部事件或任务的一种机制。它允许微控制器在执行程序的过程中,能够中断当前的工作,立即响应外部事件,然后在处理完事件后恢复到原来的工作状态。中断是实时操作系统(RTOS)和高效嵌入式系统设计中常用的一种技术。
中断的工作原理
当一个中断发生时,微控制器会:
-
暂停当前程序:当前正在执行的代码(包括主程序或其他中断服务程序)会被暂停。微控制器保存当前的执行状态(程序计数器、寄存器值等)。
-
跳转到中断处理函数(ISR):程序计数器会被修改,跳转到对应的中断服务程序地址。该中断服务程序通常是用户编写的代码,用来处理特定的中断事件。
-
处理中断:在中断服务程序中,微控制器执行相应的代码以响应中断,比如读取传感器数据、处理外部设备的请求等。
-
恢复执行:中断处理完毕后,微控制器恢复执行原来的程序,继续之前被暂停的操作。
回归正题 ,将 PA0 设置为上升沿触发的中断
在代码中,您需要启用和配置外部中断:
// 在 MX_GPIO_Init 函数中启用中断
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0); // 设置中断优先级
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn); // 启用 EXTI0_1 中断
中断服务程序(ISR)通常放在 stm32f1xx_it.c
中:
// 中断回调函数
void EXTI0_1_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); // 处理外部中断
}
// 回调函数,当发生中断时调用
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0) {
// 对 PA0 引脚的中断进行处理
}
}
4. 使用外设和其他功能
- 配置和使用多个 GPIO 引脚:通过 STM32CubeMX 配置多个 GPIO 引脚进行输入、输出或中断操作。
- 控制 LED:在
main.c
中使用HAL_GPIO_WritePin()
控制连接到开发板的 LED。 - 配置按键:配置外部按键,并在中断或轮询模式下读取按键状态。
5. 示例代码:点亮 LED
下面是一个完整的示例,展示如何通过 GPIO 控制 LED:
#include "main.h"
// 主函数
int main(void)
{
HAL_Init(); // 初始化 HAL 库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化 GPIO
while (1)
{
// 点亮 LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(500); // 延时 500ms
// 熄灭 LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_Delay(500); // 延时 500ms
}
}
// GPIO 初始化函数
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 GPIOA 时钟
// 配置 PA5 为输出(LED)
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 设置输出速度
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化 GPIOA5
}
6. 小结
- GPIO 初始化:通过 STM32CubeMX 配置引脚,并使用 HAL 库函数进行初始化。
- 输入输出操作:使用
HAL_GPIO_WritePin()
控制输出,使用HAL_GPIO_ReadPin()
读取输入。 - 中断处理:通过 STM32CubeMX 配置中断,并在中断回调函数中处理外部中断。