lj250668420 发表于 2014-10-5 15:13:42

卢老师请看一下STM32在UCOSII下进TIM2中断异常

本帖最后由 lj250668420 于 2014-10-5 15:21 编辑

用的是ST3.5的库函数,uCOS-II是用的是2.91版本.在程序中创建了一个LED-red+500ms延时取反的任务,另外还想做一个TIM2的定时器,每个1秒进一次定时器中断取反另一个小灯.也就是一个任务用延时来控制小灯亮灭,另外在写一个定时器2的定时中断函数来控制另一个小灯的亮灭.现在的情况时两个小灯,A闪烁,B不闪烁,然后过一会儿(时间不固定但肯定是超过了我设定的0.5秒和1秒的)变成A不闪烁B闪烁.好苦恼已经看了几天的资料了没有解决办法.下面贴出源码int main(void)
{
          BSP_Init();
      OSInit();
      OSTaskCreate(Task_LED_RED,(void *)0,
         &Task_LED_RED_SKT, Task_LED_RED_PRIO);
      OSStart();
    return 0;
}void Task_LED_RED(void *p_arg)
{
    (void)p_arg;                              // 'p_arg' 并没有用到,防止编译器提示警告

    while (1)
    {
                printf("\r\n 小灯 \r\n");
                LED_RED=!LED_RED;
      OSTimeDlyHMSM(0, 0,0,500);
    }
}void BSP_Init(void)
{      
      RCC_Configuration();                //配置系统时钟为72M
      TIM2_Configuration();                //定时器2配置
      SysTick_init();                              //初始化并使能SysTick定时器
    LED_GPIO_Config();                  //LED 端口初始化
      USART1_Config();
}

/*
* 函数名:SysTick_init
* 描述:配置SysTick定时器
* 输入:无
* 输出:无
*/
void SysTick_init(void)
{
    SysTick_Config(SystemCoreClock/OS_TICKS_PER_SEC);//初始化并使能SysTick定时器
}
void RCC_Configuration(void)
{
      ErrorStatus   HSEStartUpStatus;                                                      //定义枚举类型变量HSEStartUpStatus
      RCC_DeInit();                                                                                                //复位系统时钟
      RCC_HSEConfig(RCC_HSE_ON);                                                                        //开启HSE
      HSEStartUpStatus=RCC_WaitForHSEStartUp();                                       //等待HSE稳定起振
      
      if(HSEStartUpStatus==SUCCESS)                                                                //如果HSE稳定起振                                                               
      {               
                RCC_HCLKConfig(RCC_SYSCLK_Div1);                                    //选择HCLK(AHB)时钟源为SYSCLK 1分频               
                RCC_PCLK2Config(RCC_HCLK_Div1);                                 //选择PCLK2时钟源为HCLK(AHB) 1分频               
                RCC_PCLK1Config(RCC_HCLK_Div2);                                 //选择PLCK1时钟源为HCLK(AHB) 2分频         
                FLASH_SetLatency(FLASH_Latency_2);                                 //设置FLASH延时周期数为2                  
                FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);         //使能FLASH预取缓存               
                RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);         //选择PLL时钟源为HSE 1分频,倍频数为6,则PLL=12MHz*6=72MHz         
                RCC_PLLCmd(ENABLE);                                                                           //使能PLL
                while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);                  //等待PLL输出稳定         
                RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                 //以PLL作为系统时钟                  
                while(RCC_GetSYSCLKSource()!=0x08);                                    //等待PLL成为有效系统时钟源
      }         
      
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);                        //各外设时钟使能RCC_APB1Periph_USART3|
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|
                                                   RCC_APB2Periph_GPIOD|RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2|RCC_APB2Periph_USART1 ,ENABLE);                        
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_USART2|RCC_APB1Periph_BKP|RCC_APB1Periph_PWR , ENABLE);
}
void TIM2_Configuration(void)
{
      TIM_TimeBaseInitTypeDef          TIM_TimeBaseStructure;                        //定义TIM_TimeBase初始化结构体TIM_TimeBaseStructure
      TIM_OCInitTypeDef                        TIM_OCInitStructure;                        //定义TIM_OCInit初始化结构体TIM_OCInitStructure
      NVIC_InitTypeDef NVIC_InitStructure;                                                //定义NVIC初始化结体NVIC_InitStructure   
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                         //选择NVIC优先级分组0

      NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                              //使能TIM2全局中断,0级先占优先级,3级次占有先机         
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);      
      
      TIM_TimeBaseStructure.TIM_Period=65535;                                                 /* 自动重装载寄存器周期的值(计数值) */
    TIM_TimeBaseStructure.TIM_Prescaler=7199;                                        /* 时钟预分频数*/
    TIM_TimeBaseStructure.TIM_ClockDivision=0;                                       /* 时钟分割 */
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;         /* 向上计数模式 */
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
      
      TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Timing;                        //选择定时器模式为TIM输出比较时间模式
      TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;      //使能输出比较状态
      TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;                //TIM输出比较极性高
      TIM_OCInitStructure.TIM_Pulse=10;                                                      //设置了待装入捕获比较寄存器的脉冲值
      TIM_OC1Init(TIM2,&TIM_OCInitStructure);                                                //根据TIM_OCInitStruct中指定的参数初始化TIM2通道1
      TIM_OCInitStructure.TIM_Pulse=100;
      TIM_OC2Init(TIM2,&TIM_OCInitStructure);
      TIM_OCInitStructure.TIM_Pulse=1000;
      TIM_OC3Init(TIM2,&TIM_OCInitStructure);
      TIM_OCInitStructure.TIM_Pulse=10000;
      TIM_OC3Init(TIM2,&TIM_OCInitStructure);

      TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Disable);                        //失能TIM2在CCR1上的预装载寄存器
      TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Disable);
      TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Disable);
      TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Disable);
      TIM_ITConfig(TIM2,TIM_IT_CC1|TIM_IT_CC2|
                                          TIM_IT_CC3|TIM_IT_CC4,ENABLE);                                        //使能TIM2中断         
      TIM_Cmd(TIM2, ENABLE);                                                                            //定时器2启动
}
void USART1_Config(void)
{
    USART_InitTypeDefUSART_InitStructure;                                                      //定义USART初始化结构体USART_InitStructure
      GPIO_InitTypeDef GPIO_InitStructure;                                                      //定义GPIO初始化结构体GPIO_InitStructure
      NVIC_InitTypeDef NVIC_InitStructure;                                                      //定义NVIC初始化结体NVIC_InitStructure   
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                 //选择NVIC优先级分组0

      NVIC_InitStructure.NVIC_IRQChannel =USART1_IRQn ;                                 //使能USART1全局中断,0级先占优先级,0级次占有先机
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;   
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                //设置USART1的Tx脚(PA.9)为第二功能推挽输出模式
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                                                //设置USART1的Rx脚(PA.10)为悬空输入
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

      USART_InitStructure.USART_BaudRate = 115200;                                        //波特率设置
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;                //8位数据长度
      USART_InitStructure.USART_StopBits = USART_StopBits_1;                        //1个停止位
      USART_InitStructure.USART_Parity = USART_Parity_No;                              //奇偶失能
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;      //硬件流控制失能
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      //使能发送和接收模式      
      USART_Init(USART1, &USART_InitStructure);                                                //根据USART_InitStruct中指定的参数初始化外设USART1寄存器

      USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);                                        //使能USART1中断      
      USART_ITConfig(USART1, USART_IT_TXE,DISABLE);                                        //失能USART1中断               
    USART_Cmd(USART1, ENABLE);                                                                              //使能USART1
      USART_ClearITPendingBit(USART1, USART_IT_RXNE);
      USART_ClearITPendingBit(USART1, USART_IT_TXE);
      USART_ClearFlag(USART1, USART_FLAG_TXE);                                                //清除发送标志位
      USART_ClearFlag(USART1, USART_FLAG_RXNE);                                                //清除发送标志位
}void SysTick_Handler(void)
{
      OSIntEnter();
    OSTimeTick();
    OSIntExit();
}

