版主,你好,最近弄一个步进电机的项目,对时间要求非常严格,我想用到STM32的中断抢占功能,以下是我写的一个简单的DEMO,在软件仿真的时候,TIM2中断函数里触发了TIM3的软件中断,此时是可以正常被TIM3抢占的,TIM3的中断执行完以后又会回到TIM2。但挪到硬件上执行以后,情况就不一样了,TIM2中第一次触发的软件中断要在TIM2执行完TIM_ClearITPendingBit(TIM2, TIM_IT_Update);语句后才被TIM3抢占,TIM2中第二次触发的软件中断就不能再被TIM3抢占了,项目非常紧急,请版主帮忙看看有没什么地方漏了什么没有,万分感谢!
#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_nvic.h"
#include "stm32f10x_systick.h"
void fInit_TIM2(void);
void fInit_TIM3(void);
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != 0) //TIM_GetITStatus(TIM2, TIM_IT_Update)
{
__nop();
TIM_GenerateEvent(TIM3,TIM_EventSource_Update);// TIM3->CNT = 0XC34F; //产生定时器3中断
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
__nop();
TIM_GenerateEvent(TIM3,TIM_EventSource_Update); //TIM3->CNT = 0XC34F; //产生定时器3中断
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
}
}
void BSP_SysInit(void)
{
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSI */
RCC_HSICmd(ENABLE);
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* ADCCLK = PCLK2/6 */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
/* PLLCLK = 4MHz * 9 = 36 MHz */
//RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_2);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
int main(void){
NVIC_InitTypeDef NVIC_InitStructure;
BSP_SysInit();
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//DBGMCU_Config(DBGMCU_TIM2_STOP,ENABLE);
//DBGMCU_Config(DBGMCU_TIM3_STOP,ENABLE);
// DBGMCU_Config(DBGMCU_TIM4_STOP,ENABLE
/* Deinitializes the NVIC */
NVIC_DeInit();
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); //3位抢先优先级,1位亚优先级
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
fInit_TIM2();
fInit_TIM3();
while(1);
}
void fInit_TIM2(void) //自身运行
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 10000;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Output Compare Inactive Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_Pulse = 0x0;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM2, 0, TIM_PSCReloadMode_Immediate);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
void fInit_TIM3(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //打开定时器
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Prescaler = 720; //10us一次累加
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 500 * 100; //半流时间为ms
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Output Compare Inactive Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_Pulse = 0x0;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM3, 0, TIM_PSCReloadMode_Immediate);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Global); //可以由软件产生最新中断
TIM_Cmd(TIM3, ENABLE);
}
我以前也遇到过类似的问题,查了好久。
后来在调试的时候,断点中发现优先级的组数变了。后来发现是驱动库的问题。
楼主也不妨检查一下。
多谢兄台回复,问题已经找到,是因为开启了以下两句的原因,开启了以下两句在单步调试的时候会对抢占有影响,就算关闭了这两句如果不复位板子也还是一样有问题,所以只要在关闭这两句以后重上电就可以了。
DBGMCU_Config(DBGMCU_TIM2_STOP,ENABLE);
DBGMCU_Config(DBGMCU_TIM3_STOP,ENABLE);