超级网站模板下载阿里企业邮箱手机版
超级网站模板下载,阿里企业邮箱手机版,wordpress主题汉化中文版,户型图在线设计网站STM32中断EXTI 中断的介绍中断简介中断优先级中断嵌套 STM32中断NVIC介绍作用功能如何分组 EXTI简介EXTI结构EXTI框图 AFIO介绍主要功能和作用#xff1a; 中断配置步骤 一个中断时的代码初始化两个中断时的代码和错误提示 中断的介绍
中断简介
中断#xff1a;在主程序运行… STM32中断EXTI 中断的介绍中断简介中断优先级中断嵌套 STM32中断NVIC介绍作用功能如何分组 EXTI简介EXTI结构EXTI框图 AFIO介绍主要功能和作用 中断配置步骤 一个中断时的代码初始化两个中断时的代码和错误提示 中断的介绍
中断简介
中断在主程序运行过程中出现了特定的中断触发条件中断源使得CPU暂停当前正在运行的程序转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行。 举例当你正在吃饭你发现电话响了你要停下吃饭转而去接电话接完电话后继续回到最初的吃饭的状态。这个电话响了就是中断源。你吃饭才吃了半个饼子这时电话响了你去接电话这个时刻时间点就是断点接完电话继续吃没吃完的饼子也即是回到主程序。
中断优先级
中断优先级当有多个中断源同时申请中断时CPU会根据中断源的轻重缓急进行裁决优先响应更加紧急的中断源 举例: 假如一个饼子。你还没有吃完刚吃到一半这时候电话响了同时呢烧水器的水烧开了有两个事情需要你去处理这时候你就需要抉择一下先执行哪个。很显然烧水器的水是比较重要的因为如果烧水器的水烧开了。不去拔掉的话可能不去拔掉的话可能会引起着火。这时候优先级就出来了。
中断嵌套
中断嵌套当一个中断程序正在运行时又有新的更高优先级的中断源申请中断CPU再次暂停当前中断程序转而去处理新的中断程序处理完成后依次进行返回 举例 假如你现在正在吃饼子饼子吃到一半的时候。突然间电话响了这时候你去另一个房间去接电话但是当走到一半的时候,你发现烧水器在你走到一半路的时候也烧开了这时候呢你转而去把烧水器的接头拔了。然后再去另一个房间接电话。等电话接完你又继续吃剩下的半张饼。
STM32中断
STM32有68个可屏蔽中断通道包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设。 或许您有这个疑惑 stm32有那么多的中断那么CPU是怎么进行管理的呢 答他当然需要一个小助手来帮他处理一些中断的事情而CPU继续忙他的事情。中断则交给了他的小助手。那么他的小助手是谁呢他的小助手就是NVIC。
NVIC介绍
NVIC (Nested Vectored Interrupt Controller) 是 ARM Cortex-M 处理器架构中的一个重要组件在STM32系列微控制器中被广泛应用。它是一个硬件模块用于管理中断请求IRQ和异常处理。
作用 中断管理 NVIC 负责管理外部中断和内部异常的优先级和触发。 中断控制 它允许您配置和控制每个中断的优先级、使能状态和其他相关设置。 中断处理 当发生中断请求时NVIC 根据预先配置的中断优先级和相关设置确定中断的处理顺序。 异常处理 NVIC 还负责处理与系统异常相关的操作如硬件错误、系统调试等。 嵌套处理 NVIC 支持嵌套中断即在处理一个中断时如果另一个中断发生系统能够通过中断优先级来判断是否需要暂时挂起当前中断并处理更高优先级的中断。
功能 优先级管理 NVIC 允许每个中断都分配一个优先级这样可以确保在发生多个中断时系统按照优先级处理。 中断使能 NVIC 控制每个中断的使能状态允许开启或关闭特定中断。 异常处理 对于内部异常如硬件错误或系统异常NVIC 负责相应的异常处理。 中断向量表 NVIC 维护中断向量表用于指示每个中断的处理程序地址。
总结NVIC 是 STM32 系列微控制器中负责管理中断和异常的重要组件它的功能和作用包括中断管理、优先级控制、异常处理等。
为了理解NVIC和CPU的关系这里也给出NVIC的基本结构和举例:
CPU是医生NVIC是医生的小助手也即是叫号系统门外TIMADC等都是病人病人病的程度不一样这时优先级不同。这里线上的n是值得有n个通道但最终NVIC叫号系统只通过一根线告诉cpu医生下一位是哪个病人这样相比医生自己既叫号又给病人看病的效率就高很多了
如何分组 上面分组应注意
分组方式中的数字表示优先级分组的编号数字越小分组的位数越少。抢占优先级和响应优先级的位数决定了可以表示的优先级级别的数量因此位数越少可以表示的优先级级别越少优先级的细粒度也就越高。抢占优先级和响应优先级的取值表示了优先级的具体数值。通常来说数值越小表示的是优先级越高。所以取值越小的优先级级别越高。
抢占优先级和响应优先级中断优先顺序
高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的抢占优先级相同的中断高响应优先级不可以打断低响应优先级的中断抢占优先级相同的中断当两个中断同时发生的情况下哪个响应优先级高哪个先执行如果两个中断的抢占优先级和响应优先级都是一样的话则看哪个中断先发生就先执行优先级数字越小优先级越高越先被执行
EXTI简介
EXTIExtern Interrupt外部中断EXTI可以监测指定GPIO口的电平信号当其指定的GPIO口产生电平变化时EXTI将立即向NVIC发出中断申请经过NVIC裁决后即可中断CPU主程序使CPU执行EXTI对应的中断程序支持的触发方式上升沿/下降沿/双边沿/软件触发支持的GPIO口所有GPIO口但相同的Pin不能同时触发中断 通道数16个GPIO_Pin外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒故而通道数有20个触发响应方式中断响应/事件响应
EXTI结构 所以在STM32配置的时候需要先配置gpio然后再配置AFIO再配置EXTI完成四个配置。首不要忘记打开时钟线RCC。
EXTI框图 AFIO介绍
AFIOAlternate Function I/O是在STM32系列微控制器中的一个重要模块用于管理芯片的引脚复用和外设功能分配。
主要功能和作用 引脚复用 AFIO 允许用户为每个引脚选择不同的功能。由于微控制器的引脚通常具有多种功能比如 GPIO、USART、SPI 等AFIO 可以配置引脚以选择适当的功能。 外设功能分配 有些外设可能需要与多个引脚连接AFIO 可以配置这些外设与引脚之间的映射关系以确保外设正常工作。 复用模式配置 AFIO 允许配置每个引脚的复用模式包括推挽、开漏和复用功能选择等。 中断和事件控制 AFIO 还可以配置一些特殊的中断和事件触发方式比如外部中断线的映射、中断触发方式等。 Debug 功能 AFIO 也与调试功能相关可以配置调试接口和引脚。
中断配置步骤 一个中断时的代码初始化
这里使用的是EXTI10-15的即10~15共用一个中断当中断来时并不确定哪个来的。所以中断函数内需要判断下是不是所需的中断。
#include stm32f10x.h // Device headervoid CountSensor_Init(void)
{//看该模块的原理图可知默认有个上拉电阻故而通电时端口DO是高电平也即是B14高电平低电平指示灯亮RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//配置AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//因为EXTI和NVIC的时钟是一直在开着的所以不需要再开启时钟//配置GPIOGPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;//设置为上拉这里看红外对射的电路原理图和GPIO参考手册8.2的EXTI推荐可知可知GPIO_InitStructure.GPIO_PinGPIO_Pin_14;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStructure);//配置AFIOGPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14); //配置EXTI打开Library分组/找到stm32f10x_exti.h查看里面的函数EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_LineEXTI_Line14;EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt ;//选择事件模式为中断触发EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;//设置为下降沿触发EXTI_InitStructure.EXTI_LineCmdENABLE;//使能EXTI_Init( EXTI_InitStructure);//NVIC的配置因为NVIC是内核外设所以他的库函数被分配到杂项这里了也即是不misc.h里NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//注意分组代码在整个芯片中只需要分组一次就行可以将其放在int main里NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannelEXTI15_10_IRQn;//从f103.h的md后缀找//因为上面选择了分组二即NVIC_PriorityGroup_2故而下面的抢占和非抢占都需使用分组二的数值NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;NVIC_InitStructure.NVIC_IRQChannelSubPriority1;//一般优先级在多个中断源同时申请产生拥挤时才有作用因为这里中断只有一个所以设置比较随意NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;//使能NVIC_Init( NVIC_InitStructure);//初始化}void EXTI15_10_IRQHandler(void) //中断函数 这里的中断函数名字是固定的参考/Start/startup_stm32f10x_md.s里面带有IRQhandeler的写法
{//因为这个中断15~10的中断都能进来所以需要判断下是不是14的进来的。//这时候需要打开exti.h查看EXTI_GetITStatus()函数来判断if(EXTI_GetITStatus(EXTI_Line14)SET)//14的响应这里为什么判断SET看EXTI_GetITStatus函数的说明他的返回值是SET和RESET{//中断结束后一定一定要调用一下清除中断标志位的函数。因为上面中断标志位置1了就会进入中断函数如果不清除就会一直申请中断EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位}}
两个中断时的代码和错误提示 *//切记不要这样写因为对端口1使能会把端口0的值覆盖掉这样只配置了1端口。 //要一个一个的配置这里NVIC_Init( NVIC_InitStruct);就把值传递过去了然后再配置端口0也就是分开配置单独配置0的和1的。这样是没有任何问题的,下方给出错误的代码 错误的代码: NVIC_InitStructure.NVIC_IRQChannel EXTI0_IRQn ;//对0端口进行配置NVIC_InitStructure.NVIC_IRQChannel EXTI1_IRQn ;//对1端口,NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;//使能NVIC_InitStructure.NVIC_IRQChannelSubPriority1;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;NVIC_Init(NVIC_InitStructure);正确配置如下
#include stm32f10x.h // Device header
int16_t Encoder_Count;//正反转计次有正转和反转所以定义的类型为int16_t有符号类型/*** brief 旋转编码器初始化/中断* param 无 * retval 无*/
void Encoder_Init(void)
{//GPIO时钟配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//AFIO使能配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//GPIO配置GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;//配置为上拉输入GPIO_InitStructure.GPIO_PinGPIO_Pin_0 | GPIO_Pin_1;//配置端口GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStructure);//AFIO配置注意此处也要分开配置不要//GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0|GPIO_PinSource1);//GPIO_EXTILineConfig() 函数用于将指定的 GPIO 端口引脚映射到外部中断线上//但是在一个函数调用中只能映射一个引脚到一个外部中断线上。//结构体能或是因为他不是传递的参数函数传参或了以后传递的是两个数或操作之后的值而不是传了两个参数//如果想要将 GPIOB 的 Pin 0 和 Pin 1 映射到外部中断线上你需要分别调用 GPIO_EXTILineConfig() 函数两次GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//EXTI配置EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_LineEXTI_Line0|EXTI_Line1;EXTI_InitStructure.EXTI_LineCmdENABLE;//使能EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt;//选择中断触发EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;//下降沿触发EXTI_Init( EXTI_InitStructure);//NVIC初始化//中断分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//切记不要这样写因为对端口1使能会把端口0的值覆盖掉这样只配置了1端口。//要一个一个的配置这里NVIC_Init( NVIC_InitStruct);就把值传递过去了然后再配置端口0这样是没有任何问题的/*NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel EXTI0_IRQn ;//对0端口进行配置NVIC_InitStructure.NVIC_IRQChannel EXTI1_IRQn ;//对1端口,NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;//使能NVIC_InitStructure.NVIC_IRQChannelSubPriority1;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;NVIC_Init(NVIC_InitStructure);*/// 对0端口进行配置NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; // 使能NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;//响应优先级NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;//抢占优先级NVIC_Init(NVIC_InitStructure);// 对1端口进行配置NVIC_InitStructure.NVIC_IRQChannel EXTI1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; // 使能NVIC_InitStructure.NVIC_IRQChannelSubPriority 2;//数值越大优先级越小NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;NVIC_Init(NVIC_InitStructure);//记得写一定别忘记了切记切记}/*** brief 计次函数正转计次反转计数--* param 无 * retval temp次数*/int16_t Encoder_GetCount(void)
{//不清零的话如果第二次调用这个函数就是从目前的值开始加减int16_t temp;tempEncoder_Count;Encoder_Count0;return temp;
}/*** brief EXTI0中断函数* param 无 * retval 无*/
void EXTI0_IRQHandler(void)//函数名固定的在startup/start_stm32f10x_md.h可找到函数名
{if(EXTI_GetITStatus(EXTI_Line0)SET){if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)0)//反转{Encoder_Count--;}EXTI_ClearITPendingBit(EXTI_Line0);//清除标志位}}/*** brief EXTI1中断函数 * param 无 * retval 无*/
void EXTI1_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line1)SET){if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)0)//正转 当A口触发下降沿此时看B口电平状态{Encoder_Count;}EXTI_ClearITPendingBit(EXTI_Line1);//清除标志位}}c
//在主函数里用
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//中断标志位
void EXTI_ClearFlag(uint32_t EXTI_Line);//清除中断标志位//在中断函数里用:
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//获取中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除中断标志位
完结撒花来支持吧^ o ^----------------------------------------(doge)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/87309.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!