NVIC和EXTI

2024-05-08 19:18
文章标签 exti nvic

本文主要是介绍NVIC和EXTI,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

NVICNest Vector Interrupt Controller,嵌套中断向量控制器,是用来管理中断嵌套的,核心任务在于其优先级的管理。NVIC给每个中断赋予先占优先级(抢占优先级)和次占优先级(响应优先级)。

CM3 内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32并没有使用CM3内核的全部东西,而是只用了它的一部分,STM3276 个中断,包括16 个内核中断和60 个可屏蔽中断,具有16级可编程的中断优先级。而我们常用的就是这60个可屏蔽中断。

STM32CM3内核的中断向量表进行了重新编排,将编号-36的中断向量定义为系统异常,编号为负的内核异常不能被设置优先级,从编号7开始为外部中断,这些中断优先级都是可以自行设置的。

EXTIExternal Interrupt,外部中断,通过GPIO检查输入脉冲,引起中断时间,打断原来的代码执行流程,进入到中断服务函数中进行处理,处理完后再返回中断之前的代码中执行。

STM32 EXTI控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM3219 个外部中断为 :
线 0~15:对应外部IO口的输入中断。
线 16:连接到PVD输出。
线 17:连接到RTC闹钟事件。
线 18:连接到USB唤醒事件。

 

EXTI中断步骤:

① 配置端口为输入模式

② 开启与该IO口相对应的线上中断/事件,并设置触发条件

③ 配置中断分组(NVIC)并使能中断

④ 中断函数

 

一、配置端口为输入模式

void GPIOA_Init(void)

{

   GPIO_DeInit(GPIOA);

RCC->APB2ENR|=1<<2;     //使能PORTA时钟

GPIOA->CRL&=0XFFFFFFF0;//PA0设置成上拉输入   

GPIOA->CRL|=0X00000008;   

}

在对端口进行任何操作之前,必须打开对应的时钟信号,其设置才能生效。这里使

用了GPIOA.00 端口作为中断0输入,作为输入时一般我们设置为上拉输入,如果要

设置成浮空输入的话,外部一定要加上拉电阻,这样对于过滤输入波动很有益处(

设在电压在3.3-2.0之间进行波动,时间上没尝试按键操作,因为一旦有按键,就应

该为0,那么接了上拉的话,除非产生了低电平,否则小波动都会被拉高过滤掉)

 

二、开启与该IO口相对应的线上中断/事件,并设置触发条件

这一步封装在函数void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)中,可以直接调用,例如:Ex_NVIC_Config(GPIO_A,0,RTIR); //设置PA0上升沿触发

  Ex_NVIC_Config(GPIO_A,13,FTIR);//设置PA13)下降沿触发

该函数为 Ex_NVIC_Config,该函数有3个参数:GPIOxGPIOA~G0~6),在sys.h里面有定义。代表要配置的IO口。BITx则代表这个IO口的第几位。TRIM为触发方式,低2位有效(0x01代表下降触发;0x02代表上升沿触发;0x03代表任意电平触发)。其代码如下:
/**************************

该函数只针对GPIOA~G;不包括PVDRTCUSB唤醒这三个,参数:GPIOA~G0~6),代表GPIOA~G;BITx:需要使能的位;TRIM:触发模式,1,上升沿;2,下降沿;3,任意电平触发;该函数一次只能配置1IO 口,多个IO 口,需多次调用,该函数会自动开启对应中断,以及屏蔽线

***************************/

void Ex_NVIC_Config(u8 GPIOxu8 BITxu8 TRIM)
{

u8 EXTADDR;
u8 EXTOFFSET;
EXTADDR=BITx/4;//得到中断寄存器组的编号
EXTOFFSET=(BITx%4)*4;
RCC->APB2ENR|=0x01;//使能IO复用时钟
AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;//EXTI.BITx映射到GPIOx.BITx
//自动设置
EXTI->IMR|=1<<BITx;//开启line BITx上的中断
EXTI->EMR|=1<<BITx;//不屏蔽lineBITx上的事件
if(TRIM&0x01)EXTI->FTSR|=1<<BITx;//lineBITx 上事件下降沿触发
if(TRIM&0x02)EXTI->RTSR|=1<<BITx;//lineBITx 上事件上升降沿触发
}

EXTICR(External interrupt configuration register)即外部中断配置寄存器。

因为STM32 任何一个IO口都可以配置成中断输入口,但是IO口的数目远大于中断线数(16个),所以我们需要选择哪一个中断是经由那个IO口输入的。于是STM32就这样设计,GPIOA~GPIOG[15:0]分别对应中断线15~0。这样每个中断线对应了最多7IO 口,以线0为例:它对应了GPIOA.0PIOB.0GPIOC.0GPIOD.0GPIOE.0GPIOF.0GPIOG.0。而中断线每次只能连接到1IO 口上,这样就需要EXTICR来决定对应的中断线配置到哪个GPIO上了。寄存器EXTIR有四组,在书写时要注意。具体对应关系如下:0000: PA[x] pin0001: PB[x] pin0010: PC[x] pin0011: PD[x] pin0100: PE[x] pin0101: PF[x] pin0110: PG[x] pin。假设我们需要设定外部中断0GPIOA_0来控制,那么我就可以写成AFIO->EXTIR[0] |=0X00;  


