01嵌套向量中断控制器——nvicnvic的全称是nested vectoredinterrupt controller,即嵌套向量中断控制器。控制着整个芯片中断相关的功能,通过对nvic寄存器进行配置可以实现对内核和片上外设的中断的控制。但是各个芯片厂商在设计芯片的时候会对 cortex-m4内核里面的 nvic进行裁剪,把不需要的部分去掉,所以说 stm32的 nvic 是 cortex-m4的 nvic 的一个子集,只是用到了nvic的一部分功能,其余的保留以后备用。
抢占式优先级(占先式优先级)和响应优先级(子优先级)
抢占优先级(占先式优先级)
抢占,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数a 的过程中被中断b 打断,执行完中断服务函数b 再继续执行中断服务函数a)。
通俗的讲,完成某一件事正常是有顺序,先完成事件 a ,再完成事件 b,假如,张三现在在做事件 a ,突然李四叫张三去做事件 b ,那么现在就有一个问题,张三是先完成事件 a ?还是去做事件 b ?这里就需要看看那个事件的优先级了,倘若事件 a ,比事件 b 比较重要,那么先完成事件 a 后再完成事件 b ,假如是事件 b, 比事件 a 比较重要,则张三需要先完成事件 b ,再回来继续完成事件 a ,不管事件 a,有没有完成。
在片内中设置好事件执行的优先级之后,总是高优先级先执行完然后再执行低优先级的。编号越低优先级越高。即 “0”的优先级最高。
响应优先级(子优先级)
响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达, 则先处理响应优先级高的中断。
通俗的讲,同时有事件 a 、事件 b 、事件 c ,其中事件 a 的抢占优先级要高于事件 b 、事件 c ,其次事件 b 、事件 c 的抢占优先级一样,在完成事件 a 之后,假如事件 b 、事件 c 这两件事同时“到达”,那这个时候响应属性的作用就开始发挥了,假如事件 b 的响应属性高于事件 c ,则优先完成事件b。
响应和抢占优先级,有种抢占优先级里面包含着响应优先级的感觉,只不过抢占优先级强调的事,我正在做某一件事,有另外一件事来打断我现在在做的这件。响应优先级则强调的是,同时“到达”,我先处理哪一件事的问题。
nvic 的定义在 nvic 有一个专门的寄存器:中断优先级寄存器 nvic_iprx,用来配置外部中断的优先级,ipr宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。但是绝大多数 cm3 芯片都会精简设计,以致实际上支持的优先级数减少,在 f103 中,只使用了高 4bit,如下所示:
在仅剩的4位中,又包含抢占优先级和响应优先级。理论是会有16个中断源,但是stm32又进行了分组,共分为5组,如下:
在库文件misc.c和misc.h中分别用宏定义定义了 nvic_ptioritygroup这五组分组源。
#define nvic_prioritygroup_0 ((uint32_t)0x700) /* 0 bits for pre-emption priority 4 bits for subpriority */#define nvic_prioritygroup_1 ((uint32_t)0x600) /* 1 bits for pre-emption priority 3 bits for subpriority */#define nvic_prioritygroup_2 ((uint32_t)0x500) /* 2 bits for pre-emption priority 2 bits for subpriority */#define nvic_prioritygroup_3 ((uint32_t)0x400) /* 3 bits for pre-emption priority 1 bits for subpriority */#define nvic_prioritygroup_4 ((uint32_t)0x300) /* 4 bits for pre-emption priority 0 bits for subpriority */通过misc.c文件中定义的 “ **nvic_prioritygroupconfig(uint32_t nvic_prioritygroup) ** ” 函数:
void nvic_prioritygroupconfig(uint32_t nvic_prioritygroup){ /* check the parameters */ assert_param(is_nvic_priority_group(nvic_prioritygroup)); /* set the prigroup[10:8] bits according to nvic_prioritygroup value */ scb- >aircr = aircr_vectkey_mask | nvic_prioritygroup;
配置响应优先级及应用举例例如配置以下一位抢占优先级,三位子优先级
nvic_prioritygroupconfig(nvic_prioritygroup_1);//中断优先级分组:2位的抢占,2位的子优先级在选择完组源之后,就需要对该组的中断源、抢占优先级和响应优先级、配置通道的开启进行配置 。
通过在 misc.h 中的结构体,进行配置
typedef struct{uint8_t nvic_irqchannel;//中断源uint8_t nvic_irqchannelpreemptionpriority;//抢占优先级uint8_t nvic_irqchannelsubpriority;//响应优先级functionalstate nvic_irqchannelcmd;//是否使能} nvic_inittypedef;针对每个中断,设置对应的抢占优先级和响应优先级,下面以中断源为 usart2_irqn,抢占优先级为1,响应优先级为0,的例子,优先级分组为一。
static void nvic_configuration(void){nvic_inittypedef nvic_initstructure;nvic_prioritygroupconfig(nvic_prioritygroup_2); /* 嵌套向量中断控制器组选择 */nvic_initstructure.nvic_irqchannel = debug_usart_irq; /* 配置usart为中断源 */nvic_initstructure.nvic_irqchannelpreemptionpriority = 0; /* 抢断优先级*/nvic_initstructure.nvic_irqchannelsubpriority = 2; /* 子优先级 */nvic_initstructure.nvic_irqchannelcmd = enable; /* 使能中断 */ nvic_init(&nvic_initstructure); /* 初始化配置nvic */}其中中断源通过在 stm32f10x.h中的结构体
typedef enum irqn{ . . . . .}irqn_type;至此,关于nciv的简单配置就完成了
02外部中断/事件控制器——extiexti简介
exti(external interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。exti 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
中断/事件线
exti 有 20 个中断/事件线,每个 gpio 都可以被设置为输入线,占用 exti0 至 exti15,还有另外七根用于特定的外设事件。这里得并不是以pa的整个系列作为一个中断/事件线,而是以pa0,pb0,pc0 …… pg0作为一个中断源,如下图所示。
16个中断线的不是每个中断都有独立的中断服务函数,io口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。
从表可以看出外部中断exti5_9共用一个服务函数,外部中断exti15_10共用一个服务函数,对应的中断函数在启动文件里面
exti0_irqhandlerexti1_irqhandlerexti2_irqhandlerexti3_irqhandlerexti4_irqhandler因为这里是通过stm32 的引脚,通过映射的方法,让gpio具有了中断的功能,所以在使用某一个gpio作为中断的引脚的时候,就需要调动映射服务函数。( “ stm32f10x_gpio.c” 中的 “ gpio_extilineconfig”)
void gpio_extilineconfig(uint8_t gpio_portsource, uint8_t gpio_pinsource){ uint32_t tmp = 0x00; /* check the parameters */ assert_param(is_gpio_exti_port_source(gpio_portsource)); assert_param(is_gpio_pin_source(gpio_pinsource)); tmp = ((uint32_t)0x0f) < exticr[gpio_pinsource > > 0x02] &= ~tmp; afio- >exticr[gpio_pinsource > > 0x02] |= (((uint32_t)gpio_portsource) < stm32f10x_exti.h
exti为中断模式:
exti_trigger :
最后一步则是选择exti的信号源,通过下面该函数,进行配置
void gpio_extilineconfig(uint8_t gpio_portsource, uint8_t gpio_pinsource)以上中断服务函数的初始化就完成了,接下来则是编写中断服务函数
void exti0_irqhandler (void){ //要执行的内容 exti_clearitpendingbit( 相应的中断线);//查询相应中断线和exti_line 一样} exti0_irqhandler 在启动文件中查找
void exti_clearitpendingbit( 相应的中断线):
其作用就是清除进入中断时对寄存器某个位置 1,进行清 0
理论完成,进入喜闻乐见的实验环节
以按键触发中断为例子,触发引脚为:pa1
简单的逻辑过程
exit.c
#include exti.hstatic void nvic_configuration(void){ nvic_inittypedef nvic_initstructure; /* 嵌套向量中断控制器组选择 */ nvic_prioritygroupconfig(nvic_prioritygroup_2); /* 配置usart为中断源 */ nvic_initstructure.nvic_irqchannel = exti1_irqn; /* 抢断优先级*/ nvic_initstructure.nvic_irqchannelpreemptionpriority = 0; /* 子优先级 */ nvic_initstructure.nvic_irqchannelsubpriority = 2; /* 使能中断 */ nvic_initstructure.nvic_irqchannelcmd = enable; /* 初始化配置nvic */ nvic_init(&nvic_initstructure);}void exit_config(void){ gpio_inittypedef gpio_initstruct; rcc_apb2periphclockcmd(rcc_apb2periph_gpioa , enable); gpio_initstruct.gpio_mode= gpio_mode_in_floating ; gpio_initstruct.gpio_pin= gpio_pin_1 ; gpio_initstruct.gpio_speed= gpio_speed_50mhz ; gpio_init(gpioa,&gpio_initstruct); rcc_apb2periphclockcmd(rcc_apb2periph_afio, enable); exti_inittypedef exti_initstruct; exti_initstruct.exti_line=exti_line1 ; exti_initstruct.exti_linecmd=enable ; exti_initstruct.exti_mode= exti_mode_interrupt; exti_initstruct.exti_trigger= exti_trigger_falling; nvic_configuration(); exti_init(&exti_initstruct);}void exti1_irqhandler (void){ systick_config_delay_ms(10); gpio_resetbits(gpioc, gpio_pin_13 ); exti_clearitpendingbit( exti_line1 );//查询相应中断线和exti_line 一样}exit.h
#ifndef _exit_h#define _exit_h#include misc.h#include stm32f10x_gpio.h#include stm32f10x.h#include led.h#include systick.h#include stm32f10x_exti.hvoid exit_config(void);static void nvic_configuration(void);#endifmain.c
#include led.h#include stm32f10x.h#include exti.h#include systick.hint main(void){ systick_init(); led_gpio_config() ; exit_config( ); while(1) { }}
4·29首都网络安全日 长亭科技创新升级“安全兵法”
基于CAN总线信号的波形解码和报文解码不一致的情况分析
浅析计算机系统的各种层次结构
利用荧光氧气传感器LOX-02-S检测高原氧浓度
【技术】扬尘监测设备的光学原理及激光原理
单片机的NVIC与EXTI中断详解
三星利用霍尼韦尔的量子计算机来改善电池设计
什么是USB-PD?
常用无线技术的技术基础和相对优势
转载丨填补国内市场空白!这家人机接口芯片厂商另辟蹊径
如何通过流策略实现VLAN间的访问权限?
语音芯片电路图
联想发布LaVie家庭一体机,搭载LG的屏幕发声技术将于3月上市
NVIDIA宣布正打造英国最强大的超级计算机,将借助AI解决医疗难题
带宽范围为120dB的双对数变换器ADL5310
光谱分布图及波长
加速“芯”动力|2022集成电路测试工程师研修班(第三期)圆满落幕
电线安全载流量的计算方法
大健康将是LED未来发展趋势?
Fluke F317便携式真有效值钳型表的功能介绍