STM32速成笔记—中断

news2024/12/25 9:11:32

文章目录

  • 一、什么是中断
  • 二、中断的相关概念
    • 2.1 中断优先级
    • 2.2 中断嵌套
    • 2.3 中断服务函数
    • 2.4 中断标志位
  • 三、外部中断EXIT
  • 四、中断程序配置
    • 4.1 设置中断分组并使能中断
    • 4.2 初始化EXIT
    • 4.3 编写中断服务函数
  • 五、注意事项

一、什么是中断

首先介绍一下什么是中断。在实际开发过程中,中断是很有必要的。比如需要针对某种特殊情况进行快速响应,单纯的使用一个while轮询似乎并不能满足。中断的概念非常好理解,举个经典例子。比如你在家里看电视,忽然有人敲门,你临时把电视暂停了,转去开门。开完门之后再次回来继续看电视。中断也就是这种流程。看电视的行为就类似于程序中main函数的while,轮询执行业务。忽然有人敲门,对应程序运行过程中忽然产生了一个中断请求。此时暂停电视,对应于此时程序中断当前的业务,转而去处理中断业务(开门)。最后,中断业务处理完成后,再继续执行main函数while轮询中的业务。简单用一个图来表示一下

中断概念示意图

根据中文参考手册的介绍,STM32F103ZET6除了一些特殊的中断外,常用的中断有60个,这些中断是通过中断控制器来有条不紊地分配执行的。

二、中断的相关概念

2.1 中断优先级

从字面意思来讲,优先级用来区分中断的响应顺序。当同时接收到多个中断请求时,中断控制器会根据中断优先级来决定中断处理的顺序,优先级高的会先被处理。如果在处理某个中断请求时又来了一个中断,这时会根据两个中断的中断优先级来确定处理方式。如果新来的中断优先级比当前中断的优先级高,则会停止对当前中断的处理,转而处理新的中断。反之,如果新来的中断优先级比当前中断的优先级低,则需要等到当前中断处理完成后,再去处理新来的中断。

中断优先级有两种,一种是抢占优先级,一种是响应优先级。响应优先级通常又被称为“亚优先级”或者“副优先级”。当两个中断的抢占优先级相同时,用相应优先级来决定中断的处理顺序。如果两个中断的抢占优先级和相应优先级相同,则根据芯片手册中的中断向量号来决定中断的处理顺序。比如同时来了两个中断请求,在抢占优先级和响应优先级均相同时,中断向量号为41的中断会比中断向量号为42的中断先被处理。

STM32提供了16个可编程的优先等级(使用了4位中断优先级),优先级分组可以使用库函数提供的NVIC_PriorityGroupConfig()设置。

2.2 中断嵌套

一些低优先级的中断可以被高优先级中断打断,这种情况叫做中断嵌套。

2.3 中断服务函数

中断服务函数就是在进入中断后需要执行的内容。中断服务函数有特定的函数名,可以在下图文件中搜索“IRQ”找到。
中断服务函数名

2.4 中断标志位

不同的中断会有对应的中断标志位,通常标志位默认值为0。当产生中断请求时,标志位被置1。比如设置一个串口接收完成中断,串口接收完成标志位初始值为0。当串口接收完成后对应的串口接收完成标志位会被置1。在中断服务函数中检测该标志位的值,来确定是否是串口接收完成中断产生了。每次中断服务函数执行结束后,需要清除一下对应的中断标志位。

三、外部中断EXIT

STM32F103ZET6有一个外部中断控制器(EXIT),可以支持20个软件的中断/事件请求,其中外部中断的EXIT0~EXIT15同坐IO中断。

外部中断IO对应

其他详细的介绍这里就不再说明。

四、中断程序配置

这里以配置PA0(按键WK UP)的外部中断为例,展示一下库函数开发时,外部中断的配置流程。关于其他中断的配置,后续使用其他外设时会单独介绍。

想要实现的效果是,利用外部中断实现按下WK UP,LED1点亮。

4.1 设置中断分组并使能中断

这里使用外部中断,需要开启AFIO时钟,设置IO与外部中断线的映射关系。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   // 开启AFIO时钟

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择GPIO管脚用作外部中断线路

