1 STM32 中断优先级概念
STM32(coetex-M3)有两个中断优先级概念,抢占式优先级和响应式优先级,也把响应式优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定属于哪一种优先级。
1、何为抢占式优先级(pre-emption priority)
高抢占式优先级的中断事件会打断当前的主程序/中断程序运行,俗称中断嵌套。
2、何为响应式优先级
在抢占式优先级相同的情况下,高相应的优先级首先被相应。
在抢占式优先级相同的情况下,如果有低级响应式优先级的中断正在被执行,要等到低级优先级的中断执行结束后才能得到相应(不能被嵌套)
3 判断中断被响应
首先是抢占式优先级,其次是响应式优先级。
抢占式优先级决定是否有中断嵌套。
4、STM32(coetex-M3)优先级冲突的处理
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。当两个中断源的抢占式优先级相同的情况下,这两个中断没有嵌套关系,当以个中断到来时,程序正在处理另一个中断,这个后来到中断要等到前一个中断处理结束后才能被处理。如果这两个中断同时到达,则中断控制器要根据要根据他们的优先级高级来决定先处理那个。如果他们的抢占式优先级和响应优先级都相同,则根据他们在中断表中的排列顺序来决定先处理那个中断
5、STM32 对中断优先级的定义
下图是 STM32 中断优先级的拓扑说明
STM32 中指定中断优先级的寄存器有 4 位,NVIC_PriorityGroup 函数,由这个函数的取值(0-4)决定决定寄存器分组状态。设置优先级分组,这4 个寄存器位分组如下:
第 0 组,所有 4 位用于指定响应优先级;
第 1 组,最高 1 位用于指定抢占式优先级,余下 3 位用于指定响应优先级;
第 2 组,最高 2 位用于指定抢占式优先级,余下 2 位用于指定响应优先级;
第 3 组,最高 3 位用于指定抢占式优先级,余下 1 位用于指定响应优先级;
第 4 组,所有 4 位用于指定抢占式优先级;
下面说一下本次试验的目的
通过实验板键盘产生外部中断,在中断中控制 LED 发光二极管,当键盘每次按下时,LED 发光二极管状态取反。目的是通过键盘产生中断,中断处理程序控制 LED 发光二极管,当键盘按下时 LED 发光,当键盘再一次按下时
LED 熄灭,如此反复。
软件设计
中断总结概述
外部中断对应的中断入口函数在我们使用的这款单片机中,PA0~PE0 公用 EXIT0 这个中断向量;PA1~PE1 公用 EXIT1 这个中断向量;PA2~PE2 公用 EXIT2 这个中断向量;PA3~PE3 公用 EXIT3 这个中断向量;PA4~PE4 公用 EXIT4 这个中断向量;PA5~9~PE5~9 公用 EXIT9~5 这个中断向量; PA10~15~PE10~15 公用 EXIT15~10这个中断向量
STM32 库函数文件
本节实验我们主要用到的库文件,其中 stm32f10x_gpio.h 头文件包含了 GPIO 端口的定义。stm32f10x_rcc.h 头文件包含了系统时钟配置函数以及相关的外设时钟使能函数,所以我们要把这两个头文件对应的stm32f10x_gpio.c 和 stm32f10x_rcc.c 加到工程中;Misc.c 库函数主要包含了中断优先级的设置,stm32f10x_exti.c 库函数主要包含了外部中断处理程序。
项目文件结构
#include "pbdata.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void EXTI_Configuration(void);
void NVIC_Configuration(void);
int main(void)
{
RCC_Configuration(); //ϵͳʱÖÓ³õʼ»¯
GPIO_Configuration();//¶Ë¿Ú³õʼ»¯
EXTI_Configuration();
NVIC_Configuration();
while(1);
}
/*******************************************************************************
* º¯ÊýÃû : RCC_Configuration
* º¯ÊýÃèÊö : ÉèÖÃϵͳ¸÷²¿·ÖʱÖÓ
* ÊäÈë²ÎÊý : ÎÞ
* Êä³ö½á¹û : ÎÞ
* ·µ»ØÖµ : ÎÞ
*******************************************************************************/
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
}
/*******************************************************************************
* º¯ÊýÃû : GPIO_Configuration
* º¯ÊýÃèÊö : ÉèÖÃϵͳ¸÷²¿·ÖÒý½Å
* ÊäÈë²ÎÊý : ÎÞ
* Êä³ö½á¹û : ÎÞ
* ·µ»ØÖµ : ÎÞ
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//LED
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//KEY
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
/*******************************************************************************
* º¯ÊýÃû : EXIT_Configuration
* º¯ÊýÃèÊö : ÅäÖÃÍⲿÖжÏ
* ÊäÈë²ÎÊý : ÎÞ
* Êä³ö½á¹û : ÎÞ
* ·µ»ØÖµ : ÎÞ
*******************************************************************************/
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
//Çå³ýÒý½Å¶ÔÓ¦µÄÖжϷÀÖ¹·¢ÉúÒâÍâÖжÏ
EXTI_ClearITPendingBit(EXTI_Line5);
/* ¶¨ÒåPC.5ΪÍⲿÖжÏ0ÊäÈëͨµÀ£¨EXIT5£© */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);
/* Ñ¡ÔñÊäÈëͨµÀ£¨EXIT5£© */
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
/* Ñ¡Ôñ´¥·¢ÖжϷ½Ê½*/
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
/* Ñ¡ÔñÉÏÉçÑØ´¥·¢ÖжÏ*/
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
/* ʹÄÜÖжÏ*/
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/*******************************************************************************
* º¯ÊýÃû : NVIC_Configuration
* º¯ÊýÃèÊö : ÅäÖÃÍⲿÖжÏÓÅÏȼ¶
* ÊäÈë²ÎÊý : ÎÞ
* Êä³ö½á¹û : ÎÞ
* ·µ»ØÖµ : ÎÞ
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* ÖжÏÓÅÏȼ¶·Ö×é*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//ÍⲿÖжÏÏß 9-5 ÖжÏ
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
//ÉèÖÃÇÀÕ¼ÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//ÉèÖÃÏìÓ¦ÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
//ʹÄÜ
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
#include "pbdata.h"
u8 dt=0;
void RCC_HSE_Configuration(void) //HSE×÷ΪPLLʱÖÓ£¬PLL×÷ΪSYSCLK
{
RCC_DeInit(); /*½«ÍâÉèRCC¼Ä´æÆ÷ÖØÉèΪȱʡֵ */
RCC_HSEConfig(RCC_HSE_ON); /*ÉèÖÃÍⲿ¸ßËÙ¾§Õñ£¨HSE£© HSE¾§Õñ´ò¿ª(ON)*/
if(RCC_WaitForHSEStartUp() == SUCCESS) { /*µÈ´ýHSEÆðÕñ, SUCCESS£ºHSE¾§ÕñÎȶ¨ÇÒ¾ÍÐ÷*/
RCC_HCLKConfig(RCC_SYSCLK_Div1);/*ÉèÖÃAHBʱÖÓ(HCLK)RCC_SYSCLK_Div1¡ª¡ªAHBʱÖÓ = ϵͳʱ*/
RCC_PCLK2Config(RCC_HCLK_Div1); /*ÉèÖøßËÙAHBʱÖÓ(PCLK2)RCC_HCLK_Div1¡ª¡ªAPB2ʱÖÓ = HCLK*/
RCC_PCLK1Config(RCC_HCLK_Div2); /*ÉèÖõÍËÙAHBʱÖÓ(PCLK1)RCC_HCLK_Div2¡ª¡ªAPB1ʱÖÓ = HCLK / 2*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/*ÉèÖÃPLLʱÖÓÔ´¼°±¶ÆµÏµÊý*/
RCC_PLLCmd(ENABLE); /*ʹÄÜPLL */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ; /*¼ì²éÖ¸¶¨µÄRCC±ê־λ(PLL×¼±¸ºÃ±êÖ¾)ÉèÖÃÓë·ñ*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /*ÉèÖÃϵͳʱÖÓ£¨SYSCLK£© */
while(RCC_GetSYSCLKSource() != 0x08); /*0x08£ºPLL×÷ΪϵͳʱÖÓ */
}
}
void delay(u32 nCount)
{
for(;nCount!=0;nCount--);
}
/****************************************************************************
* Ãû ³Æ£ºdelay_us(u32 nus)
* ¹¦ ÄÜ£ºÎ¢ÃëÑÓʱº¯Êý
* Èë¿Ú²ÎÊý£ºu32 nus
* ³ö¿Ú²ÎÊý£ºÎÞ
* ˵ Ã÷£º
* µ÷Ó÷½·¨£ºÎÞ
****************************************************************************/
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = 9*nus;
SysTick->VAL=0X00;//Çå¿Õ¼ÆÊýÆ÷
SysTick->CTRL=0X01;//ʹÄÜ£¬¼õµ½ÁãÊÇÎÞ¶¯×÷£¬²ÉÓÃÍⲿʱÖÓÔ´
do
{
temp=SysTick->CTRL;//¶ÁÈ¡µ±Ç°µ¹¼ÆÊýÖµ
}while((temp&0x01)&&(!(temp&(1<<16))));//µÈ´ýʱ¼äµ½´ï
SysTick->CTRL=0x00; //¹Ø±Õ¼ÆÊýÆ÷
SysTick->VAL =0X00; //Çå¿Õ¼ÆÊýÆ÷
}
/****************************************************************************
* Ãû ³Æ£ºdelay_ms(u16 nms)
* ¹¦ ÄÜ£ººÁÃëÑÓʱº¯Êý
* Èë¿Ú²ÎÊý£ºu16 nms
* ³ö¿Ú²ÎÊý£ºÎÞ
* ˵ Ã÷£º
* µ÷Ó÷½·¨£ºÎÞ
****************************************************************************/
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD = 9000*nms;
SysTick->VAL=0X00;//Çå¿Õ¼ÆÊýÆ÷
SysTick->CTRL=0X01;//ʹÄÜ£¬¼õµ½ÁãÊÇÎÞ¶¯×÷£¬²ÉÓÃÍⲿʱÖÓÔ´
do
{
temp=SysTick->CTRL;//¶ÁÈ¡µ±Ç°µ¹¼ÆÊýÖµ
}while((temp&0x01)&&(!(temp&(1<<16))));//µÈ´ýʱ¼äµ½´ï
SysTick->CTRL=0x00; //¹Ø±Õ¼ÆÊýÆ÷
SysTick->VAL =0X00; //Çå¿Õ¼ÆÊýÆ÷
}
#ifndef _pbdata_H
#define _pbdata_H
#include "stm32f10x.h"
#include "stm32f10x_exti.h"
#include "misc.h"
//¶¨Òå±äÁ¿
extern u8 dt;
//¶¨Ò庯Êý
void RCC_HSE_Configuration(void);
void delay(u32 nCount);
void delay_us(u32 nus);
void delay_ms(u16 nms);
#endif
/****************************************************************************
* Ãû ³Æ£ºvoid EXTI9_5_IRQHandler(void)
* ¹¦ ÄÜ£ºEXTI9-5Öжϴ¦Àí³ÌÐò
* Èë¿Ú²ÎÊý£ºÎÞ
* ³ö¿Ú²ÎÊý£ºÎÞ
* ˵ Ã÷£º
* µ÷Ó÷½·¨£ºÎÞ
****************************************************************************/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5)==SET)
{
EXTI_ClearITPendingBit(EXTI_Line5);
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==Bit_RESET)
{
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)==Bit_RESET)
{
//LED ϨÃð
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
else
{
//LED ·¢¹â
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
}
}
}