打印

stm32定时器的4个通道能否分别开启和关闭

[复制链接]
18552|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sckaty|  楼主 | 2013-1-29 22:02 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
TIM2的4个通道想分别用在不同的事件处理中,但是似乎只有TIM_Cmd()这函数可以用,就是把所有通道同时开启或关闭, 而想用TIM_CCxCmd()来分别操作各个通道则完全不起作用。
比如说TIM_Cmd(TIM2, ENABLE); 了之后,再TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Disable);就没办法关闭这个通道,还是会不停的进定时器中断。如果TIM_Cmd(TIM2, DISABLE); 了,则TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Enable);
也没办法把这个通道开启。请问该怎么解决这种问题。。。
沙发
sckaty|  楼主 | 2013-1-29 22:13 | 只看该作者
相关的代码如下:
vu16 CCR1_Val = 500;
vu16 CCR2_Val = 1000;
vu16 CCR3_Val = 2000;
vu16 CCR4_Val = 4000;
void Timer2_Init()
{
        TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
    TIM_OCInitTypeDef    TIM_OCInitStructre;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);             //时钟使能
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period = 65535;                                     //自动重装计数值
        TIM_TimeBaseStructure.TIM_Prescaler = 2;                                       // 时钟预分频数,        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;              //采样分频
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     //向上计数
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);                        //初始化
       
    TIM_PrescalerConfig(TIM2,2,TIM_PSCReloadMode_Update);
   
    TIM_OCInitStructre.TIM_OCMode = TIM_OCMode_Timing;
    TIM_OCInitStructre.TIM_OCPolarity = TIM_OCPolarity_High;      
   
    TIM_OCInitStructre.TIM_Pulse = CCR1_Val;                                     //输出捕获通道1配置
    TIM_OC1Init(TIM2,&TIM_OCInitStructre);
    TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Disable);
   
    TIM_OCInitStructre.TIM_Pulse = CCR2_Val;                                    //输出捕获通道2配置
    TIM_OC2Init(TIM2,&TIM_OCInitStructre);
    TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Disable);
   
    TIM_OCInitStructre.TIM_Pulse = CCR3_Val;                                   //输出捕获通道3配置
    TIM_OC3Init(TIM2,&TIM_OCInitStructre);
    TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Disable);
   
    TIM_OCInitStructre.TIM_Pulse = CCR4_Val;                                  //输出捕获通道4配置
    TIM_OC4Init(TIM2,&TIM_OCInitStructre);
    TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Disable);
   
    //TIM_ARRPreloadConfig(TIM2,ENABLE);
   /*预先清除所有中断位*/
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4|TIM_IT_Update);
   
    TIM_ITConfig(TIM2 , TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4 , ENABLE);  
//TIM_Cmd(TIM2, ENABLE);
}
void NVIC_Configuration(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
#ifdef  VECT_TAB_RAM
        //Set the Vector Table base location at 0x20000000
        NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  // VECT_TAB_FLASH
        // Set the Vector Table base location at 0x08000000
        NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                                                       //设置2   位先占优先级,2位从占优先级

        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                                           //定时器2的中断配置
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

......
}
void TaskMain(void *p_arg)
{
    PHY_Init();                                                                 //物理层初始化,Timer2_Init()包含在这个函数里面
  NVIC_Configuration();
    OS_CPU_SysTickInit();        //使能SYSTICK中断               
    #if (OS_TASK_STAT_EN > 0)
    OSStatInit();         
    #endif
               
    os_err = OSTaskCreate(APP_Task,                                                          //应用层任务
                       (void *)APP_TASK_STK_SIZE,                   
                       (OS_STK *)&APPTaskStk[APP_TASK_STK_SIZE - 1],          //堆栈指针
                       (INT8U)APP_TASK_PRIO);                                                          //优先级为10   

    os_err = OSTaskCreate(USAER_Send_Task,                                   //串口发送任务
                       (void *)USART_TASK_STK_SIZE,                   
                       (OS_STK *)&USARTTaskStk[USART_TASK_STK_SIZE - 1],//堆栈指针
                       (INT8U)USART_TASK_PRIO);                                                //优先级为30   
                                    
   
    /* 允许TIM2开始计数 */
    TIM_Cmd(TIM2, ENABLE);
#if 1
    TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Disable);  //这几个函数在这完全不起作用
    TIM_CCxCmd(TIM2, TIM_Channel_2, TIM_CCx_Disable);
    TIM_CCxCmd(TIM2, TIM_Channel_3, TIM_CCx_Disable);
    TIM_CCxCmd(TIM2, TIM_Channel_4, TIM_CCx_Disable);
