STM32速成笔记—中断

2023-11-15

一、什么是中断

首先介绍一下什么是中断。在实际开发过程中,中断是很有必要的。比如需要针对某种特殊情况进行快速响应,单纯的使用一个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文件中声明
  • 中断服务函数中不要有过长的业务
  • 中断服务函数最后需要清除中断标志位
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32速成笔记—中断 的相关文章

  • linux搭建主备负载均衡

    1 原理图 底层原理 2 负载集合的功能 1 客户端传过来的请求 在负载均衡那里 根据算法 把用户的请求给指定的服务器 2 如果负载均衡主机宕机了 备机马上接手 如果主机恢复了 备机马上退后 3 如果某个服务器挂了 该服务器马上被踢出去 负
  • mac 打开网页慢_苹果笔记本打开网页很慢是什么原因

    有时候我们找资料会发现网页打开很慢 这是怎么回事呢 为什么网页打开会很慢呢 以下就是小编给你做的整理 希望对你有用 的原因 一 网络最小带宽这是最主要的因素 也就是网友经常说的宽带不够 同样的网站 如果宽带高 访问速度就会明显变快 网络的带
  • ubantu18.04安装Opencv4.0.0

    1 安装依赖 sudo apt get install build essential sudo apt get install cmake git libgtk2 0 dev pkg config libavcodec dev libav
  • 使用z-file和七牛云对象存储构建个人网盘

    最近想构建一个个人网盘玩玩 用来存储些资源 这里使用云服务器 zfile 七牛云对象存储进行搭建 租用云服务器 首先需要在常用的云服务网站买一个云服务器 如阿里云 腾讯云等 这里不说该怎么租用和搭建了 使用七牛云对象存储 这里使用七牛云对象
  • 02功能之读写文件流操作(C语言实现读取文件指定一行)

    02功能之读写文件流操作 C语言实现读取文件指定一行 1 C语言读取文件指定一行 读取文件指定一行 int ReadLine1 const char fileName char outBuf int n int whichLine n 指定
  • sql查询一个字段包含另一个字段内容

    SELECT FROM tbl name WHERE a like CONCAT b 字段a包含字段b 例如 Find the capital and the name where the capital includes the name

