当前位置: 首页 > news >正文

【星云 Orbit-F4 开发板】04.一触即发:GPIO 外部中断

【星云 Orbit-F4 开发板】04. 一触即发:外部中断控制

摘要

本文详细介绍了如何使用STM32F407微控制器的HAL库实现外部中断功能。通过配置GPIO引脚作为外部中断源,并在中断回调函数中处理按键事件,实现了按键控制LED状态翻转的功能。本文旨在为初学者提供一个详细、易懂的教程,包括硬件电路设计、软件架构、代码实现及应用示例。


1. 引言

外部中断是嵌入式系统中常见的功能,用于检测外部事件并触发相应的中断处理程序。STM32F407微控制器提供了丰富的GPIO资源和灵活的中断配置,通过HAL库可以方便地实现外部中断功能。本文以STM32F407开发板为例,详细介绍了如何配置外部中断,实现按键控制LED状态翻转的功能。


2. 硬件设计

2.1 硬件资源

本实验使用STM32F407开发板上的两个按键和两个LED,具体资源如下:

  • LED
    • LED0:连接到GPIOF的Pin 9
    • LED1:连接到GPIOF的Pin 10
  • 按键
    • WKUP:连接到GPIOA的Pin 0
    • KEY0:连接到GPIOE的Pin 4

2.2 硬件接线

本实验使用的两个 STM32F407 板载按键,分别为 KEY0 按键和 WKUP 按键,其与板载 MCU 的连接原理图如下所示:

在这里插入图片描述
从原理图中可以看出,WKUP 按键和 KEY0 按键的一端连接到了电源正极(VCC),而另一端分别与 MCU 的 PA0 引脚和 PE4 引脚相连接。对于该硬件设计,PA0 引脚和 PE4 引脚应当配置为下拉模式,这样一来,在按键被按下的时候,PA0 引脚或 PE4 引脚就会从原来的低电平状态变为高电平状态,在这期间就会有一个上升沿的跳变,因此可以使用该上升沿信号作为中断的触发源。


3. 软件设计

3.1 软件架构

本实验的软件架构主要包括以下几个部分:

  1. 系统初始化:初始化HAL库、时钟、延时、串口和LED。
  2. 外部中断初始化:配置GPIO引脚作为外部中断源,并设置中断优先级。
  3. 中断服务函数:处理外部中断事件,实现按键控制LED状态翻转的功能。

为了提高代码的可读性和可维护性,我们将代码分为多个模块,每个模块负责一个特定的功能。

3.2 GPIO 配置

使用 HAL 库配置 GPIO 引脚为外部中断模式:

  • 模式:上升沿触发中断。
  • 上拉/下拉:下拉模式。

3.3 中断配置

3.3.1 设置中断优先级

使用 HAL_NVIC_SetPriority 函数设置中断优先级:

HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);
  • IRQn:NVIC 中断请求,例如 EXTI0_IRQnUSART1_IRQn 等(在 stm32f407xx.h 文件中有定义)。
  • PreemptPriority:抢占优先级。
  • SubPriority:子优先级。
3.3.2 使能中断

使用 HAL_NVIC_EnableIRQ 函数使能中断:

HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
  • IRQn:NVIC 中断请求,例如 EXTI0_IRQnUSART1_IRQn 等(在 stm32f407xx.h 文件中有定义)。

3.3 中断服务函数

编写中断服务函数,处理按键按下事件:

  • WKUP_INT_IRQHandler:处理 WKUP 按键中断。
  • KEY0_INT_IRQHandler:处理 KEY0 按键中断。

3.4 中断回调函数

使用 HAL_GPIO_EXTI_Callback 函数处理中断事件,翻转 LED 状态。


4. 代码实现

4.1 系统初始化模块

