大家在编写多个中断服务程序的时候,涉及到中断优先级和端口的配置,容易出现系统不响应或者是响应不正常的问题,所以Cortex-m3内核的MM32f103,大家应该知道关于中断的小知识。
刚开始我做的抢答器,本来实时性非常高,所以就得用中断,又有多路抢答,所以,优先级的配置显得很重要。
Cortex-M3中有两个优先级——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
这是手册中的图,可以按照这么配置,
还有
看这个图,最重要的是同一时间,对于不同端口同一序号的端口线,只能设置一个做中断!!!!!!
由于屏来的时候就是坏的,所以信息就上传不了了。。。
这是终端程序,一个定时,俩外部
void RCC_Configuration(void)
{
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus=RCC_WaitForHSEStartUp();
if(HSEStartUpStatus==SUCCESS)
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource()!=0x08)
{
}
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|
RCC_APB2Periph_AFIO,ENABLE);
}
配置完了RCC后,接下来配置SysTick了,使用 ST 的函数库使用 systick 的步骤:
1 、调用 SysTick_CounterCmd() -- 失能 SysTick 计数器
2 、调用 SysTick_ITConfig () -- 失能 SysTick 中断
3 、调用 SysTick_CLKSourceConfig() -- 设置 SysTick 时钟源。
4 、调用 SysTick_SetReload() -- 设置 SysTick 重装载值。
5 、调用 SysTick_ITConfig () -- 使能 SysTick 中断
6 、调用 SysTick_CounterCmd() -- 开启 SysTick 计数器
void SysTick_Configuration(void)//配置 SysTick
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
NVIC_SystemHandlerPriorityConfig(SystemHandler_SysT
SysTick_ITConfig(ENABLE);
}
写响应的中断服务子函数,这个先对比较简单,直接在void SysTickHandler(void)函数里填充计数值便可:
vu32 TimingDelay = 0;
void SysTickHandler(void)
{
TimingDelay--;
}
//接下来需要开启SysTick计数器以便让其工作
void Delay(u32 nTime)//小延时
{
SysTick_CounterCmd(SysTick_Counter_Enable);
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick_CounterCmd(SysTick_Counter_Disable);
SysTick_CounterCmd(SysTick_Counter_Clear);
}
接下来配置其他两个中断,这两个为按键输入,作为外部中断事件,分为两个部分,其一为端口配置在GPIO_Configration函数中,选择工作模式为上拉输入,用作外部中断线路,下降沿触发
void GPIO_Configration(void)
{
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource11);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line11|EXTI_Line12;//线选择
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//中断线使能
EXTI_Init(&EXTI_InitStructure);
}
其二是NVIC嵌入式中断配置,包括中断源(中断向量)、优先级、使能等常规设置
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0X0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0X0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//选择第一组
//使能EXTI15_10中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;// 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;// 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//
NVIC_Init(&NVIC_InitStructure);
//使能EXTI15_10中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;// 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;// 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//
NVIC_Init(&NVIC_InitStructure);
}
最后是相应的中断服务子函数,该中断为EXTI15_10中断,故而其中断服务子函数在void EXTI15_10_IRQHandler(void)中惊醒执行:
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line11)!=RESET)//判断标志,中断是否发生
{
//diy
EXTI_ClearITPendingBit(EXTI_Line11); //清标志位
}
if(EXTI_GetITStatus(EXTI_Line12)!=RESET)//判断标志,中断是否发生
{
//diy
EXTI_ClearITPendingBit(EXTI_Line12); //清标志位
}
}
根据自己的经验和理解写的,有的可能不是很正确,,,但也能凑合看
大家在编写多个中断服务程序的时候,涉及到中断优先级和端口的配置,容易出现系统不响应或者是响应不正常的问题,所以Cortex-m3内核的MM32f103,大家应该知道关于中断的小知识。
刚开始我做的抢答器,本来实时性非常高,所以就得用中断,又有多路抢答,所以,优先级的配置显得很重要。
Cortex-M3中有两个优先级——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
这是手册中的图,可以按照这么配置,
还有
看这个图,最重要的是同一时间,对于不同端口同一序号的端口线,只能设置一个做中断!!!!!!
由于屏来的时候就是坏的,所以信息就上传不了了。。。
这是终端程序,一个定时,俩外部
void RCC_Configuration(void)
{
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus=RCC_WaitForHSEStartUp();
if(HSEStartUpStatus==SUCCESS)
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource()!=0x08)
{
}
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|
RCC_APB2Periph_AFIO,ENABLE);
}
配置完了RCC后,接下来配置SysTick了,使用 ST 的函数库使用 systick 的步骤:
1 、调用 SysTick_CounterCmd() -- 失能 SysTick 计数器
2 、调用 SysTick_ITConfig () -- 失能 SysTick 中断
3 、调用 SysTick_CLKSourceConfig() -- 设置 SysTick 时钟源。
4 、调用 SysTick_SetReload() -- 设置 SysTick 重装载值。
5 、调用 SysTick_ITConfig () -- 使能 SysTick 中断
6 、调用 SysTick_CounterCmd() -- 开启 SysTick 计数器
void SysTick_Configuration(void)//配置 SysTick
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
NVIC_SystemHandlerPriorityConfig(SystemHandler_SysT
SysTick_ITConfig(ENABLE);
}
写响应的中断服务子函数,这个先对比较简单,直接在void SysTickHandler(void)函数里填充计数值便可:
vu32 TimingDelay = 0;
void SysTickHandler(void)
{
TimingDelay--;
}
//接下来需要开启SysTick计数器以便让其工作
void Delay(u32 nTime)//小延时
{
SysTick_CounterCmd(SysTick_Counter_Enable);
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick_CounterCmd(SysTick_Counter_Disable);
SysTick_CounterCmd(SysTick_Counter_Clear);
}
接下来配置其他两个中断,这两个为按键输入,作为外部中断事件,分为两个部分,其一为端口配置在GPIO_Configration函数中,选择工作模式为上拉输入,用作外部中断线路,下降沿触发
void GPIO_Configration(void)
{
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource11);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line11|EXTI_Line12;//线选择
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//中断线使能
EXTI_Init(&EXTI_InitStructure);
}
其二是NVIC嵌入式中断配置,包括中断源(中断向量)、优先级、使能等常规设置
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0X0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0X0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//选择第一组
//使能EXTI15_10中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;// 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;// 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//
NVIC_Init(&NVIC_InitStructure);
//使能EXTI15_10中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;// 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;// 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//
NVIC_Init(&NVIC_InitStructure);
}
最后是相应的中断服务子函数,该中断为EXTI15_10中断,故而其中断服务子函数在void EXTI15_10_IRQHandler(void)中惊醒执行:
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line11)!=RESET)//判断标志,中断是否发生
{
//diy
EXTI_ClearITPendingBit(EXTI_Line11); //清标志位
}
if(EXTI_GetITStatus(EXTI_Line12)!=RESET)//判断标志,中断是否发生
{
//diy
EXTI_ClearITPendingBit(EXTI_Line12); //清标志位
}
}
根据自己的经验和理解写的,有的可能不是很正确,,,但也能凑合看