STM32第二天之外部中断及系统定时器

2023-11-20

1.中断优先级

1.在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255。

2.数值越小,优先级越高。 在 F103 中,只使用了高 4bit,用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级

3.如果有多个中断同时响应,抢占 优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如 果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

1.优先级分组

2.在配置每个中断的时候一般有 3 个编程要点:

1. 使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中 断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。

2. 初始化 NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使 能中断请求。NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义。

typedef struct {
    uint8_t NVIC_IRQChannel; // 中断源
    uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
    uint8_t NVIC_IRQChannelSubPriority; // 子优先级
    FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
 } NVIC_InitTypeDef;
//NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序
也不会报错,只会导致不响应中断。具体的成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type
结构体定义,这个结构体包含了所有的中断源。

 3. 编写中断服务函数

启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些 中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为 了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。 关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量 表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限 循环,实现不了中断。

 4.外部中断EXTI

1.原理框图

编号 1 是输入线,EXTI 控制器有 19 个中断/事件输入线,这些输入线可以通过寄存器设置 为任意一个 GPIO,也可以是一些外设的事件。输入线 一般是存在电平变化的信号

编号 2 是一个边沿检测电路,它会根据上升沿触发选择寄存器 (EXTI_RTSR) 和下降沿触发 选择寄存器 (EXTI_FTSR) 对应位的设置来控制信号触发。边沿检测电路以输入线作为信号 输入端,如果检测到有边沿跳变就输出有效信号 1 给编号 3 电路,否则输出无效信号 0。

编号 3 电路实际就是一个或门电路,它一个输入来自编号 2 电路,另外一个输入来自软件 中断事件寄存器 (EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事 件线。我们知道或门的作用就是有 1 就为 1,所以这两个输入随 便一个有有效信号 1 就可以输出 1 给编号 4 和编号 6 电路。

编号 4 电路是一个与门电路,它一个输入是编号 3 电路,另外一个输入来自中断屏蔽寄存 器 (EXTI_IMR)。与门电路要求输入都为 1 才输出 1,导致的结果是如果 EXTI_IMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 4 电路输出的信号都为 0;如果 EXTI_IMR 设置为 1 时,最终编号 4 电路输出的信号才由编号 3 电路的输出信号决定,这 样我们可以简单的控制 EXTI_IMR 来实现是否产生中断的目的。编号 4 电路输出的信号会 被保存到挂起寄存器 (EXTI_PR) 内,如果确定编号 4 电路输出为 1 就会把 EXTI_PR 对应位 置 1。

编号 5 是将 EXTI_PR 寄存器内容输出到 NVIC 内,从而实现系统中断事件控制。

2.编程要点

1) 初始化用来产生中断的 GPIO;

2) 初始化 EXTI;

3) 配置 NVIC;

4) 编写中断服务函数;

/*配置NVIC寄存器*/
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源:配置两个中断源 */
  NVIC_InitStructure.NVIC_IRQChannel =  EXTI0_IRQn|EXTI15_10_IRQn;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  NVIC_Init(&NVIC_InitStructure);
}

 /**
  * @brief  配置 IO为EXTI中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/*开启按键GPIO口的时钟,AFIO为外部中断的时钟*/
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
												
	/* 配置 NVIC 中断*/
	NVIC_Configuration();
	