void TIM2_IRQHandler(void)
{         
      vu16 capture=0;                                                                              //当前捕获计数值局部变量
      
      OSIntEnter();

      if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)                        //检查TIM2中TIM捕获/比较1中断源发生
      {      
                capture=TIM_GetCapture1(TIM2);                                        //读取当前计数值
                TIM_SetCompare1(TIM2,capture+10);                              //根据当前计数值更新输出捕获寄存器
                TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);
      }else if(TIM_GetITStatus(TIM2,TIM_IT_CC2)!=RESET)
      {
                capture=TIM_GetCapture2(TIM2);
                TIM_SetCompare2(TIM2,capture+100);
                TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);               
      }else if(TIM_GetITStatus(TIM2,TIM_IT_CC3)!=RESET)
      {
                capture=TIM_GetCapture3(TIM2);
                TIM_SetCompare3(TIM2,capture+1000);
                TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);               
      }else if(TIM_GetITStatus(TIM2,TIM_IT_CC3)!=RESET)
      {
                LED_GREEN=!LED_GREEN;                                                      //小灯控制
                capture=TIM_GetCapture3(TIM2);
                TIM_SetCompare3(TIM2,capture+10000);
                TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);               
      }
      OSIntExit();      
}

void USART1_IRQHandler(void)                                                                //串口1中断函数
{
      OSIntEnter();
      if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)      //检查USART2中接收中断发生与否
      {
//                LED_GREEN=!LED_GREEN;
//                getchar1 = USART_ReceiveData(USART1);
//                Usart_TransData(2,getchar1);
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);
      }
//      else if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
//      {
//                USART_ClearITPendingBit(USART1, USART_IT_TXE);
//      }
      OSIntExit();
}程序的串口中断都可以正常的进入,但是定时器这边就出问题.两个小灯,A闪烁,B不闪烁,然后过一会儿(时间不固定但肯定是超过了我设定的0.5秒和1秒的)变成A不闪烁B闪烁.总感觉像是定时器2的配置这里出了问题,是不是中断向量表我弄错了?麻烦大家给指点一下

laoliang-67665 发表于 2015-12-14 17:07:28

我觉得原理上没问题的,可以分部解决
1.写定时器2的裸奔程序,直到正常
2. 在带UCOS的程序中,先完成延时部分,直到正常
3.再加入中断处理,直到正常
建议在ISR中POST信号量让任务来点灯

无帝老三 发表于 2015-12-4 16:07:34

版主是问题,下面都是学习。。。
神奇

one棉花糖one 发表于 2014-12-7 18:56:24

我是来赚铜板的:lol

wale2013 发表于 2014-10-15 19:07:38

:)学习了,谢谢分享

jwdxu2009 发表于 2014-10-6 22:32:36

下载下来,好好学习,写的好
页: [1]
查看完整版本: 卢老师请看一下STM32在UCOSII下进TIM2中断异常

Baidu
map