[学习笔记] PWM动态调整频率和占空比配置方法

[复制链接]
464|14
 楼主 | 2020-1-8 10:56 | 显示全部楼层 |阅读模式
输出PWM如果需要动态的修改PWM频率,配置不当会导致PWM波形有一段时间无输出的情况。
正确的配置如下。拿PWM1模块举例。
1.初始化PWM1
  1. void PWM1_GenerateFrequency(void)
  2. {
  3.     uint16_t preScaler = 0,channelValue;
  4.     float duty = 0;
  5.     /*
  6.         初始化PWM模块为边沿对齐(PWM_PWMMODE_EDGEALLIGNED),高有效(PWM_PWM_HIGHTRUEPULSE)
  7.         输出模式有三种配置模式:
  8.         1. EPWM(边沿对齐)模式  PWM_PWMMODE_EDGEALLIGNED
  9.             EPWM(边沿对齐) 周期由MCVR - CNTIN + 1确定,占空比由CHnV - CNTIN确定
  10.         边沿对齐PWM频率的计算公式 = PWM时钟频率 / (PWM计数器的模数值 - CNTIN + 1) / (PWM时钟分频值 + 1)
  11.         freqValue = CLK / (MOD_PWM - CNTIN+ 1) / (PRESCALER_PWM + 1)
  12.         备注:默认CNTIN为0,如果没有特意去设置CNTIN值,计时公式可简写为:
  13.         freqValue = CLK / (MOD_PWM + 1) / (PRESCALER_PWM + 1)
  14.         2.CPWM(中心对齐)模式 PWM_PWMMODE_CENTERALLIGNED
  15.             CPWM(中心对齐) 周期由2x(MCVR - CNTIN)确定,占空比由2x(CHnV - CNTIN)确定。MCVR必须保持在0x0001至0x7FFF范围内。
  16.         中心对齐PWM频率的计算公式 = (PWM时钟频率 / (PWM计数器的模数值 - CNTIN + 1) / (PWM时钟分频值 + 1)) / 2
  17.         freqValue = CLK / (MOD_PWM - CNTIN+ 1) / (PRESCALER_PWM + 1) / 2
  18.         3.Combine模式  PWM_PWMMODE_COMBINE
  19.             组合模式周期由(MCVR - CNTIN + 1)确定,占空比由(|CH(n+1)V - CH(n)V|)确定。
  20.         组合模式PWM频率的计算公式 = PWM时钟频率 / (PWM计数器的模数值 - CNTIN + 1) / (PWM时钟分频值 + 1)
  21.         freqValue = CLK / (MOD_PWM - CNTIN + 1) / (PRESCALER_PWM + 1)
  22.         组合模式两个通道的输出默认为互补输出。可配置为非互补输出。如何配置?
  23.         
  24.         有效极性配置:
  25.         PWM_PWM_HIGHTRUEPULSE:高有效,如果占空比设为25%,是指的高有效电平占比25%
  26.         PWM_PWM_LOWTRUEPULSE:低有效,如果占空比设为25%,是指的低有效电平占比25%
  27.     */
  28.     PWM_PWMInit(PWM1, PWM_PWMMODE_EDGEALLIGNED, PWM_PWM_HIGHTRUEPULSE);
  29.     /*
  30.     设置MCVR寄存器。及设置PWM计数器的模数值。当PWM计数值达到MCVR值后,
  31.     溢出标志(CNTOF)在下一个时钟置起,计数器的下一个值取决于所选的计数方法。
  32.     */
  33.     PWM_SetModValue(PWM1, MOD_PWM);
  34.     // 占空比计算方式
  35.     /*
  36.         注意:如下计算方式仅限于边沿对齐和中心对齐模式,组合模式的占空比由(|CH(n+1)V - CH(n)V|)确定。
  37.     */
  38.     duty = 0.25; //25%占空比
  39.     channelValue = (MOD_PWM +1) * duty;//
  40.     //设置CH0占空比
  41.     PWM_SetChannelValue(PWM1, PWM_CHANNEL_CHANNEL0, channelValue);
  42.     duty = 0.60; //60%占空比
  43.     channelValue = (MOD_PWM +1) * duty;//
  44.     //设置CH1占空比
  45.     PWM_SetChannelValue(PWM1, PWM_CHANNEL_CHANNEL1, channelValue);
  46.     preScaler = (APB_CLK / (MOD_PWM + 1) / FREQ) - 1;
  47.     PWM_ClockSet(PWM1, 1, preScaler);
  48. }
复制代码
2.配置同步寄存器
  1. void setPWM1SyncMode(void)
  2. {
  3.     PWM_SetPWMEnhanced(PWM1);
  4.     PWM1->MODESEL |= PWM_MODESEL_PAIR0SYNCEN_Msk  ; //对应通道同步使能
  5.     PWM1->SYNCONF |= PWM_SYNCONF_SWVSWSYNC_Msk |  PWM_SYNCONF_SYNCMODE_Msk | PWM_SYNCONF_SWOC_Msk;
  6.     PWM1->SYNC |= PWM_SYNC_MAXSYNCP_Msk;//加载点为PWM计数器达到其最大值(MCVR 寄存器)时。
  7.     PWM1->SYNCONF |= PWM_SYNCONF_OMVSWSYNC_Msk |  PWM_SYNCONF_SYNCMODE_Msk ;
  8.     PWM1->SYNCONF |= PWM_SYNCONF_CNTVSWSYNC_Msk | PWM_SYNCONF_PWMSVSWSYNC_Msk;  ////SW Trig MCVR and CHnV
  9. }
