打印

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

[复制链接]
25562|33
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
topspeedbupt|  楼主 | 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);
沙发
秋天落叶| | 2010-5-27 21:44 | 只看该作者
会有50US停顿时间?

使用特权

评论回复
板凳
topspeedbupt|  楼主 | 2010-5-28 08:33 | 只看该作者
2# 秋天落叶

对。

使用特权

评论回复
地板
静默| | 2010-5-28 09:13 | 只看该作者
思路: 把TIM_TimeBaseStructure定义为全程变量。初始化时按照1楼的代码初始化,交替变换时只用以下语句即可:
  TIM_TimeBaseStructure.TIM_Period = 320-1;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

不过:只减少代码执行的一丁点时间,估计停顿时间不会减少多少。

使用特权

评论回复
5
香水城| | 2010-5-28 09:22 | 只看该作者
在更新中断中改变参数,这样就不会有任何的停顿。

使用特权

评论回复
6
topspeedbupt|  楼主 | 2010-5-28 20:32 | 只看该作者
5# 香水城

这个调用PWM输出,本身已经是在中断里面产生的了啊。当DMA中断产生的时候,在DMA中断响应函数里,对PWM输出进行设置,然后使能输出。每个输出的频率都有可能是不一样的。
可能对香主的话,不是太明白,能否说的详细一点?何为更新中断?

使用特权

评论回复
7
topspeedbupt|  楼主 | 2010-5-28 21:32 | 只看该作者
我刚才搜了一下,搜到了香主的这个回帖https://bbs.21ic.com/icview-158988-1-1.html
“但使用我建议的更新中断(事件),将在每个周期的开始更新比较寄存器的数值,不会出现上述问题。”
看这意思是,改变占空比的么?我这里要求占空比一直都是50%。只能改变频率。

使用特权

评论回复
8
topspeedbupt|  楼主 | 2010-5-28 21:36 | 只看该作者
4# 静默
这个我之前试过,没有用 TIM_DeInit(TIM1); 等。会出现几个跳变,这样来说,对我的系统更危险。呵呵

使用特权

评论回复
9
香水城| | 2010-5-29 17:14 | 只看该作者
回6楼:怎么会有DMA中断?楼主位的问题没有DMA的问题,产生PWM信号也不需要DMA操作。

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

使用特权

评论回复
10
topspeedbupt|  楼主 | 2010-5-29 17:34 | 只看该作者
本帖最后由 topspeedbupt 于 2010-5-29 18:13 编辑

9# 香水城

DMA中断是ADC采样的时候要用到,用来控制传输速率。在DMA中断里,根据是1或0,发送不同的频率。而且下一个信号是0或1是不确定的,只有在检测到是1或0时,马上按对应频率在同一管脚上输出。

使用特权

评论回复
11
topspeedbupt|  楼主 | 2010-5-29 17:40 | 只看该作者
设计preload register和shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的preload register的内容,这样可以保证多个通道的操作能够准确地同步。

但我现在是在TIM1的一个通道上实现,频率变化。

使用特权

评论回复
12
香水城| | 2010-5-30 12:10 | 只看该作者
不管是在一个还是多个通道上,问题的关键是,使用更新中断,使你可以准确地同步输出的信号。

使用特权

评论回复
13
topspeedbupt|  楼主 | 2010-5-31 18:01 | 只看该作者
12# 香水城
非常感谢香主,把香主的博客仔细看了。改了程序。把原来的一大段改成这两行
  TIM_SetAutoreload(TIM1,PeriodPFM);
  TIM_GenerateEvent(TIM1,TIM_EventSource_Update);

目前模拟看效果可以,大概只有几us的延迟。明天实际运行看看。
再次感谢香主!

使用特权

评论回复
14
topspeedbupt|  楼主 | 2010-5-31 18:09 | 只看该作者
有一个问题有点疑问
  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);

使用特权

评论回复
15
香水城| | 2010-5-31 20:47 | 只看该作者
更新事件或更新中断都是在每个PWM周期结束时产生,这时修改PWM的参数可以使下一个周期始终是完整的,如果在没有发生更新事件时修改PWM参数,则会使一个没有结束的周期提前结束或延后结束,结果就是你开始看到的样子。

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

还是我在5楼说的:需要在更新中断中改变参数,这样就不会有任何的停顿。

使用特权

评论回复
16
香水城| | 2010-5-31 20:57 | 只看该作者
实际上,如果你不需要在更新中断中处理什么事情,可以不使能更新中断,也不要使用软件触发TIM_GenerateEvent,直接设置参数,等待硬件在产生更新事件时自动更新那些实际寄存器即可。

使用特权

评论回复
17
topspeedbupt|  楼主 | 2010-5-31 21:37 | 只看该作者
15# 香水城
香主, 您说的硬件中断是指,计数器向上计数溢出产生的中断么?
如果是这样,在每个周期,都会产生中断,怎么才能在我需要改变频率的那一刻,执行中断函数?

使用特权

评论回复
18
香水城| | 2010-5-31 21:42 | 只看该作者
15# 香水城  
香主, 您说的硬件中断是指,计数器向上计数溢出产生的中断么?
如果是这样,在每个周期,都会产生中断,怎么才能在我需要改变频率的那一刻,执行中断函数? ...
topspeedbupt 发表于 2010-5-31 21:37


请看我在16楼的补充说明。

就你的情况,更新事件的条件是:每个PWM周期结束而不是计数器向上计数溢出。

使用特权

评论回复
19
topspeedbupt|  楼主 | 2010-5-31 21:59 | 只看该作者
我按您16楼的说法,关闭update中断。同时只用这两行代码

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

产生有周期提前结束现象,而且有时候整个某个频率就没有,全部为高电平或低电平。

使用特权

评论回复
20
香水城| | 2010-5-31 22:17 | 只看该作者
你是否调用TIM_OC1PreloadConfig使能了Preload功能?

使用特权

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

本版积分规则

个人签名:石块,碎石,沙子,水!

0

主题

44

帖子

1

粉丝