程序见上一次串口配置
中断的概述 4.1.1 什么是中断 程序在正常运行过程中发生了内部或外部事件时,打断了正在执行的程序,转到外部或内部事件中去执行中断对应的代。 4.1.2 中断的意义 高效的去执行程序,不会一直占用MCU的资源。 4.1.3 中断入口 中断服务函数:芯片中固定了一段地址空间用来存储程序代码。这一段程序代码是中断执行的程序代码 中断的入口:中断服务函数名。 4.1.4 中断的优先级 中断优先级:指的是给中断编号,用来区分那件事件先执行,那件事情后执行。编号越小优先级越高 4.1.5 中断的嵌套 中断嵌套:在执行中断服务函数代码时,又发生中断事件打断了正在执行的程序。 4.1.6 补充 main函数与中断服务函数的关系? main函数、与中断服务函数属于同一级别,不存在的一个说法是main函数调用中断服务函数。所以中断服务函数不需要什么函数声明啊,调用函数等,只需要重写实现中断服务函数就好。 中断的执行流程? 发生中断事件,找到中断入口,抢占MCU资源执行中断服务函数中的代码(此时main函数失去MCU的使用权),如图1所示。 图1 中断执行流程 断点:正常执行的程序,发生中断事件时,被打断的位置。MCU去执行中断服务函数中的代码前,存储的该断点的现场信息,我们把这一过程称为:压栈(入栈)。在执行完中断服务函数后,回到断点,从栈中读出之前存入的现场信息,继续执行,我们称这一过程为弹栈(出栈)。 中断嵌套的执行流程? 图2嵌套中断流程 中断嵌套如图2,(简单理解:中断中又发生了中断)。 4.2 异常与中断 4.2.1 异常的理解 异常:简单理解,属于内核的中断(系统内部)称为异常,如图3所示。 中断:不属于内核的中断,称为外部中断,简称中断,如图4所示。 如无特殊说明,可以不分辨“中断”与“异常”这两个术语,可以互换使用。 图3 系统异常(中断) 图4 外部中断 由图可知,编号0没有进行任何定义,编号为 1-15 的对应系统异常,大于等于 16 的则全是外部中断。 4.2.2 优先级 悬起: 先理解一个概念:“悬起”。如果发生了一个中断但是它不能马上反应,称为悬起。 优先级: 优先级的概念:优先级解决的问题是同时发生多个中断请求时,先响应谁,把谁悬起的问题。被悬起的中断,等待高优先级响应完,它们才能有机会正常执行响应中断请求。 优先级的特点: 数值越小,优先级越高。 高优先可抢占低优先级。 抢占优先级与子优先级: 为了使抢占机能变得更可控,CM3 还把256级优先级按位分成高低两段,分别称为抢占优先级和子优先级。 图5优先级分组 由图5可知,有8(0到7)个分组位置。 从分组位置0可知,抢占优先级最多可以使用7位(高七位—>7、6、5、4、3、2、1)表示,27=128,能表示128个抢占优先级,即:最多支持128层中断嵌套。进而得出子优先级至少有1位,21=2,能表示2个子优先级。 从分组位置7可知道可以没有抢占优先级,但必须有子优先级。
NVIC 中有一个寄存器是“应用程序中断及复位控制寄存器”,如图6,它里面有一个位段名为“优先级组”。该位段的值对每一个优先级可配置的异常都有影响——把其优先级分为 2 个位段: MSB 所在的位段(左边的)对应抢占优先级,而 LSB 所在的位段(右边的) 对应子优先级。 图6应用程序中断及复位控制寄存器AIRCR 举个例子,如果只使用 3 个位来表达优先级[7:5],并且优先级组的值是5,查表可知,如图7、8所示,位7与位6表示抢占优先级。 图7优先级分组值为5查表结果 图83位表示优先级,分组值为5实际分组 4.2.3抢占优先级与子优先级 《1》高抢占优先级是可以打断正在进行的低抢占优先级中断的。 《2》抢占优先级相同的中断,高子优先级不可以打断低子优先级的中断。 《3》 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个子优先级高,就先执行。 《4》如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行; 4.2.4 补充 从需求理解中断: 中断的发明是为了提高MCU执行程序的效率、让程序变得更加灵活、高效。例如按键的扫描,需要MCU不断的去轮询,当程序的框架复杂,实现很多功能,代码量多时,按键往往就没那么灵敏了。可能有时按下有效果,有时按下没效果。这时候就需要使用到中断了,最简单的做法把按键扫描函数,放在按键中断服务函数中;当按键按下,发生中断,找到中断入口(按键中断服务函数名),执行中断服务函数中的按键扫描代码,这使MCU执行程序的效率大大的提高。具体流程如下图9。 图9 按键外部中断流程图 中断如果只设计一个出来,那就不需要优先级的概念了,优先级就是为了解决多个中断发送,先响应谁,把谁悬起的问题。而在执行中断的过程中,又发生了中断,称为中断嵌套;要弄清楚谁可以打断谁,规律是什么,就需要明白抢占优先级与子优先级的,优先级分组的作用、意义。
4.3 NVIC 4.3.1 NVIC概述 NVIC:嵌套向量中断控制器,用于管理外部所有中断 《1》NVIC 共支持 1 至 240 个外部中断输入(通常外部中断写作 IRQs) 《2》所有的中断控制/状态寄存器均可按字/半字/字节的方式访问 《3》所有 NVIC 的中断控制/状态寄存器都只能在特权级下访问。不过有一个例外——软件触发中断寄存器可以在用户级下访问以产生软件中断 4.3.2 中断的使能与除能 CM3中可以有240对使能位/除能位(SETENA 位/CLRENA 位),每个中断拥有一对。 欲使能一个中断,我们需要写 1 到对应 SETENA 的位中;欲除能一个中断,你需要写 1 到对应的 CLRENA 位中。如果往它们中写 0,则不会有任何效果。 这240个对子分布在8对32位寄存器中,SETENA0, SETENA1…SETENA7,最后一对没有用完,如图10所示。 图10 8对32位寄存器 4.4 软件设计 4.4.1 USART中断配置流程 1.使能模块级中断 2.使能NVIC中断(使能前,可设置优先级分组、抢占优先级、响应优先级) 总体配置框图如下图11。 图11 USART中断配置框图 4.4.2 中断初始化代码解读 打开模块级中断: 找到控制寄存器相应中断位,配置寄存器。 图12 USART中断配置相应位 USART1->CR1 |=1<<5;// 读取数据寄存器不为空 USART1->CR1 |=1<<4;// 检测到空闲线路
打开NVIC中断: 找到密钥 设置分组 图13 打开NVIC中断流程 SCB->AIRCR = 0x05FA0500;//优先级分组5 找到串口1中断向量号,设置优先级 图14串口1中断向量号 分组为5,7-5=2,说明抢占优先级可以有2(7、6)位配置。USART1的向量号位37,可写入下面代码。如图 NVIC->IP[37] = 0xf0; //串口1 抢占优先级3 响应优先级3 图14优先级配置 图15串口1中断使能寄存器 NVIC->ISER[1] = 1<<(37-32);//串口1使能 中断号37
4.4.3 串口1中断服务函数 图16串口1中断寄存器配置与代码 一、接收中断分析: - 读取数据寄存器,接收中断标志位自动清零。
- 对接收中断标志位,写入0,将该位进行清零操作。
rc_w0的理解: 图17 rc_w0的理解: 所以,当发生接收中断,你在读数据寄存器时,接收中断标志位,已经自动清零了,无需手动清零。 图18接收代码的深入理解: 二、空闲中断分析: 空闲中断,第一次空闲,发生中断,空闲标志位置1,读入 USART_SR 寄存器,然后读入 USART_DR 寄存器,可对空闲标志位清零。 注意:当有新的空闲时(相对于前一次),才会发生第二次空闲中断,所以空闲中断与接收中断密不可分、相互联系。接收就不会空闲,空闲就说明没有数据发送过来,所以接收中断常常与空闲中断配合使用。
4.4.4 小结 中断时STM32的灵魂,是一个难点、好用、灵活的东西,用好它能使能的程序变化很灵活、高效,用不好也可是你代码性能变坏,本章只是简单的介绍了STM32的中断。NVIC是个内核的秘书,管理着全部的外部中断,外部的模块若想打开中断,除了打开自己模块的中断开关,还有打NVIC对应的中断开关。
以上的Word格式文档51黑下载地址:
4.NVIC.docx
(2.04 MB, 下载次数: 9)
|