设置中断分组并使能中断时,库函数提供了一个结构体,我们直接配置这个结构体就可以了。

    //EXTI0 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   //EXTI0中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;   //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;   //子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	   //根据指定的参数初始化VIC寄存器

需要注意的是,配置优先级时,数值越大,优先级越低。

4.2 初始化EXIT

初始化EXIT时,库函数也提供了一个结构体,其中包括中断线,EXIT模式,触发方式以及EXIT使能或者失能。由按键检测一节了解到,WK UP按下时,会产生一个上升沿。因此触发方式我们选择上升沿触发。

    EXTI_InitStructure.EXTI_Line=EXTI_Line0;   // EXIT0
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;   // 中断
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;   // 上升沿触发
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;   // 使能
	EXTI_Init(&EXTI_InitStructure);

整体配置函数如下

/*
 *==============================================================================
 *函数名称:Exit_Init
 *函数功能:初始化外部中断
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Exit_Init (void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef  EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   // 开启AFIO时钟

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择GPIO管脚用作外部中断线路
	
	//EXTI0 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   //EXTI0中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;   //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;   //子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	   //根据指定的参数初始化VIC寄存器
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line0;   // EXIT0
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;   // 中断
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;   // 上升沿触发
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;   // 使能
	EXTI_Init(&EXTI_InitStructure);
}

4.3 编写中断服务函数

上面介绍了如何找中断服务函数的函数名,这里直接开始写中断服务函数。这里的中断服务函数比较简单,直接点亮LED1即可。

/*
 *==============================================================================
 *函数名称:EXTI0_IRQHandler
 *函数功能:外部中断0中断服务函数
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void EXTI0_IRQHandler(void)
{
	// 如果EXIT0中断标志位被置1
	if(EXTI_GetITStatus (EXTI_Line0)==1)
	{
		Med_Led_StateCtrl (LED1,LED_ON);   // 点亮LED1
	}
	EXTI_ClearITPendingBit (EXTI_Line0);   // 清除中断标志位
}

至此,按下WK UP后,LED1会点亮。这种方法与之前的按键点亮LED有什么区别?之前的按键点亮LED是在main函数的while中实现的,而利用外部中断的方法,是在外部中断的中断服务函数中实现的。即使main函数的while轮询业务中没有按键业务,按键依旧可以起作用。

五、注意事项

  • 中断服务函数无需在.h文件中声明
  • 中断服务函数中不要有过长的业务
  • 中断服务函数最后需要清除中断标志位

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/654057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenCV 笔记_2

文章目录 笔记_2图像尺寸变换resize 图像缩放 (重置图像大小)flip 图像翻转hconcat 横向连接vconcat 纵向连接 图像方式变换warpAffine 仿射变换函数:矩阵M(2*3)getRotationMatrix2D 获取图像旋转矩阵M:矩阵M&#xff…

电脑出现MSVCP100.dll丢失错误怎么办?

MSVCP100.dll是一个Windows系统文件,它可以确保Windows程序正确平稳运行,如果该文件安装不正确、丢失或损坏,则使用该文件的应用程序将无法正常启动,会出现“无法启动此程序,因为计算机中丢失MSVCP100.dll”的错误提示…

OpenCV 笔记_4

文章目录 笔记_4图像细化thinning 图像细化函数 轮廓检测findContours 轮廓检测函数drawContours 轮廓绘制函数contourArea 计算轮廓面积:返回值 double类型arcLength 计算轮廓长度:返回值 double类型 轮廓外接多边形boundingRect 给定轮廓的外接矩形min…

Hook攻防之InlineHook

什么是InlineHook Inline Hook,又称为超级Hook,是一种强大而又灵活的Hook技术。 Inline Hook的主要思想就是直接修改目标函数的代码,通常是在目标函数的开头插入一个跳转指令(jmp)。这个跳转指令会将程序的执行流跳转…

PPT写作要义:信息效率

PPT写作的要义:信息效率 抖音里一个有货的讲师的总结 花里胡哨的PPT一定偏离了初衷 这点上要像互联网公司学习 其实有些PPT制作的初衷,就是搞神秘感 故意让人听不懂 趣讲大白话:大道至简 【趣讲信息科技198期】 ****************************…

基于Java绿色农产品推广应用网站设计实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

CRC原理

文章目录 简介 CRC思想错误检测基本思想多项式运算没有进位的二进制计算 CRC计算方式发送方计算接收方校验多项式选择 CRC实现原理CRC8整体处理数据单个处理数据与整体数据处理比较使用查找表加速计算 扩展到CRC16整体处理数据单个处理数据与整体数据处理比较使用查找表加速计算…

项目管理中,如何实现有效的项目预算管理?

在《PMBOK指南》第七版中,变化较大的一点是从以成果为导向演变为以价值为导向,其十二项指导原则之一——“聚焦于价值”也阐述了价值是项目的最终成功指标和驱动因素。在这一指导原则下,项目经理就不能只关注在范围、进度、成本三重要素约束下…

UmiJs - 拆包优化

UmiJs - 拆包优化 前言一. 如何拆包,怎么拆1.1 分析自己项目的编译产物结构1.2 开始拆包 二. 有哪些注意点2.1 样式丢失2.2 存在需单独打包的页面 前言 我们在写前端代码的时候,难以避免的是,我们可能引入的依赖越来越多。那么随之而来的&am…

Redis入门 - Lua脚本

原文首更地址,阅读效果更佳! Redis入门 - Lua脚本 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-scription.html Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。 …

【Golang系列】Golang环境配置和第一个Go程序

⭐️前面的话⭐️ 本篇文章将介绍Golang语言的环境配置,以及如何在VS code中运行第一个golang程序。 📒博客主页:未见花闻的博客主页 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📌本文由未…

Pytest教程__定制allure报告(12)

定制报告需要先导入allure模块,再使用以下装饰器方法: feature: 标注主要功能模块。story: 标注feature功能模块下的分支功能。description:在报告中显示用例描述。step: 标注测试用例步骤。issue && testcase:标注用例关…

单链表刷题(1-3)

目录 反转链表 移除元素 合并有序链表 反转链表 力扣 我们用取头节点依次进行头插的方式解决这道题。需要注意的是头插前要保存下一个节点。 struct ListNode* reverseList(struct ListNode* head){typedef struct ListNode SL;SL* cur head;SL* rhead NULL;//初始指向空…

TienChin 代码格式化-项目结构大改造

代码格式化 博主下载项目之后发现,整体的代码格式化风格,与 C 那种语言很相似,说明这个作者之前就是从事这块的导致风格有点类似,我们来格式化一下,当然这不是必要的,我是没习惯这种写法所以这里我写一下我…

2023年测试岗,你真的懂测试吗?凭什么他能月薪25k+

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 测试人员应该居安…

Redis入门 - 事务

原文首更地址,阅读效果更佳! Redis入门 - 事务 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-transaction.html Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: 批量操作在发送 EXEC 命…

STM32串口通信详解(嵌入式学习)

STM32串口通信 1.通信基础知识1.1 时钟信号区分同步通信异步通信波特率总线协议(电气协议) 1.2 通信方式划分串行通信并行通信 1.3 通信方向划分单工通信半双工通信全双工通信常见通信总结 2. USARTUSART 介绍 3. 串口通信协议4. 相关寄存器串口控制寄存器波特率寄存器中断和状…

segment anything环境配置与使用测试

硬件:RTX3070 i9-11900H 内存16G 目录 一、环境配置 二、使用测试--predictor_example.ipynb 1.jupyter notebook准备操作 2.Object masks from prompts with SAM与Environment Set-up 3.Set-up 4.Example image 5.Selecting objects with SAM 6.Specifyin…

GeoServer安装部署

GeoServer是一款开源的GIS服务器,用于管理、共享和编辑空间数据。 它的主要功能包括: 管理空间数据:GeoServer可以连接各种空间数据源,包括文件(SHP、CSV等)、数据库(PostGIS,Oracle,SQL Server等)和云存储(S3,Swift,Azure等)。并提供数据的浏览、上传、下载和删除…

webgpu之旅04

继续继续 319854902 319854902 319854902 319854902 webgpu交Q流群首先准备好绘制到屏幕所需的这个descriptor if rendertarget this._textures.initRenderTarget( renderTarget ); 来看一下这个函数里面会做什么 renderTargetProperties是这个target的properties 创建一个co…