随机推荐

  • java libusb_libusb中断传输

    我需要对定制的HID USB设备 控制面板上的一些按钮和LED 进行反向工程 该驱动程序仅在Windows上可用 我们需要 nix实现 该设备显然是HID设备 但不是特定类 它提供两个接口 每个接口都有一个中断 endpoints 我的设置
  • 思考:如何保证服务稳定性?

    最近一直在忙618大促的全链路压测 稳定性保障相关工作 结果618还未开始 生产环境就出了几次生产故障 且大多都是和系统稳定性 性能相关的bad case 生产全链路压测终于告一段落 抽出时间将个人收集的稳定性相关资料整理review了一遍
  • 初学者必读的Linux入门到精通

    课程介绍 本套课程是从入门开始的Linux学习课程 适合初学者阅读 由浅入深案例丰富 通俗易懂 主要涉及基础的系统操作以及工作中常用的各种服务软件的应用 部署和优化 即使是零基础的学员 只要能够坚持把所有章节都学完 也一定会受益匪浅 课程目
  • 单片机串口实现字符串命令解析---使用函数指针(类似哈希表)

    通常情况下串口通信用的大多数都是用十六进制数据来传输指令 比如最常见的modbus的通信 如读保持寄存器指令 01 03 00 00 00 01 84 0A 这种十六进制的指令在这里就不讨论了 想要详细了解可以看往期的文章 串口相关文章链接
  • 常见问题解决方法汇总——十四届恩智浦智能车室外电磁越野组

    调车经验总结 电感值逐渐衰减 可能是变阻器松了 换个变阻器试试 电感值没有变化 肖特基管烧坏或线没接紧 可以换个肖特基管试试 主板上的芯片发烫 轻微发热是正常的 但是烫手就肯定出了问题 可能是传感器上的引脚悬空 检查引脚的是否接触上了 检查
  • 讲解MySQL8.0备份与还原工具(mysqlbackup)

    一 安装mysqlbackup 1 下载 登录oracle edelivery 进入下载连接选择适合你系统的版本下载 在这里我使用的是银河麒麟Kylin OS Server V10 SP2 因此我选择一个通用的预编译二进制的tar包 如下图
  • Android中Activity的开启Activity页面的跳转详解

    android开启和关闭activity 1 在android 中我们要开启和关闭activity按钮首先就要创建两个activity 2 然后在他们的布局文件中添加页面 3 然后使用java代码编写程序实现页面的开启和关闭 在MainAc
  • python 爬虫 验证请求 requests模块中的auth参数可以实现

    import requests 导入requests模块 from requests auth import HTTPBasicAuth 导入HTTPBasicAuth类 定义请求地址 url http sck rjkflm com 666
  • C语言基础 - char字符串数组的概念和定义

    在c语言中 字符串是以 字符数组 存储的 include
  • 【Xilinx Vivado时序分析/约束系列8】FPGA开发时序分析/约束-FPGA数据中间采样、边缘采样PLL时序优化实操

    目录 时序分析实操 分析数据手册 实验工程 输入部分 输出部分 顶层部分 设计层次 综合布线 时序约束 时钟约束 输入延时约束 分析输入延时的约束如何设计 数据中间采样 最小延时约束 最大延时约束 结果分析 数据边缘采样 添加input d
  • java基础补充

    Scanner类的使用 从键盘获取不同类型的变量 需要使用Scanner类 具体实现步骤 1 导包 import java util Scanner 2 Scanner的实例化 Scanner scan new Scanner System
  • c++ 优先队列(priority_queue)

    优先队列的本质是堆 但它具有队列的所有操作特性 与普通队列不同的地方就是出队的时候按照优先级顺序出队 这个优先级即最大堆或最小堆的规则 即大的为top优先出队或小的为top优先出队 在队列的基础上加了个堆排序 以O log n 的效率查找一
  • Qt for iOS:将ipa安装包发布到App store

    终于到了这一步了 我希望你阅读这篇文章的时候 已经按照顺序阅读了我之前的文章 Qt for iOS 基础环境搭建 Qt for iOS 真机调试环境部署 Qt for iOS 申请发布证书 App配置文件 Qt for iOS 从Qt工程到
  • spring boot 项目开发常用目录结构

    在spring boot开发中一些常用的目录划分 一 代码层结构 根目录 net csdn 1 启动类 CsdnApplication java 推荐放在根目录net csdn包下 2 实体类 domain A net csdn domai
  • delphi操作png的单元pngimage.pas包括引用的ZlibExApi.pas和 PngLang.pas

    有需要的可以去这里下载源码 http download csdn net detail sushengmiyan 4662715 delphi操作png是在delphi2009版本之后 网上这么说的 于是乎 我找了源码来共享 希望对大家有帮
  • 【软件工程师学硬件】之 开关电源(4) —— 初识Viper12a

    Viper12a是一个很不错的电源芯片 至少我是这样认为的 当然了 肯定有很多其他的很好的电源芯片 我之所以以Viper12a为例 一方面是其电路简单 便于说明问题 其次它用得比较广 什么电磁炉 影碟机上面电源芯片大部分都是它 其三价格也比
  • 初识 python - 数组及其简单使用(一)

    目录 1 创建数组 2 数组的属性 3 数组的运算 4 查看数组 切片 5 特殊构建数组
  • 稳压芯片TPS54531的设计和分析

    2020 9 5补充 最终5 28V转3 3V的输出电路可以推算出来 输入的电压下限为4V R1为330K R2为160K 输出的电压为3 3V R5为10K R6为3 3K 输出的电流0 1A L1为47uH 根据相位增益进行补偿 C6为
  • 二叉排序树与平衡二叉树(BST&AVLT)

    平衡二叉树的一些操作 平衡二叉树相对于二叉排序树来说是二叉排序树的一个优化版 避免了二叉排序树中的极端情况 想更好的理解还是要结合图片自己动手做做QwQ 这里写的是双平衡 双旋转版 并非LL RR LR RL四种特殊情况单独处理 平衡二叉树
  • STM32速成笔记—中断

    文章目录 一 什么是中断 二 中断的相关概念 2 1 中断优先级 2 2 中断嵌套 2 3 中断服务函数 2 4 中断标志位 三 外部中断EXIT 四 中断程序配置 4 1 设置中断分组并使能中断 4 2 初始化EXIT 4 3 编写中断服