复制代码
3.修改MOD和CHnV后触发软件同步
  1. void testFreq(void)
  2. {
  3.     mdelay(1);
  4.     PWM_SetModValue(PWM1, 99);
  5.     PWM_SetChannelValue(PWM1, PWM_CHANNEL_CHANNEL1, 50);
  6.     PWM_SoftwareSync(PWM1);
  7.     mdelay(1);
  8.     PWM_SetModValue(PWM1, 999);
  9.     PWM_SetChannelValue(PWM1, PWM_CHANNEL_CHANNEL1, 500);
  10.     PWM_SoftwareSync(PWM1);
  11. }
复制代码
4.测试代码
  1. int main(void)
  2. {
  3.     InitDebug();
  4.     InitDelay();
  5.     printf("\nRunning the PWM module sample code.\r\n");
  6.     PWM_GpioInit();
  7.     PWM1_GenerateFrequency();
  8.     setPWM1SyncMode();
  9.     while (1)
  10.     {
  11.         testFreq();
  12.    
  13.     }
  14. }
复制代码


使用特权

评论回复
| 2020-1-8 15:06 | 显示全部楼层
说实话,我感觉新唐的PWM还是最好用的。

使用特权

评论回复
| 2020-1-8 15:07 | 显示全部楼层
比如说,单通道PWM,就是一个函数,频率+占空比,然后配置中断,在中断里面计数,可以控制发送的PWM的个数。

使用特权

评论回复
| 2020-1-8 15:08 | 显示全部楼层
贵司的PWM,可以做中心还是边沿对齐吗?另外,PWM如果设置为脉宽控制,最小的宽度,这个参数有吗?想了解了解!

使用特权

评论回复
| 2020-1-8 15:16 | 显示全部楼层
sorry,看到了对齐模式了,边沿、中心、互补。

使用特权

评论回复
| 2020-1-8 15:17 | 显示全部楼层
如果说,单纯的想控制周期(频率)+占空比或者周期(频率)+正脉宽长度,这个好设置吗?

使用特权

评论回复
 楼主 | 2020-1-8 16:18 | 显示全部楼层
東南博士 发表于 2020-1-8 15:07
比如说,单通道PWM,就是一个函数,频率+占空比,然后配置中断,在中断里面计数,可以控制发送的PWM的个数 ...

这个的差别在于我们把设频率和占空比的寄存器单独封装成接口方便用户配置。也可以放到一个函数里面,都是配寄存器。可以根据自己的偏好去修改

使用特权

评论回复
 楼主 | 2020-1-8 16:19 | 显示全部楼层
東南博士 发表于 2020-1-8 15:06
说实话,我感觉新唐的PWM还是最好用的。


没用习惯就会感觉别扭,用习惯了就好了

使用特权

评论回复
| 2020-1-8 16:25 | 显示全部楼层
AutochipsMCU 发表于 2020-1-8 16:18
这个的差别在于我们把设频率和占空比的寄存器单独封装成接口方便用户配置。也可以放到一个函数里面,都是 ...

嗯!你们是厂家工程师,有着深刻的了解。我们只是用户,都是讲究速成

使用特权

评论回复
 楼主 | 2020-1-8 16:26 | 显示全部楼层
東南博士 发表于 2020-1-8 15:17
如果说,单纯的想控制周期(频率)+占空比或者周期(频率)+正脉宽长度,这个好设置吗? ...

按照一楼的方式配就行。简单来讲就是4个寄存器值。(可能比别人复杂点在于同步多设了两个寄存器吧,下一代MCU已经进行了优化
  1. PWMx->MCVR = modValue;
  2. PWMx->CHANNELS[pwmChannel].CHV = channelValue;
  3. PWMx->SYNCONF   |= PWM_SYNCONF_SYNCMODE_Msk;   //recommend enhanced sync mode
  4. PWMx->SYNC      |= PWM_SYNC_SWSYNC_Msk;
复制代码


使用特权

评论回复
| 2020-1-8 16:29 | 显示全部楼层
AutochipsMCU 发表于 2020-1-8 16:26
按照一楼的方式配就行。简单来讲就是4个寄存器值。(可能比别人复杂点在于同步多设了两个寄存器吧,下一 ...

了解了解!谢谢!

使用特权

评论回复
 楼主 | 2020-1-8 16:29 | 显示全部楼层
東南博士 发表于 2020-1-8 16:25
嗯!你们是厂家工程师,有着深刻的了解。我们只是用户,都是讲究速成

嗯,是的,我们也要站在客户的角度考虑。目的让客户用起来更简单方便。还在努力ing

使用特权

评论回复
| 2020-1-8 17:07 | 显示全部楼层
AutochipsMCU 发表于 2020-1-8 16:29
嗯,是的,我们也要站在客户的角度考虑。目的让客户用起来更简单方便。还在努力ing ...

我感觉也就是厂家的科学家做一些封装的事情!嘿嘿。。。

使用特权

评论回复
| 2020-1-8 17:08 | 显示全部楼层
AutochipsMCU 发表于 2020-1-8 16:29
嗯,是的,我们也要站在客户的角度考虑。目的让客户用起来更简单方便。还在努力ing ...

这点,肯定是可以做的更好的!

使用特权

评论回复
 楼主 | 2020-1-8 17:24 | 显示全部楼层
carefull3357dc 发表于 2020-1-8 17:08
这点,肯定是可以做的更好的!

有很大的进步空间

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表