#endif   

    while(1)
    {
        OSTimeDly(OS_TICKS_PER_SEC);
        LEDS_ON();
        OSTimeDly(OS_TICKS_PER_SEC/2);
        LEDS_OFF();
    }
}       
void main(void)
{
   OSInit();                //UCOS INIT~
  
  os_err = OSTaskCreate(TaskMain,                          //第一个任务0
                       (void *)MAIN_TASK_STK_SIZE,                  //不带参数
                       (OS_STK *)&MAINTaskStk[MAIN_TASK_STK_SIZE - 1],//堆栈指针
                       (INT8U )MAIN_TASK_PRIO);                     //优先级
                  
    OSStart();                                                                  //操作系统启动
     while(1);
}
void TIM2_IRQHandler(void)
{
  OS_CPU_SR cpu_sr;
  OS_ENTER_CRITICAL();
  OSIntNesting++;
  OS_EXIT_CRITICAL();
        //用户程序..
  if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
  {
    //调试时不停的进这里面的中断,我以为调了TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Disable);  应该就不会进来了。。
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);
        CaptureTime = TIM_GetCapture1(TIM2);                                                               //获取捕获时间
    TIM_SetCompare1(TIM2, CaptureTime + CCR1_Val);                                  //设置TIM2通道1的捕获时间
   }
  else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
  {
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
        CaptureTime = TIM_GetCapture2(TIM2);
        TIM_SetCompare2(TIM2, CaptureTime + CCR2_Val);
   }
  else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
  {
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);
   ......
  }
  else if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)
  {
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC4);
        ......
  }
  else if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  {
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);   

  }
  OSIntExit();

}

使用特权

评论回复
板凳
uet_cache| | 2013-1-30 10:05 | 只看该作者
时基单元的中断跟比较中断不同,别入错中断。另外,每个独立的比较通道可以单独禁止的,肯定可以实现。你可以看下官方例程。

使用特权

评论回复
地板
sckaty|  楼主 | 2013-1-30 11:58 | 只看该作者
uet_cache 发表于 2013-1-30 10:05
时基单元的中断跟比较中断不同,别入错中断。另外,每个独立的比较通道可以单独禁止的,肯定可以实现。你可 ...

谢谢uet_cache指点,我照着OCActive里面的那个例程改写了Timer2_Init(),但是结果还是一样。。。我这种应用应该是属于比较中断吧,不是很理解时基中断和比较中断在设置上有哪些差别。另外,TIM_CCxCmd()和TIM_CCxNCmd()是不是应该成对使用?

使用特权

评论回复
5
sckaty|  楼主 | 2013-1-30 14:47 | 只看该作者
搞定了!从定时器的框图上看,使能4个通道的线只有一根,所以不能分别开启和关闭,但是不同的通道可以有不同的CCxI寄存器配置,用TIM_ITConfig(TIM2 , TIM_IT_CC1, ENABLE);或DISABLE,直接开中断或关中断,开启之后再重新置计数值,就可以实现我想要的功能了。
多谢uet_cache的回答,20分都给你了!

使用特权

评论回复
6
sckaty|  楼主 | 2013-1-30 14:50 | 只看该作者
擦!怎么结贴?

使用特权

评论回复
7
sckaty|  楼主 | 2013-1-30 15:57 | 只看该作者
社区帮助上说“点击帖子左上方的"我要结贴"按钮”,版主,哪里有这按钮啊,怎么找不着?


使用特权

评论回复
8
TT5656| | 2013-1-30 16:18 | 只看该作者
sckaty 发表于 2013-1-30 15:57
社区帮助上说“点击帖子左上方的"我要结贴"按钮”,版主,哪里有这按钮啊,怎么找不着?

24小时后结贴

使用特权

评论回复
9
dzkjdx| | 2014-4-4 21:46 | 只看该作者
sckaty 发表于 2013-1-30 14:47
搞定了!从定时器的框图上看,使能4个通道的线只有一根,所以不能分别开启和关闭,但是不同的通道可以有不 ...

使用TIM1->CCER&=0xfffe;可以关闭TIM1的第一通道,我试过的。

使用特权

评论回复
10
liangzhuotian| | 2014-9-20 15:56 | 只看该作者
楼主能否详细“开启之后再重新置计数值”是什么意思

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

9

帖子

0

粉丝