Ex_NVIC_Config,首先根据GPIOx的位得到中断寄存器组的编号,即EXTICR的编号,在EXTICR里面配置中断线应该配置到GPIOx的哪个位。然后使能该位的中断及事件,最后配置触发方式。这样就完成了外部中断的的配置了。从代码中可以看到该函数默认是开启中断和事件的。其次还要注意的一点就是该函数一次只能配置一个IO口,如果你有多个IO口需要配置,则多次调用这个函数就可以了。

三、配置中断分组(NVIC)并使能中断

这一步封装在函数void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)里面可以直接调用,例如

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);    //抢占2,子优先级2,组2
    NVIC 设置函数MY_NVIC_Init,该函数有4个参数,分别为:NVIC_PreemptionPriorityNVIC_SubPriorityNVIC_ChannelNVIC_Group。第一个参数NVIC_PreemptionPriority为中断抢占优先级数值,第二个参数NVIC_SubPriority为中断子优先级数值,前两个参数的值必须在规定范围内,否则也可能产生意想不到的错误。第三个参数NVIC_Channel为中断的编号(范围为0~59),最后一个参数NVIC_Group为中断分组设置(范围为0~4)。

/********************设置NVIC****************
*NVIC_PreemptionPriority:抢占优先级
*//NVIC_SubPriority :响应优先级
*NVIC_Channel :中断编号
*NVIC_Group :中断分组 0~4
*注意优先级不能超过设定的组的范围!否则会有意想不到的错误
*组划分:
*0:0 位抢占优先级,4 位响应优先级
*1:1 位抢占优先级,3 位响应优先级
*2:2 位抢占优先级,2 位响应优先级
*3:3 位抢占优先级,1 位响应优先级
*4:4 位抢占优先级,0 位响应优先级
*NVIC_SubPriority NVIC_PreemptionPriority的原则是,数值越小,越优先

************************************/
void MY_NVIC_Init(u8 NVIC_PreemptionPriorityu8 NVIC_SubPriorityu8NVIC_Channelu8 NVIC_Group)
{
  u32 temp;
  u8 IPRADDR=NVIC_Channel/4; //每组只能存4个,得到组地址
  u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
  IPROFFSET=IPROFFSET*8+4; //得到偏移的确切位置
  MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
  temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
  temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
  temp&=0xf;//取低四位

if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位(要清除的话,相反操作就OK)
   else

NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级和抢断优先级
}

MY_NVIC_PriorityGroupConfigNVIC的分组函数,该函数的参数NVIC_Group为要设置的分组号,可选范围为0~4,总共5组:EXTI0EXTI1EXTI2EXTI3EXTI4Line0~Line4EXTI15_10Line15~Line10EXTI9_5Line9~Line5。如果参数非法,将可能导致不可预料的结果。

/***************设置NVIC分组*****************
*NVIC_Group:NVIC 分组 0~4总共5

************************************/

void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)
{
  u32 temptemp1;
  temp1=(~NVIC_Group)&0x07;//取后三位

temp1<<=8;

temp=SCB->AIRCR; //读取先前的设置

temp&=0X0000F8FF; //清空先前分组

temp|=0X05FA0000; //写入钥匙

temp|=temp1;

SCB->AIRCR=temp; //设置分组
}

MY_NVIC_PriorityGroupConfig 函数设置中断优先级分组的思路:STM325 个分组是通过设置SCB->AIRCRBIT[10:8]来实现的,SCB->AIRCR的修改需要通过在高16位写入0X05FA这个密钥才能修改的,故在设置AIRCR之前,应该把密钥加入到要写入的内容的高16位,以保证能正常的写入AIRCR。在修改AIRCR的时候,我们一般采用读->->写的步骤,来实现不改变AIRCR原来的其他设置。MY_NVIC_PriorityGroupConfig分组函数在每个系统里面只要设置一次就够了,设置多次,则是以最后的那一次为准。但是只要多次设置的组号都是一样,就没事。否则前面设置的中断会因为后面组的变化优先级会发生改变,这点在使用的时候要特别注意!一个系统代码里面,所有的中断分组都要统一,以上代码对要配置的中断号默认是开启中断的。也就是ISER中的值设置为1了。

四、中断函数

A.  中断函数名的书写有要求,否则会找不到中断入口。

stm32f10x_it.c是专门用来存放中断服务函数的。

3.5 库函数之前,在stm32f10x_it.c中就预先写好了个外部中断的函数名称,我们只要将对应的执行过程填充进去就可以。

