文章中所需图片在对应资源中
中断和事件
中断的特性
嵌套向量中断控制器(NVIC):N嵌套V向量I中断C控制器
-
可屏蔽:可供操作的;不可屏蔽:如电脑复位键不可操作
-
拥有82个中断响应函数,利用函数调用实现中断,中断通道表示函数地址,中断触发代表函数地址的跳转
-
通过4个比特位设置中断通道优先级
-
着重外部中断控制器,从属于NVIC全局中断,EXTI只有23个,用EXTI功能时需要配置NVIC和EXTI参数,外部中断触发依赖于边沿检测,上升沿(低电平→高电平)、下降沿(高电平→低电平)
-
向量表(容器):存放82个中断函数的表,82个可屏蔽中断通道
-
上面灰色可以触发,不能更改,不能自己实现,如Reset、SysTick;
-
优先级高先被执行,通过代码配置优先级,优先级的值越小,优先级越高。
-
函数名即是函数的起始地址,是固定的,系统已经提前声明好了,需要时调用,定义和函数体可以改
中断定义
-
中断是对CPU的干预操作
-
假设把网络和触摸屏当成两个中断,系统能够操作的优先级,不同中断优先级不一样,假设抢占优先级2个比特位
值越小,优先级越高
-
抢占优先级:高优先级任务会直接打断正在执行的低优先级任务;抢占优先级不同时不需要考虑响应优先级
-
响应优先级:前提-->抢占优先级相同;高响应任务不能打断正在执行的低响应任务;处于就绪队列中的任务,先执行高响应优先级任务
-
-
不知道什么时候被触发,就使用中断接收数据,系统自动检测标志位
中断响应函数和普通函数的区别:
-
普通函数的声明定义都需要我们自行书写;中断响应函数系统已经声明过了
-
普通函数需要我们手动调用;中断响应函数是由系统触发调用
-
普通函数可以根据我们的要求自行修改:返回类型、函数名、形参列表;中断响应函数的函数首部是不允许修改的
-
中断响应函数:返回类型是void,形参列表是void,函数名需要参考中断向量表确定
外部中断专线专用
-
LED、按键、蜂鸣器使用的是IO功能,而外部中断是通过当前引脚的检测实现中断功能,使用引脚的复用功能
-
由于每个端口下最多只有0-15总共16根引脚,所以我们针对GPIO的外部中断总共就16根外部中断线
-
所有端口的同号引脚共用一根外部中断线
-
每根外部中断线,同一时刻只能有一根引脚使用其中断功能
-
这16个外部中断线是可以同时工作的
-
-
16个外部中断线对应7个中断响应函数
中断触发和事件触发
-
中断触发
-
通过CPU处理紧急任务(需要软件干预)
-
经过NVIC
-
必须经过中断响应(服务)函数(ISR)
-
举例:按键检测、数据接收
-
-
事件触发
-
触发硬件自动操作(无需CPU干预)
-
直接通过硬件逻辑触发联动外设
-
完全由硬件自动处理
-
举例:定时器触发ADC转换、DMA(直接内存访问)传输
-
代码实现按键外部中断
key.c
//**************************2、按键的EXTI操作***************************// // 1、查看原理图,确定待操作按键对应的端口号及引脚标号 // 2. 添加GPIO、EXTI标准固件库(没有NVIC) // 3、RCC-->端口或功能硬件时钟使能(拷贝上面代码) // 4、GPIO_Init --> // 5、SYSCFG // 6、EXTI_Init // 7、配置外部中断全局参数NVIC初始化 void key_exti_init(void) { GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // 配置为上拉输入模式 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStruct); // 将PA0与外部中断0号线连接起来 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); // 外部中断线的配置 EXTI_InitStruct.EXTI_Line = EXTI_Line0; // 配置为外部中断0号线 EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 配置为中断模式 EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;// 下降沿触发 EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 使能外部中断线 EXTI_Init(&EXTI_InitStruct); // 中断全局配置,主要是配置中断通道和中断优先级 NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // 配置外部中断通道 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F; // 抢占优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0F; // 响应优先级 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 使能NVIC NVIC_Init(&NVIC_InitStruct); // 初始化中断状态标志位 EXTI_ClearFlag(EXTI_Line0); } // 中断响应函数 --> 中断产生,系统会自动调用当前函数 // 1、打开文件 startup_stm32f40_41xxx.s // 2、在文件中找到我们所需的中断服务函数的函数名, 拷贝过来 // 3、在我们自己的代码中实现当前函数。 // 4、函数返回类型和形参列表都是void // 5、获取中断状态,并判断中断是否被触发 // 6、想要中断触发后实现的代码 // 7、操作完成之后,清除中断状态标志位 void EXTI0_IRQHandler(void) { // 判断外部中断0号线是否产生中断 if ( EXTI_GetITStatus(EXTI_Line0) != RESET ) { // 想要中断触发后实现的代码 PFout(9) ^= 1; // 清除中断状态标志位 EXTI_ClearITPendingBit(EXTI_Line0); } } //int main() //{ // // 配置系统滴答时钟的时钟源 // // AHB(168MHz/8) = 21MHz // SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // // led_init(); // key_exti_init(); // 不能与 key_init(); 同时出现 // // while(1) // { // } //}
-
链接操作:添加外围设备驱动SYSCFG
-
调用SYSCFG_EXTI...函数:
-
第一个参数:外部中断线端口号,
-
第二个参数:外部中断线引脚号
-
-
指定该引脚中断功能之后,不能再使用该引脚的IO功能
-
因为SYSCFG是新引入的外围标准设备库,所以也需要RCC使能,跳转去RCC定义中找声明
-
EXTI初始化:去提供的函数找:EXTI_Init(),与GPIO初始化类似,也是结构体类型,需要结构体类型定义变量;
-
各个参数初始化:跳转+
ctrl+f
查找-
第一个外部中断线--0号线
-
第二个类型--中断
-
第三个中断被激活的边沿--下降沿
-
第四个指定状态--使能
-
-
中断全局配置:主要配置中断通道和中断优先级
-
给定函数中查找并调用,同时结构体变量定义
-
参数(成员变量)初始化:
-
第一个中断通道--不在当前文件要在标准库文件中找F40系列或者通用系列复制外部中断0号线的参数
-
第二个抢占优先级--0-15给一个一般设置最低十六进制写法(会有专门函数设置优先级)
-
第三个响应优先级--0-15给一个一般设置最低十六进制写法
-
第四个指定状态--使能
-
中断响应函数的操作:(中断产生,系统自动调用)
-
打开文件
-
找到函数并拷贝
-
从哪找.s文件中
(汇编代码)
-
-
进行实现
-
调用函数重新实现
-
中断初始化函数需要声明
不能与
key_init()
同时出现 -
中断也可以调试:打断点一定要插开发板
-
-
返回类型和形参列表都是void
-
获取中断状态,判断中断是否被触发,检测标志位
-
//
if
判断外部中断0号线是否被触发
-
-
编写中断触发后想要实现的代码
-
// 想要中断触发后实现的代码
-
-
清除中断状态标志位
-
这个函数一般放在中断响应函数外面
-
这个放在中断响应函数里面
-
EXPORT--对外可见(导出符号),WEAK--弱引用(弱符号)
中断过程(中断响应流程)
-
中断检测
-
外设或内核产生中断请求时,置位对应的中断标志位
-
中断信号会经过NVIC的过滤(优先级较高时不能打断也会经过NVIC过滤)
-
-
中断裁决
-
多个中断被同时触发时,NVIC按以下顺序裁决:
-
抢占优先级高的优先执行(数值越小,优先级越高)
-
若抢占优先级相同,响应优先级高的优先执行
-
若优先级完全相同,按中断向量表偏移量决定
-
-
-
上下文保存(保护现场)
-
CPU自动将当前状态保存在主栈中
-
-
向量跳转
-
根据中断向量表中的地址,计算中断向量的偏移量,跳转到对应中断服务函数
-
-
中断服务函数执行
-
中断服务函数的函数名必须要与工程中启动文件中的向量名严格一致
-
中断处理
-
中断嵌套(依赖于优先级,触发点不确定)
-
-
中断退出与上下文恢复(恢复现场)
-
确保中断状态标志位已被清除,防止重复进入中断
-