/*--------------------------KEY1配置-----------------------------*/
	/* 选择按键用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); 
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	
	/* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 上升沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  /* 使能中断 */	
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
  /*--------------------------KEY2配置-----------------------------*/
	/* 选择按键用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
  EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
	
	/* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 下降沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  /* 使能中断 */	
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}
void EXTI0_IRQHandler(void)
 {
 //确保是否产生了 EXTI Line 中断
 if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {
 // LED1 取反
 LED1_TOGGLE;
 //清除中断标志位
 EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
 }

 

当中断发生时,对应的中断服务函数就会被执行,我们可以在中断服务函数实现一些控制。
一般为确保中断确实发生,我们会在中断服务函数中调用中断标志位状态读取函数读取外设中
断标志位并判断标志位状态。
EXTI_GetITStatus 函数用来获取 EXTI 的中断标志位状态,如果 EXTI 线有中断发生函数返回
“SET”否则返回“RESET”。实际上,EXTI_GetITStatus 函数是通过读取 EXTI_PR 寄存器值来判
断 EXTI 线状态的。
中断服务函数我们让 LED1 翻转其状态,执行任务后需要调用 EXTI_ClearITPendingBit 函数清除 EXTI 线的中断标志位

5.系统定时器

 主要作用产生精准延时,使用AHBCLK作为时钟源。常用ms延时和us延时,

最大不能超过重装载寄存器的值 2^ 24,当重装载寄存器的值递减到 0 的时候产生中断, 然后重装载寄存器的值又重新装载往下递减计数,以此循环往复

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32第二天之外部中断及系统定时器 的相关文章

  • 实验二 程序流程控制

    1 编写程序计算 1 3 5 7 99 之和 summ 0 for i in range 1 100 summ summ i print 和为 summ 2 编写程序 计算 2 4 6 8 100 之和 summ 0 for i in ra

随机推荐

  • 计算机网络试题

    一 选择题 1 OSI模型与TCP IP模型都具有的层次是 A 会话层 网络层和物理层 B 表示层 会话层和数据链路层 C 网络层 传输层和应用层 D 表示层 数据链路层和物理层 2 对于计算机网络体系结构 下列关于第N层和第N 1层的关系
  • 蓝桥杯:字符串

    题目链接 include
  • notepad++字符串替换

    删除空白行 在编辑选项里面包括很多功能 编辑 gt 行操作 gt 移除空行 包括空白字符 行首添加字符串 按CTRL F 选择替换页签 选择正则表达式 查找目标 设置为 替换为 设置自己想要替换的字符串 特殊字符需要添加 进行转义 行尾添加
  • 【MySQL】34道SQL综合练习详解(员工表、部门表、工资等级表)

    文章目录 一 34道SQL综合练习 二 测试使用的数据表 三 创建测试表的SQL语句 一 34道SQL综合练习 1 查询取得每个部门最高工资的人员信息 select e ename t from emp e join select dept
  • 如何使用PCL将XYZRGB点云转换为彩色mesh模型

    如何使用PCL将XYZRGB点云转换为彩色mesh模型 最近完成了一个使用RGBD传感器 构建物体模型的小demo 其中有点难的最后一步是如何将获得的物体点云变成彩色mesh模型 效果图如下 从点云变成彩色mesh 其实整体的步骤可以总结如
  • M1 macbook上安装docker 编译内核 并使用qemu启动内核。

    一 编译内核并通过qemu启动内核 1 在M1上安装docker这个就不用提供步骤了 网上自行搜索 2 在M1上pull一个ubuntu的容器 docker pull ubuntu 18 04 docker images REPOSITOR
  • 卡尔曼滤波及其MATLAB程序

    今天写了个卡尔曼滤波的小程序 希望对有需要的同学有点帮助 卡尔曼滤波是一个很常用的滤波算法 与维纳滤波相比有很多长处 这里我们把Kalman Filter简称为KF KF的基本思想是 采用信号 噪声 状态空间模型 利用前一时刻的状态最优估计
  • 学习python笔记01

    一 python是什么 人生苦短 我用python python是一门解释型语言 边解释边运行 与编译型语言的区别是 编译型语言是先编译后运行 python语言的特点 1 优雅 2 明确 3 简单 python是一个完全面向对象语言 具有强
  • 纯java实现相片转素描

    1 实例演示图片转素描效果 首先我们来看一下具体的效果 在项目中添加依赖
  • unity制作一个可以自由滑动收缩的历史记录功能。

    公司在做一款模拟经营类的卖车游戏 需要一个简单的历史记录功能 放在左上角 记录最近20条的收入 支出记录 超过2秒不动则收起 收起时展示最近的一个消息记录 用到的组件是ScrollView 使用方法可以参考我写过的一篇博客 ScrollVi
  • Input.GetAxis _ Unity3d

    Input GetAxis 获取轴 static function GetAxis axisName string float Description描述 Returns the value of the virtual axis iden
  • 【论文精读】时序逻辑应用之模型预测控制Model Predictive Control with Signal Temporal Logic Specifications

    前言 因为天天写代码实在是太枯燥了 所以读点其他东西来调剂一下 这样科研进度不至于停下 前面读了几篇关于时序逻辑学习的文章 今天来了解一下时序逻辑公式在控制中的应用 Raman V Donze A Maasoumy M Murray R M
  • Android Studio编译失败问题(aapt2)

    Android Studio 3 1编译时出错 org gradle api tasks TaskExecutionException Execution failed for task app mergeDebugResources at
  • 心灵鸡汤

    心灵鸡汤 比尔盖茨不想弯腰去捡100美金 浪费了1秒 时间是最宝贵 有限的时间资源最大化 如果你不够优秀 人脉是不值钱的 它不是追求来的 而是吸引来的 只有等价的交换 才能得到合理的帮助 虽然听起来很冷 但这是事实 与凤凰同飞 必是俊鸟 与
  • AESCBCUtil

    import javax crypto Cipher import javax crypto spec IvParameterSpec import javax crypto spec SecretKeySpec import org ap
  • 面试必问的 CAS ,要多了解

    前言 CAS Compare and Swap 即比较并替换 实现并发算法时常用到的一种技术 Doug lea大神在java同步器中大量使用了CAS技术 鬼斧神工的实现了多线程执行的安全性 CAS的思想很简单 三个参数 一个当前内存值V 旧
  • 结构体中数组放在最后位置的问题

    以下出自 C Programming FAQS 先看下面的代码 struct name int namelen char namestr 1 struct name makename char newname struct name ret
  • GDAL多光谱与全色图像融合简单使用

    目录 简述 C 代码 效果对比 GDAL融合效果和原始多光谱波段对比 GDAL融合效果和原始全色波段对比 ARCGIS融合效果与原始全色和多光谱对比 GDAL融合效果与ArcGIS融合效果对比 简述 最近在GDAL的代码中看见了gdalpa
  • 毕业设计e4a代码

    事件 主窗口 创建完毕 用来设置该窗口控件的属性 比如说该窗口的标题 该窗口的背景颜色 该窗口的背景图片 按键的标题设置 标签1 背景颜色 无色 标签1就是设备未使用 标签2 背景颜色 无色 标签2就是推出系统 标签1 可用 假 禁止标签使
  • STM32第二天之外部中断及系统定时器

    1 中断优先级 1 在 NVIC 有一个专门的寄存器 中断优先级寄存器 NVIC IPRx 用来配置外部中断的优先级 IPR 宽度为 8bit 原则上每个外部中断可配置的优先级为 0 255 2 数值越小 优先级越高 在 F103 中 只使