3.5库函数中,文件中默认只有几个福安与系统异常的中断服务函数,而且都是空函数,在需要的时候自行编写。但是中断服务函数名是不可以自己定义,中断服务函数的名字必须要与启动文件startup_stm32f10x_hd.s中的中断向量表中定义一致。

B. 在进入中断后我们需要做的动作有 2 部,一次执行中断过程,2 是清除中断挂起标识,因为执行完毕了。如果不清除中断挂起标识,则无法再次进入中断。

例程:

void EXTI0_IRQHandler(void)

{

 delayMs(10);

  if(((GPIOA->IDR)&0x01)==0)

 {

      while(((GPIOA->IDR)&0x01)==1);            

      GPIOA->ODR  = ~(GPIOA->ODR&0X02);

         EXTI->PR=1;    

   }     

}

这里 EXTI->PR=1,即想中断挂起寄存器中写1,清除中断

 

这篇关于NVIC和EXTI的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971197

相关文章

C8T6超绝模块--EXTI

C8T6超绝模块–EXTI 大纲 控制流程结构体分析EXTI实现按键 具体案例 控制流程 这里是流程框图,具体可以去看我STM32专栏的EXTI的具体分析 结构体分析 typedef struct {uint32_t EXTI_Line; // 中断/事件线EXTIMode_TypeDef EXTI_Mode; // EXTI 模式EXTITrigger_TypeDef EXTI_

江协科技STM32学习- P11 中断系统,EXTI外部中断

🚀write in front🚀   🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​  💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚  🚀Projeet source code🚀    💾工程代码放在了本人的Gitee仓库:iPickCan (iPickCan

NVIC_PriorityGroup_2

非本人原创,转载自http://blog.csdn.net/denghuanhuandeng/article/details/8350392 STM32的NVIC理解  例程:  /* Configure one bit for preemption priority */   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    /*

【STM32单片机_(HAL库)】3-4-3【中断EXTI】【智能排队控制系统】排队系统代码框架搭建

3-4-2系统框图及硬件接线 3.软件 beep、exti、gate、LCD1602、led、tasks驱动文件添加GPIO常用函数中断配置流程main.c程序 #include "sys.h"#include "delay.h"#include "led.h"#include "tasks.h"#include "gate.h"#include "beep.h"#include

【STM32单片机_(HAL库)】3-3【中断EXTI】使用SysTick模拟多线程

1.硬件 STM32单片机最小系统 LED灯模块 硬件接线 STM32LED1LED2PB8负极PB9负极5V5V5V 2.软件 led、tasks驱动文件添加GPIO常用函数main.c程序 #include "sys.h"#include "delay.h"#include "led.h"#include "tasks.h"int main(void){HAL_Init

【STM32单片机_(HAL库)】3-2-1【中断EXTI】【电动车报警器项目】震动点灯

1.硬件 STM32单片机最小系统LED灯模块震动传感器模块 2.软件 exti驱动文件添加GPIO常用函数中断配置流程main.c程序 #include "sys.h"#include "delay.h"#include "led.h"#include "exti.h"int main(void){HAL_Init(); /* 初始

STM32 EXTI(外部中断)和NVIC(嵌套向量中断控制器)学习

STM32 EXTI(外部中断)和NVIC(嵌套向量中断控制器)学习 在STM32中EXTI有0~18个事件/中断,0~4各自都是单独的一个通道,5~9是共一个通道,10~15共享一个通道,16/17/18各自独立用到一个通道 在STM32中NVIC是嵌套向量中断控制器,分为0~4五个组,称之为(Group) NVIC_PriorityGroup_0 ~ NVIC_Priorit

ARM32开发--外部中断EXTI

知不足而奋进 望远山而前行 目录 文章目录 前言 目标 内容 外部中断概念 中断触发机制 中断触发源 硬件外部中断 需求 开发流程 关心的内容 完整代码 软件外部中断 需求 开发流程 关心的内容 完整代码 中断消抖处理 系统计数模块 自定义计数器 systick完成代码 消抖完整逻辑 总结 前言 在许多嵌入式系统中,包括STM32和GD3

立创·天空星开发板-GD32F407VE-EXTI

本文以 立创·天空星开发板-GD32F407VET6-青春版 作为学习的板子,记录学习笔记。 立创·天空星开发板-GD32F407VE-EXTI 中断硬件触发中断示例软件触发中断示例 中断 中断分为内部中断和外部中断 外部中断是由外部设备(如按键、传感器、通信接口等)产生的中断请求信号,需要通过中断控制器进行处理。 通常情况下,外部中断是通过中断输入引脚连接到

Cortex-M7——NVIC

Cortex-M7——NVIC 小狼@http://blog.csdn.net/xiaolangyangyang 一、NVIC架构 二、中断及异常编号 三、中断屏蔽寄存器(__disable_irq和__enable_irq操作的是PRIMASK寄存器) 四、中断分组寄存器(SCB->AIRCR[10:8]) 五、NVIC寄存器