5回答

0收藏

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

#开源分享 #开源分享 5831 人阅读 | 5 人回复 | 2014-10-05

本帖最后由 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闪烁.好苦恼已经看了几天的资料了没有解决办法.下面贴出源码
  1. int main(void)
  2. {
  3.           BSP_Init();
  4.         OSInit();
  5.         OSTaskCreate(Task_LED_RED,(void *)0,
  6.            &Task_LED_RED_SKT[Task_LED_RED_STK_SIZE-1], Task_LED_RED_PRIO);
  7.         OSStart();
  8.     return 0;
  9. }
复制代码
  1. void Task_LED_RED(void *p_arg)
  2. {
  3.     (void)p_arg;                                // 'p_arg' 并没有用到,防止编译器提示警告

  4.     while (1)
  5.     {
  6.                 printf("\r\n 小灯 \r\n");
  7.                 LED_RED=!LED_RED;
  8.         OSTimeDlyHMSM(0, 0,0,500);
  9.     }
  10. }
复制代码
  1. void BSP_Init(void)
  2. {        
  3.         RCC_Configuration();                //配置系统时钟为72M  
  4.         TIM2_Configuration();                //定时器2配置
  5.         SysTick_init();                                //初始化并使能SysTick定时器  
  6.     LED_GPIO_Config();                  //LED 端口初始化
  7.         USART1_Config();
  8. }

  9. /*
  10. * 函数名:SysTick_init
  11. * 描述  :配置SysTick定时器
  12. * 输入  :无
  13. * 输出  :无
  14. */
  15. void SysTick_init(void)
  16. {
  17.     SysTick_Config(SystemCoreClock/OS_TICKS_PER_SEC);//初始化并使能SysTick定时器
  18. }
  19. void RCC_Configuration(void)
  20. {
  21.         ErrorStatus     HSEStartUpStatus;                                                        //定义枚举类型变量HSEStartUpStatus
  22.         RCC_DeInit();                                                                                                  //复位系统时钟
  23.         RCC_HSEConfig(RCC_HSE_ON);                                                                          //开启HSE
  24.         HSEStartUpStatus=RCC_WaitForHSEStartUp();                                         //等待HSE稳定起振
  25.         
  26.         if(HSEStartUpStatus==SUCCESS)                                                                //如果HSE稳定起振                                                                 
  27.         {                 
  28.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                    //选择HCLK(AHB)时钟源为SYSCLK 1分频                 
  29.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                   //选择PCLK2时钟源为HCLK(AHB) 1分频                 
  30.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                   //选择PLCK1时钟源为HCLK(AHB) 2分频         
  31.                 FLASH_SetLatency(FLASH_Latency_2);                                   //设置FLASH延时周期数为2                  
  32.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);         //使能FLASH预取缓存               
  33.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);           //选择PLL时钟源为HSE 1分频,倍频数为6,则PLL=12MHz*6=72MHz         
  34.                 RCC_PLLCmd(ENABLE);                                                                           //使能PLL
  35.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);                  //等待PLL输出稳定         
  36.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                   //以PLL作为系统时钟                  
  37.                 while(RCC_GetSYSCLKSource()!=0x08);                                    //等待PLL成为有效系统时钟源
  38.         }         
  39.         
  40.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);                          //各外设时钟使能  RCC_APB1Periph_USART3|
  41.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|
  42.                                                    RCC_APB2Periph_GPIOD|RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2|RCC_APB2Periph_USART1 ,ENABLE);                        
  43.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_USART2|RCC_APB1Periph_BKP|RCC_APB1Periph_PWR , ENABLE);
  44. }
  45. void TIM2_Configuration(void)
  46. {
  47.         TIM_TimeBaseInitTypeDef          TIM_TimeBaseStructure;                        //定义TIM_TimeBase初始化结构体TIM_TimeBaseStructure
  48.         TIM_OCInitTypeDef                        TIM_OCInitStructure;                        //定义TIM_OCInit初始化结构体TIM_OCInitStructure
  49.         NVIC_InitTypeDef NVIC_InitStructure;                                                //定义NVIC初始化结体NVIC_InitStructure     
  50.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                         //选择NVIC优先级分组0

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

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

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

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

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

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

  107.         USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);                                        //使能USART1中断        
  108.         USART_ITConfig(USART1, USART_IT_TXE,DISABLE);                                        //失能USART1中断               
  109.     USART_Cmd(USART1, ENABLE);                                                                                //使能USART1
  110.         USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  111.         USART_ClearITPendingBit(USART1, USART_IT_TXE);
  112.         USART_ClearFlag(USART1, USART_FLAG_TXE);                                                //清除发送标志位
  113.         USART_ClearFlag(USART1, USART_FLAG_RXNE);                                                //清除发送标志位
  114. }
复制代码
  1. void SysTick_Handler(void)
  2. {
  3.         OSIntEnter();
  4.     OSTimeTick();
  5.     OSIntExit();
  6. }

  7. void TIM2_IRQHandler(void)
  8. {         
  9.         vu16 capture=0;                                                                                //当前捕获计数值局部变量
  10.         
  11.         OSIntEnter();

  12.         if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)                        //检查TIM2中TIM捕获/比较1中断源发生
  13.         {        
  14.                 capture=TIM_GetCapture1(TIM2);                                        //读取当前计数值
  15.                 TIM_SetCompare1(TIM2,capture+10);                                //根据当前计数值更新输出捕获寄存器
  16.                 TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);
  17.         }else if(TIM_GetITStatus(TIM2,TIM_IT_CC2)!=RESET)
  18.         {
  19.                 capture=TIM_GetCapture2(TIM2);
  20.                 TIM_SetCompare2(TIM2,capture+100);
  21.                 TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);               
  22.         }else if(TIM_GetITStatus(TIM2,TIM_IT_CC3)!=RESET)
  23.         {
  24.                 capture=TIM_GetCapture3(TIM2);
  25.                 TIM_SetCompare3(TIM2,capture+1000);
  26.                 TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);               
  27.         }else if(TIM_GetITStatus(TIM2,TIM_IT_CC3)!=RESET)
  28.         {
  29.                 LED_GREEN=!LED_GREEN;                                                        //小灯控制
  30.                 capture=TIM_GetCapture3(TIM2);
  31.                 TIM_SetCompare3(TIM2,capture+10000);
  32.                 TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);               
  33.         }
  34.         OSIntExit();        
  35. }

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

使用道具 举报

回答|共 5 个

倒序浏览

沙发

jwdxu2009

发表于 2014-10-6 22:32:36 | 只看该作者

下载下来,好好学习,写的好
板凳

wale2013

发表于 2014-10-15 19:07:38 | 只看该作者

  学习了,谢谢分享
地板

one棉花糖one

发表于 2014-12-7 18:56:24 | 只看该作者

我是来赚铜板的
5#

无帝老三

发表于 2015-12-4 16:07:34 | 只看该作者

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

laoliang-67665

发表于 2015-12-14 17:07:28 | 只看该作者

我觉得原理上没问题的,可以分部解决
1.写定时器2的裸奔程序,直到正常
2. 在带UCOS的程序中,先完成延时部分,直到正常
3.再加入中断处理,直到正常
建议在ISR中POST信号量让任务来点灯
嵌入式,ucos,FPGA系统书籍作者
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条