To版主,STM32中断抢占不了的问题

wgxys2007   2011-3-5 14:08 楼主
版主,你好,最近弄一个步进电机的项目,对时间要求非常严格,我想用到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);
}

回复评论 (3)

我以前也遇到过类似的问题,查了好久。
后来在调试的时候,断点中发现优先级的组数变了。后来发现是驱动库的问题。
楼主也不妨检查一下。
点赞  2011-3-5 15:25
多谢兄台回复,问题已经找到,是因为开启了以下两句的原因,开启了以下两句在单步调试的时候会对抢占有影响,就算关闭了这两句如果不复位板子也还是一样有问题,所以只要在关闭这两句以后重上电就可以了。        
DBGMCU_Config(DBGMCU_TIM2_STOP,ENABLE);
DBGMCU_Config(DBGMCU_TIM3_STOP,ENABLE);
点赞  2011-3-5 19:42
                                 原来是这个问题呀, 是个值得留意的地方.
点赞  2011-3-5 21:21
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复