4.1.1 HAL库初始化
#include "stm32f4xx_hal.h"// 初始化HAL库
void hal_init(void)
{HAL_Init(); // 初始化HAL库
}
4.1.2 时钟配置
#include "stm32f4xx_hal.h"// 配置时钟
void sys_stm32_clock_init(uint32_t pllm, uint32_t plln, uint32_t pllp, uint32_t pllr)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};// 初始化RCC OscRCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = pllm;RCC_OscInitStruct.PLL.PLLN = plln;RCC_OscInitStruct.PLL.PLLP = pllp;RCC_OscInitStruct.PLL.PLLR = pllr;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){// 初始化失败while (1){}}// 初始化RCC ClkRCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){// 初始化失败while (1){}}
}
4.1.3 延时初始化
#include "stm32f4xx_hal.h"// 延时函数
void delay_ms(uint32_t ms)
{HAL_Delay(ms); // 使用HAL库提供的延时函数
}
4.1.4 串口初始化
#include "stm32f4xx_hal.h"// 初始化串口
void usart_init(uint32_t baudrate)
{USART_HandleTypeDef huart1;huart1.Instance = USART1;huart1.Init.BaudRate = baudrate;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){// 初始化失败while (1){}}
}
4.1.5 LED初始化
#include "stm32f4xx_hal.h"// 定义LED和按键的GPIO引脚
#define LED0_GPIO_PORT GPIOF
#define LED0_GPIO_PIN GPIO_PIN_9
#define LED1_GPIO_PORT GPIOF
#define LED1_GPIO_PIN GPIO_PIN_10// 初始化LED
void led_init(void)
{GPIO_InitTypeDef gpio_init_struct = {0};// 使能GPIO端口时钟__HAL_RCC_GPIOF_CLK_ENABLE();// 配置LED0引脚gpio_init_struct.Pin = LED0_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;gpio_init_struct.Pull = GPIO_NOPULL;gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct);// 配置LED1引脚gpio_init_struct.Pin = LED1_GPIO_PIN;HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct);// 关闭LEDHAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET);HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET);
}

4.2 外部中断初始化模块

4.2.1 GPIO引脚配置
#include "stm32f4xx_hal.h"// 定义按键的GPIO引脚
#define WKUP_INT_GPIO_PORT GPIOA
#define WKUP_INT_GPIO_PIN GPIO_PIN_0
#define WKUP_INT_GPIO_CLK_ENABLE() do { HAL_RCC_GPIOA_CLK_ENABLE(); } while (0)
#define WKUP_INT_IRQn EXTI0_IRQn
#define WKUP_INT_IRQHandler EXTI0_IRQHandler#define KEY0_INT_GPIO_PORT GPIOE
#define KEY0_INT_GPIO_PIN GPIO_PIN_4
#define KEY0_INT_GPIO_CLK_ENABLE() do { HAL_RCC_GPIOE_CLK_ENABLE(); } while (0)
#define KEY0_INT_IRQn EXTI4_IRQn
#define KEY0_INT_IRQHandler EXTI4_IRQHandler// 初始化外部中断
void exti_init(void)
{GPIO_InitTypeDef gpio_init_struct = {0};// 使能GPIO端口时钟WKUP_INT_GPIO_CLK_ENABLE();KEY0_INT_GPIO_CLK_ENABLE();// 配置WKUP控制引脚gpio_init_struct.Pin = WKUP_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_RISING;gpio_init_struct.Pull = GPIO_PULLDOWN;gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(WKUP_INT_GPIO_PORT, &gpio_init_struct);// 配置KEY0控制引脚gpio_init_struct.Pin = KEY0_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_RISING;gpio_init_struct.Pull = GPIO_PULLDOWN;gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &gpio_init_struct);// 配置中断优先级并使能中断HAL_NVIC_SetPriority(WKUP_INT_IRQn, 0, 0);HAL_NVIC_EnableIRQ(WKUP_INT_IRQn);HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 0);HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);
}

4.3 中断服务函数模块

4.3.1 外部中断服务函数
#include "stm32f4xx_hal.h"// 外部中断服务函数
void WKUP_INT_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN); // 处理WKUP按键的外部中断
}void KEY0_INT_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN); // 处理KEY0按键的外部中断
}
4.3.2 HAL库外部中断回调函数
#include "stm32f4xx_hal.h"// HAL库外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{// 机械按键消抖(仅演示,切勿在实际工程的中断服务函数中进行阻塞延时)delay_ms(20);switch (GPIO_Pin){case WKUP_INT_GPIO_PIN:HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); // 翻转LED0状态break;case KEY0_INT_GPIO_PIN:HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); // 翻转LED1状态break;}
}

4.4 主程序模块

4.4.1 主程序
#include "stm32f4xx_hal.h"
#include "system_init.h"
#include "exti_init.h"
#include "led_init.h"
#include "usart_init.h"
#include "delay.h"int main(void)
{hal_init(); // 初始化HAL库sys_stm32_clock_init(336, 8, 2, 7); // 配置时钟,168MHzdelay_init(168); // 初始化延时usart_init(115200); // 初始化串口led_init(); // 初始化LEDexti_init(); // 初始化外部中断while (1){// 主循环中不执行任何操作}
}

