STM32如何实现同个管脚PWM输出不同频率无缝切换

wumuok   2010-5-27 20:15 楼主
我要实现PWM交替输出50KHz和100KHz,占空比都是50%,在同一个管脚上。
现在用TIM,捕获比较方式,每次改变频率时,都有从新设置,拿示波器看,发现频率交替时,有大概50us的停顿时间。
请问版主,STM32能否实现无缝交替,或者是很小,只有几us的停顿时间?多谢先。


程序如下,每次交替,都有从新设置,但只改变一下红色部分的值。
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  /* Enable AFIO clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  /* Enable GPIOE clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
  GPIO_PinRemapConfig(GPIO_FullRemap_TIM1,ENABLE);
  /* Configure PE11 PE13  as IPD */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
  TIM_DeInit(TIM1);
  /* ---------------------------------------------------------------
    TIM1 Configuration: Free Up Count Mode:
    TIM1CLK = HCLK(32MHz), Prescaler = 1, TIM1 counter clock = 32 MHz
  --------------------------------------------------------------- */
  TIM1->BDTR=0x0000;
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 320-1;
  TIM_TimeBaseStructure.TIM_Prescaler = 1-1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

回复评论 (24)

                                 会有50US停顿时间?
点赞  2010-5-27 21:44


对。
点赞  2010-5-28 08:33
思路: 把TIM_TimeBaseStructure定义为全程变量。初始化时按照1楼的代码初始化,交替变换时只用以下语句即可:
  TIM_TimeBaseStructure.TIM_Period = 320-1;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

不过:只减少代码执行的一丁点时间,估计停顿时间不会减少多少。
点赞  2010-5-28 09:13
                                 在更新中断中改变参数,这样就不会有任何的停顿。
点赞  2010-5-28 09:22


这个调用PWM输出,本身已经是在中断里面产生的了啊。当DMA中断产生的时候,在DMA中断响应函数里,对PWM输出进行设置,然后使能输出。每个输出的频率都有可能是不一样的。
可能对版主的话,不是太明白,能否说的详细一点?何为更新中断?
点赞  2010-5-28 20:32
我刚才搜了一下,搜到了版主的这个回帖https://bbs.eeworld.com.cn/icview-158988-1-1.html
“但使用我建议的更新中断(事件),将在每个周期的开始更新比较寄存器的数值,不会出现上述问题。”
看这意思是,改变占空比的么?我这里要求占空比一直都是50%。只能改变频率。
点赞  2010-5-28 21:32

这个我之前试过,没有用 TIM_DeInit(TIM1); 等。会出现几个跳变,这样来说,对我的系统更危险。呵呵
点赞  2010-5-28 21:36
回6楼:怎么会有DMA中断?楼主位的问题没有DMA的问题,产生PWM信号也不需要DMA操作。

关于更新中断的问题,你需要看看STM32参考手册,我的博客中也有介绍:
STM32定时器的预装载寄存器与影子寄存器之间的关系
点赞  2010-5-29 17:14


9# 版主

DMA中断是ADC采样的时候要用到,用来控制传输速率。在DMA中断里,根据是1或0,发送不同的频率。而且下一个信号是0或1是不确定的,只有在检测到是1或0时,马上按对应频率在同一管脚上输出。
点赞  2010-5-29 17:34
设计preload register和shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的preload register的内容,这样可以保证多个通道的操作能够准确地同步。

但我现在是在TIM1的一个通道上实现,频率变化。
点赞  2010-5-29 17:40
                                 不管是在一个还是多个通道上,问题的关键是,使用更新中断,使你可以准确地同步输出的信号。
点赞  2010-5-30 12:10

非常感谢版主,把版主的博客仔细看了。改了程序。把原来的一大段改成这两行
  TIM_SetAutoreload(TIM1,PeriodPFM);
  TIM_GenerateEvent(TIM1,TIM_EventSource_Update);

目前模拟看效果可以,大概只有几us的延迟。明天实际运行看看。
再次感谢版主!
点赞  2010-5-31 18:01
有一个问题有点疑问
  TIM_SetAutoreload(TIM1,PeriodPFM);
  TIM_GenerateEvent(TIM1,TIM_EventSource_Update);
  TIM_SetCompare2(TIM1,PeriodPFM/2);//
这样可以正常输出。

但如果把设置占空比的放到更新事情前,会有尖脉冲产生。
  TIM_SetAutoreload(TIM1,PeriodPFM);
  TIM_SetCompare2(TIM1,PeriodPFM/2);//
  TIM_GenerateEvent(TIM1,TIM_EventSource_Update);
点赞  2010-5-31 18:09
更新事件或更新中断都是在每个PWM周期结束时产生,这时修改PWM的参数可以使下一个周期始终是完整的,如果在没有发生更新事件时修改PWM参数,则会使一个没有结束的周期提前结束或延后结束,结果就是你开始看到的样子。

现在你在硬件没有产生更新事件,强制用软件TIM_GenerateEvent产生它,则根本没有起到使用更新事件修改PWM参数的作用,当然不能有满意的结果。

还是我在5楼说的:需要在更新中断中改变参数,这样就不会有任何的停顿。
点赞  2010-5-31 20:47
                                 实际上,如果你不需要在更新中断中处理什么事情,可以不使能更新中断,也不要使用软件触发TIM_GenerateEvent,直接设置参数,等待硬件在产生更新事件时自动更新那些实际寄存器即可。
点赞  2010-5-31 20:57

版主, 您说的硬件中断是指,计数器向上计数溢出产生的中断么?
如果是这样,在每个周期,都会产生中断,怎么才能在我需要改变频率的那一刻,执行中断函数?
点赞  2010-5-31 21:37
15# 版主  
版主, 您说的硬件中断是指,计数器向上计数溢出产生的中断么?
如果是这样,在每个周期,都会产生中断,怎么才能在我需要改变频率的那一刻,执行中断函数? ...
请看我在16楼的补充说明。

就你的情况,更新事件的条件是:每个PWM周期结束而不是计数器向上计数溢出。
点赞  2010-5-31 21:42
我按您16楼的说法,关闭update中断。同时只用这两行代码

  TIM_SetAutoreload(TIM1,PeriodPFM);
//  TIM_GenerateEvent(TIM1,TIM_EventSource_Update);
  TIM_SetCompare2(TIM1,PeriodPFM/2);//

产生有周期提前结束现象,而且有时候整个某个频率就没有,全部为高电平或低电平。
点赞  2010-5-31 21:59
                                 你是否调用TIM_OC1PreloadConfig使能了Preload功能?
点赞  2010-5-31 22:17
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复