1、根本概念
ARMCoetex-M3内核共支撑256个中止,其间16个内部中止,240个外部中止和可编程的256级中止优先级的设置。STM32现在支撑的中止共84个(16个内部+68个外部),还有16级可编程的中止优先级的设置,仅运用中止优先级设置8bit中的高4位。
STM32可支撑68个中止通道,现已固定分配给相应的外部设备,每个中止通道都具有自己的中止优先级操控字节PRI_n(8位,可是STM32中只运用4位,高4位有用),每4个通道的8位中止优先级操控字构成一个32位的优先级寄存器。68个通道的优先级操控字至少构成17个32位的优先级寄存器。
4bit的中止优先级可以分红2组,从高位看,前面界说的是抢占式优先级,后边是呼应优先级。依照这种分组,4bit总共可以分红5组
第0组:一切4bit用于指定呼应优先级;
第1组:最高1位用于指定抢占式优先级,后边3位用于指定呼应优先级;
第2组:最高2位用于指定抢占式优先级,后边2位用于指定呼应优先级;
第3组:最高3位用于指定抢占式优先级,后边1位用于指定呼应优先级;
第4组:一切4位用于指定抢占式优先级。
所谓抢占式优先级和呼应优先级,他们之间的联系是:具有高抢占式优先级的中止可以在具有低抢占式优先级的中止处理进程中被呼应,即中止嵌套。
当两个中止源的抢占式优先级相一起,这两个中止将没有嵌套联系,当一个中止到来后,假如正在处理另一个中止,这个后到来的中止就要比及前一个中止处理完之后才干被处理。假如这两个中止一起抵达,则中止操控器依据他们的呼应优先级凹凸来决议先处理哪一个;假如他们的抢占式优先级和呼应优先级都持平,则依据他们在中止表中的排位次序决议先处理哪一个。每一个中止源都必须界说2个优先级。
有几点需求留意的是:
1)假如指定的抢占式优先等级或呼应优先等级超出了选定的优先级分组所限制的规模,将或许得到意想不到的成果;
2)抢占式优先等级相同的中止源之间没有嵌套联系;
3)假如某个中止源被指定为某个抢占式优先等级,又没有其它中止源处于同一个抢占式优先等级,则可以为这个中止源指定恣意有用的呼应优先等级。
2、GPIO外部中止
STM32中,每一个GPIO都可以触发一个外部中止,可是,GPIO的中止是以组位一个单位的,同组间的外部中止同一时间只能运用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,假如咱们运用PA0作为外部中止源,那么其他就不可以再运用了,在此情况下,咱们智能运用类似于PB1,PC2这种结尾序号不同的外部中止源。每一组运用一个中止标志EXTIx。EXTI0 – EXTI4这5个外部中止有着自己的独自的中止呼应函数,EXTI5-9共用一个中止呼应函数,EXTI10-15共用一个中止呼应函数。
关于中止的操控,STM32有一个专用的办理机构:NVIC。关于NVIC的具体解说,可以参阅《ARM Cortex-M3威望攻略》,Joseph Yiu著,宋岩译,北京航空航天大学出书社出书,第8章NVIC与中止操控。中止的使能,挂起,优先级,活动等等部都是NVIC在办理的。
3 、程序开发
其实上面那些根本概念和常识仅仅对STM32的中止体系有一个大约的知道,用程序说话将会更可以加深怎么运用中止。运用外部中止的根本进程如下:
1.设置好相应的时钟;
2.设置相应的中止;
3.IO口初始化;
4.把相应的IO口设置为中止线路(要在设置外部中止之前)并初始化;
5.在挑选的中止通道的呼应函数中中止函数。
试验进程:经过按键来触发相应的中止。依据原理图,K2/K1/K0衔接的是PE2/PE3/PE4,因而我将用EXTI2/EXTI1/EXTI0三个外部中止。PB5/PE5别离衔接了两个LED灯。中止的作用是按下按键,相应的LED灯将会被操作。
1.设置相应的时钟
首要需求翻开GPIOB、GPIOE(因为按键别的一端衔接的是PE口)。然后由所以要用于触发中止,所以还需求翻开GPIO复用的时钟。具体代码如下:
void RCC_cfg()
{
//翻开PE PB端口时钟,而且翻开复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
}
设置相应的时钟所需求的RCC函数在stm32f10x_rcc.c中,所以要在工程中增加此文件。
2.设置好相应的中止
设置相应的中止实际上便是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里边有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。具体代码如下:
void NVIC_cfg()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //挑选中止分组2
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQChannel; //挑选中止通道2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中止优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //呼应式中止优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中止
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQChannel; //挑选中止通道1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占式中止优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //呼应式中止优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中止
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel; //挑选中止通道0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占式中止优先级设置为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //呼应式中止优先级设置为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中止
NVIC_Init(&NVIC_InitStructure);
}
因为有3个中止,因而依据前文所述,需求有3个bit来指定抢占优先级,所以挑选第2组。
3.IO口初始化
void IO_cfg()
{
GPIO_InitTypeDef GPIO_InitStructure;
///////////LED//////////////
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; //挑选引脚 5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_PP; //挑选输入形式推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_Init(GPIOE,&GPIO_InitStructure); //设置PE5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; //挑选引脚 5
GPIO_Init(GPIOB,&GPIO_InitStructure); //设置PB5
/////////KEY/////////////////////////
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //挑选引脚2,3,4
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_ResetBits(GPIOE,GPIO_P