5. 下载验证

在完成编译和烧录操作后,可以看到板子上的LED0和LED1默认是处于熄灭的状态。若此时按下WKUP按键,则能够看到LED0的亮灭状态发生了一次翻转。同样的,若此时按下KEY0按键,则能够看到LED1的亮灭状态发生了一次翻转,与预期的实验现象效果相符。


6. 总结

本文详细介绍了如何使用STM32F407微控制器的HAL库实现外部中断功能,通过配置GPIO引脚作为外部中断源,并在中断回调函数中处理按键事件,实现了按键控制LED状态翻转的功能。本文涵盖了硬件电路设计、软件架构、代码实现及应用示例,旨在为初学者提供一个详细、易懂的教程。通过本文的学习,读者可以掌握STM32F407外部中断的基本配置和使用方法,为后续的嵌入式系统开发打下坚实的基础。

在完成编译和烧录操作后,可以看到板子上的LED0和LED1默认是处于熄灭的状态。若此时按下WKUP按键,则能够看到LED0的亮灭状态发生了一次翻转。同样的,若此时按下KEY0按键,则能够看到LED1的亮灭状态发生了一次翻转,与预期的实验现象效果相符。


6. 总结

本文详细介绍了如何使用STM32F407微控制器的HAL库实现外部中断功能,通过配置GPIO引脚作为外部中断源,并在中断回调函数中处理按键事件,实现了按键控制LED状态翻转的功能。本文涵盖了硬件电路设计、软件架构、代码实现及应用示例,旨在为初学者提供一个详细、易懂的教程。通过本文的学习,读者可以掌握STM32F407外部中断的基本配置和使用方法,为后续的嵌入式系统开发打下坚实的基础。

相关文章:

【星云 Orbit-F4 开发板】04.一触即发:GPIO 外部中断

【星云 Orbit-F4 开发板】04. 一触即发:外部中断控制 摘要 本文详细介绍了如何使用STM32F407微控制器的HAL库实现外部中断功能。通过配置GPIO引脚作为外部中断源,并在中断回调函数中处理按键事件,实现了按键控制LED状态翻转的功能。本文旨在…...

笔记二:整数和浮点数在内存中存储

目录 一、数据类型介绍 二、类型的基本归类 1.整形家族: 2.浮点数家族: 3.构造类型: 4.指针类型 5.空类型: 三、整形在内存中的存储 3.1 原码,反码、补码 3.2 大小端介绍 四、浮点数在内存中的存储 ​编辑 4.…...

PyQT(PySide)的上下文菜单策略设置setContextMenuPolicy()

在 Qt 中,QWidget 类提供了几种不同的上下文菜单策略,这些策略通过 Qt::ContextMenuPolicy 枚举类型来定义,用于控制控件(如按钮、文本框等)在用户右键点击时如何显示上下文菜单。 以下是 Qt::ContextMenuPolicy 枚举中…...

BladeX框架接口请求跨域

前端使用代理请求接口,接口可以正常访问。如果换全路径请求就跨域。 除了后端要配置跨域 还需要修改配置文件对OPTIONS请求的限制...

如何在Apple不再支持的MacOS上安装Homebrew

手头有一台2012年产的Macbook Pro,系统版本停留在了10.15.7(2020年9月24日发布的)。MacOS 11及后续的版本都无法安装到这台老旧的电脑上。想通过pkg安装Homebrew,发现Homebrew releases里最新的pkg安装包不支持MacOS 10.15.7&…...

本地大模型编程实战(26)用langgraph实现基于SQL数据构建的问答系统(5)

本文将将扩展上一篇文章完成的 langgraph 链,继续使用基于 langgraph 链 ,对结构化数据库 SQlite 进行查询的方法。该系统建立以后,我们不需要掌握专业的 SQL 技能,可以用自然语言询问有关数据库中数据的问题并返回答案。主要完善…...

数据结构与算法:滑动窗口

前言 滑动窗口一般主要用于解决子数组或子串问题,这类的题目更看重对题目的分析和转化。 一、原理 在整个数组上,用l和r分别控制窗口的左右边界,r就扩大,l就减小。 当窗口的范围和题目中某个指标间存在单调关系时,…...

江协科技/江科大-51单片机入门教程——P[2-1] 点亮一个LED

