AutochipsMCU 发表于 2020-1-8 10:56

PWM动态调整频率和占空比配置方法

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

東南博士 发表于 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

如果说,单纯的想控制周期(频率)+占空比或者周期(频率)+正脉宽长度,这个好设置吗?

AutochipsMCU 发表于 2020-1-8 16:18

東南博士 发表于 2020-1-8 15:07
比如说,单通道PWM,就是一个函数,频率+占空比,然后配置中断,在中断里面计数,可以控制发送的PWM的个数 ...

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

AutochipsMCU 发表于 2020-1-8 16:19

東南博士 发表于 2020-1-8 15:06
说实话,我感觉新唐的PWM还是最好用的。


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

東南博士 发表于 2020-1-8 16:25

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

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

AutochipsMCU 发表于 2020-1-8 16:26

東南博士 发表于 2020-1-8 15:17
如果说,单纯的想控制周期(频率)+占空比或者周期(频率)+正脉宽长度,这个好设置吗? ...

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

東南博士 发表于 2020-1-8 16:29

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

了解了解!谢谢!

AutochipsMCU 发表于 2020-1-8 16:29

東南博士 发表于 2020-1-8 16:25
嗯!你们是厂家工程师,有着深刻的了解。我们只是用户,都是讲究速成

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

carefull3357dc 发表于 2020-1-8 17:07

AutochipsMCU 发表于 2020-1-8 16:29
嗯,是的,我们也要站在客户的角度考虑。目的让客户用起来更简单方便。还在努力ing ...

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

carefull3357dc 发表于 2020-1-8 17:08

AutochipsMCU 发表于 2020-1-8 16:29
嗯,是的,我们也要站在客户的角度考虑。目的让客户用起来更简单方便。还在努力ing ...

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

AutochipsMCU 发表于 2020-1-8 17:24

carefull3357dc 发表于 2020-1-8 17:08
这点,肯定是可以做的更好的!

有很大的进步空间

lanmanck 发表于 2020-2-28 18:19

東南博士 发表于 2020-1-8 15:06
说实话,我感觉新唐的PWM还是最好用的。

是因为他的定时器比较简单吧?他能同时兼顾捕获霍尔、编码器、外部PWM计数吗?

東南博士 发表于 2020-3-1 12:15

lanmanck 发表于 2020-2-28 18:19
是因为他的定时器比较简单吧?他能同时兼顾捕获霍尔、编码器、外部PWM计数吗? ...

同时兼顾捕获这个功能似乎还没有做过

ZJY135790 发表于 2022-11-23 15:55

怎么不用输出比较功能呢

vivilyly 发表于 2023-2-2 09:32

这个直接使用寄存器控制点。            

lzmm 发表于 2023-2-2 09:41

修改占空比的时候,不会有问题。            
页: [1] 2
查看完整版本: PWM动态调整频率和占空比配置方法