本节将向大家介绍如何用 51 单片机去控制开发板上的 LED。开发板上的 LED 位置标注有 “LED 模块”。 第二章要写 3 个程序代码:第一个代码实现点亮开发板上的第一个 LED;第二个代码让第一个 LED 以 1 秒为周期闪烁;第三个代码使 8 个 LED 以…...

leetcode hot 100 41. 缺失的第一个正数

代码 测试用例 测试用例 测试结果 41. 缺失的第一个正数 已解答 困难 相关标签 相关企业 提示 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xf…...

UniApp 使用 u-loadmore 完整步骤

文章目录 一、前期准备1. 安装 uView - UI 二、使用 u-loadmore组件1. 创建页面2. 编写页面代码模板部分(loadmore-demo.vue)样式部分脚本部分 三、要点补充1. u-loadmore 状态说明2. 数据请求优化3. 性能优化4. 兼容性问题 在 UniApp 开发中&#xff0c…...

设置电脑一接通电源就主动开机

文章目录 1、进入BIOS2、设置4、功能弊端5、电脑自动开机的设置 1、进入BIOS 在电脑重启时,这时屏幕上会显示按XXX键到BIOS界面 没有进入BIOS提示的,按下面方法操作: 方法一 在开机显示logo的时候,立即按下面这几个按键&#xf…...

优艾智合机器人日本子公司成立,加速推进国际化布局

2月27日,工业移动机器人解决方案商优艾智合宣布日本子公司Youibot Robotics Japan株式会社(以下简称“Youibot Japan”)成立,并于东京举行开业典礼。此举标志着优艾智合在日本市场的现地服务能力进一步深化,是其全球化…...

自然语言处理NLP入门 -- 第七节预训练语言模型

1 什么是预训练模型? 在自然语言处理(NLP)里,训练一个好模型通常需要很多数据和计算资源。为了解决这个难题,就出现了“预训练模型”。 预训练模型 是指我们先在海量文本(比如网络上爬到的大量文章、对话…...

Git GitHub基础

git是什么? Git是一个分布式版本控制系统,用于管理源代码的变更。它允许多个开发者在同一个项目上协作,同时跟踪每个修改的历史记录。 关键词: 分布式版本控制软件 软件 安装到我们电脑上的一个工具 版本控制 例如论文&…...

多平台文章同步工具PostSync 安装介绍

PostSync 是一个开源的用于多平台文章同步的工具 环境安装 安装 Python:PostSync 是基于 Python 开发的,你需要确保系统中已经安装了 Python 环境,建议使用 Python 3.7 及以上版本。你可以从 Python 官方网站 下载并安装适合你操作系统的版…...

PXE批量网络装机与Kickstart自动化安装工具

目录 一、系统装机的原理 1.1、系统装机方式 1.2、系统安装过程 二、PXE批量网络装机 2.1、PXE实现原理 2.2、搭建PXE实际案例 2.2.1、安装必要软件 2.2.2、搭建DHCP服务器 2.2.3、搭建TFTP服务器 2.2.4、挂载镜像并拷贝引导文件到tftp服务启动引导文件夹下 2.2.5、编…...

css的复合选择器

1.1什么是复合选择器 在css中,选择器分为基础选择器和复合选择器,复合选择器是建立在基础选择器之上,对基本选择器进行组合形成。 复合选择器可以更准确、更高效的选择目标元素(标签)由两个或多个基础选择器,通过不同的方式组合…...

Wireshark Lua 插件教程

本⽂主要介绍 Lua 脚本在 Wireshark 中的应⽤, Lua 脚本可以在 Wireshark 中完成如下功能: 从⽹络包中提取数据, 或者统计⼀些数据包(Dumper) 需要解析⼀种 Wireshark 不提供原⽣⽀持的协议(Dissector) ⽰例 协议解析 VREP 协议是 NOGD 框架对于 TRIP 协议的⼀种延伸和扩展…...

mysql怎样优化where like ‘%字符串%‘这种模糊匹配的慢sql

一 问题描述 工作中经常遇到这种模糊匹配的慢sql: select * from 表名 where 字段 like %字符串%; 由于前面有%,导致无法走该字段上的索引。 二 解决办法 ① 给该字段创建一个全文索引 CREATE FULLTEXT INDEX 索引名 ON 表名 (字段名); ② 改写sq…...

Python代码片段-断点任务

使用Python处理一堆长耗时任务的时候,为了防止异常退出程序或者手动退出程序后丢失任务进度,可用使用断点的方式记录任务进度,下次重载任务后,继续运行上次未完成的任务即可。 这里用json文件作为数据持久化的方式,免…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...