This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F280039C:TBPHS 值小于 CMPA 时跳过 PWM

Guru**** 1652420 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1294852/tms320f280039c-pwm-skip-when-tbphs-value-is-less-than-cmpa

器件型号:TMS320F280039C

尊敬的 Champ:

我想就我当前面临的问题征求您的意见。 我的应用使用两个 PWM 模块、PWM1和 PWM2。 相位在 PWM2上启用、PWM1作为 SYNCIN (主器件)。

当相位在 CMPA 值附近缓慢下降时、就会出现问题。 我观察到 PWM2在一个周期内跳过。 根据我在此处找到的一些帖子、建议的解决方案是处理相位更新、方法是在一个周期内将 CMPA 值更改为小于 TBPHS、然后在下一个周期将 CMPA 改回正常值。

但是,这种方法(*)不能解决本例中的问题。 是否有需要添加的特定设置或处理程序?

我在这里附上了我的代码供您参考。

void PWM_init(void){
    EPwm1Regs.TBPRD                    = pwm_prd;
    EPwm1Regs.TBPHS.bit.TBPHS          = 0; // PWM-1 serves as reference
    EPwm1Regs.CMPA.bit.CMPA            = pwm_cmpa;
    EPwm1Regs.CMPB.bit.CMPB            = 0;
    EPwm1Regs.TBCTL.bit.CLKDIV         = TB_DIV1;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV      = TB_DIV1;         //change to sysclk
    EPwm1Regs.TBCTL.bit.CTRMODE        = TB_COUNT_UPDOWN; // Symmetrical mode
    EPwm1Regs.TBCTL.bit.PRDLD          = TB_SHADOW;
    EPwm1Regs.EPWMSYNCOUTEN.bit.ZEROEN = 1;
    EPwm1Regs.EPWMSYNCINSEL.bit.SEL    = SYNC_IN_SRC_DISABLE_ALL;
    EPwm1Regs.CMPCTL.bit.SHDWAMODE     = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE     = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE     = CC_CTR_ZERO;
    EPwm1Regs.CMPCTL.bit.LOADBMODE     = CC_CTR_ZERO;
    
    EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // Active high
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.CAD = AQ_CLEAR; // Active LOW
    EPwm1Regs.AQCTLB.bit.CAU = AQ_SET;
    
    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // Enable Dead-band module
    EPwm1Regs.DBCTL.bit.POLSEL   = DB_ACTV_HIC;    // Active Hi complementary
    EPwm1Regs.DBFED.bit.DBFED    = Deadtime;   
    EPwm1Regs.DBRED.bit.DBRED    = Deadtime;   
    
    EPwm2Regs.TBPRD                 = pwm_prd;
    EPwm2Regs.TBPHS.bit.TBPHS       = pwm_phs;
    EPwm2Regs.CMPA.bit.CMPA         = pwm_cmpa;
    EPwm2Regs.CMPB.bit.CMPB         = 0;
    EPwm2Regs.TBCTL.bit.CLKDIV      = TB_DIV1;
    EPwm2Regs.TBCTL.bit.HSPCLKDIV   = TB_DIV1;
    EPwm2Regs.TBCTL.bit.CTRMODE     = TB_COUNT_UPDOWN;
    EPwm2Regs.TBCTL.bit.PHSEN       = TB_ENABLE;
    EPwm2Regs.TBCTL.bit.PRDLD       = TB_SHADOW;
    EPwm2Regs.EPWMSYNCINSEL.bit.SEL = SYNC_IN_SRC_SYNCOUT_EPWM1;
    EPwm2Regs.CMPCTL.bit.SHDWAMODE  = CC_IMMEDIATE;
    EPwm2Regs.CMPCTL.bit.SHDWBMODE  = CC_IMMEDIATE;
    //        EPwm2Regs.CMPCTL.bit.LOADAMODE  = CC_CTR_ZERO_PRD; // load on CTR=Zero
    //        EPwm2Regs.CMPCTL.bit.LOADBMODE  = CC_CTR_ZERO_PRD; // load on CTR=Zero
    
    EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; //Active LOW
    EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm2Regs.AQCTLB.bit.CAD = AQ_SET; //Active HIGH
    EPwm2Regs.AQCTLB.bit.CAU = AQ_CLEAR;
    
    EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // Enable Dead-band module
    EPwm2Regs.DBCTL.bit.POLSEL   = DB_ACTV_HIC;    // Active Hi complementary
    EPwm2Regs.DBFED.bit.DBFED    = Deadtime;   
    EPwm2Regs.DBRED.bit.DBRED    = Deadtime;   
    
    EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;
}
void phase_update(uint16_t phase)
{
    static uint16_t temp;
    temp = (uint16_t)(((uint32_t)phase* EPwm1Regs.TBPRD) / 180);

    pwm_phs = temp;
    update_request = 1;
}
void PWMUpdate(void)
{
    if (skip_pwm_flag == 1) {
        EPwm2Regs.TBPHS.bit.TBPHS = pwm_phs;
        pwm_phs_prev  = EPwm2Regs.TBPHS.bit.TBPHS;
        skip_pwm_flag++;
    } else if (skip_pwm_flag == 2) {
        EPwm2Regs.CMPA.bit.CMPA   = (EPwm2Regs.TBPRD >> 1);
        skip_pwm_flag = 0;
    }

    if (update_request == 1) {
        update_request = 0;
        if (pwm_phs_prev > EPwm2Regs.CMPA.bit.CMPA && pwm_phs <= EPwm2Regs.CMPA.bit.CMPA) {
            EPwm2Regs.CMPA.bit.CMPA   = pwm_phs - 1;
            skip_pwm_flag = 1;
        } else {
            EPwm2Regs.TBPHS.bit.TBPHS = pwm_phs;
            pwm_phs_prev  = EPwm2Regs.TBPHS.bit.TBPHS;
        }
    }
}

E2E 参考(*)

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1163045/tms320f28069-epwm-miss-cycle-while-tbphs-change?tisearch=e2e-sitesearch&keymatch=tbphs%2525252525252520cmpa%2525252525252520pwm%2525252525252520missed#

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1161072/tms320f28033-when-tbphs-load-value-is-less-than-cmpa-value-the-below-figure-will-the-aq-action-be-lost

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Luiz:

    是的、一般思路是修改比较值、这样当我们使用 PHS 值在同步处修改时基计数器值时、不会错过比较事件。

    根据此处发布的代码、EPWM2设置为递减 CMPA 值、而清除为递增 CMPA 值。 在您的情况下,您能区分哪个比较事件被设置或清除吗? 由于您使用的是有源高电平互补 CMPB 值将不会很重要。


    在您的情况下、可能会错过设置或清除事件、具体取决于您的 PHS 值和加载时间。 例如 、在向上计数中、当发生同步时、如果 epwm2的时基计数器小于 cmpa、则 PHS 设置为高于 cmpa 的值、则可能会错过 CLEART/SET-LOW 事件。 在向下计数 cmpa 值时 set-HIGH 也是如此,但您已经在 PWMUpdate()函数中考虑到了这一点。

     PHASE_UPDATE 和 PWMUpdate 的序列也很重要。 此外,如果您可以共享在基于同步输入的相位加载过程中丢失比较事件的快照?

    谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Prarthan、

    感谢您的快速响应。

    是的一般想法是修改比较值,这样当我们使用 PHS 值在 syncin 时修改时基计数器值时,比较事件就不会丢失。

    了解。

    根据您在此处发布的代码,EPWM2设置为递减 CMPA 值,并按递增 CMPA 值清零。 您能告诉哪些比较事件在您的情况下被忽略设置或清除吗?
    当 PHS 从340更改为339时、会发生错过的事件。 CMPA 默认值为340、而默认 PRD 为681。
    示波器捕获显示了 PWM2_CTR 倒计时处丢失的事件、其中预计将清除 PWM2A、预计将设置 PWM2B。
     PHASE_UPDATE 和 PWMUpdate 的序列也很重要
    PHASE_UPDATE 每10ms 调用一次、它不会立即更新 PHS。 在 ADC 中断中执行的 PWMUpdate 将更新 PHS。 ADC 中断由 PWM1 PRD 事件触发。
    假设当 PHS 从340变为339时发生丢失的事件。 我使用以下方法:
    1. 如果目标(PWM_PHS <= CMPA)和之前的(PWM_PHS_PREV>= CMPA)、则不会立即加载 PHS。
    2. 然后、PWM 值按三个顺序更新:
      1. 首先、将 CMPA 值降低到低于目标相位。 CMPA = PWM_PHS - 1.
      2. 然后、将 PHS 设置为目标相位。 TBPHS = PWM_PHS。
      3. 最后、将 CMPA 设置回正常值。 CMPA =(EPwm2Regs.TBPRD >> 1);
    此过程需要三个中断才能更新 PHS。 虽然这种方法有助于避免大多数 PWM 跳过事件、但仍然发生约30%的跳过事件。

    void PWMUpdate(void)
    {
        if (skip_pwm_flag == 1) {
            EPwm2Regs.TBPHS.bit.TBPHS = pwm_phs;
            pwm_phs_prev  = EPwm2Regs.TBPHS.bit.TBPHS;
            skip_pwm_flag++;
        } else if (skip_pwm_flag == 2) {
            EPwm2Regs.CMPA.bit.CMPA   = (EPwm2Regs.TBPRD >> 1);
            skip_pwm_flag = 0;
        }
    
        if (update_request == 1) {
            update_request = 0;
            if (pwm_phs_prev >= EPwm2Regs.CMPA.bit.CMPA && pwm_phs <= EPwm2Regs.CMPA.bit.CMPA) {
                EPwm2Regs.CMPA.bit.CMPA   = pwm_phs - 1;
                skip_pwm_flag = 1;
            } else {
                EPwm2Regs.TBPHS.bit.TBPHS = pwm_phs;
                pwm_phs_prev  = EPwm2Regs.TBPHS.bit.TBPHS;
            }
        }
    }

    例如 ,在递增计数中,PHS 设置为高于 cmpa 的值,如果发生同步时 epwm2的时基计数器小于 cmpa,则可能会错过清除/置位低电平事件[/引号]
    只需确认、这里的同步是指 PWM1 CTR = 0、对吧? 根据 PWM 设置、如下所示
    EPwm1Regs.EPWMSYNCOUTEN.bit.ZEROEN = 1;
    EPwm1Regs.EPWMSYNCINSEL.bit.SEL    = SYNC_IN_SRC_DISABLE_ALL;
    
    EPwm2Regs.EPWMSYNCINSEL.bit.SEL = SYNC_IN_SRC_SYNCOUT_EPWM1;
    EPwm2Regs.CMPCTL.bit.SHDWAMODE  = CC_IMMEDIATE;
    EPwm2Regs.CMPCTL.bit.SHDWBMODE  = CC_IMMEDIATE;

    是否需要任何其他设置? 相位噪声的影响。

    此致、
    路易斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    • 首先、将 CMPA 值降低到低于目标相位。 CMPA = PWM_PHS - 1.
    • 然后、将 PHS 设置为目标相位。 TBPHS = PWM_PHS。
    [/报价]

    如果在写入相位之前更新 CMPA、则应该没问题。  在零同步输入事件阶段 自动加载时、您如何延迟相加载 事件?

    主要部分是计数器零同步输入事件的序列时序、并更新 CMPA 值。 您能详细介绍一下吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Prarthan、

    • 首先、将 CMPA 值降低到低于目标相位。 CMPA = PWM_PHS - 1.
    • 然后、将 PHS 设置为目标相位。 TBPHS = PWM_PHS。
    • 最后、将 CMPA 设置回正常值。 CMPA =(EPwm2Regs.TBPRD >> 1);
    [/报价]

    该序列在 由 PWM1 PRD 事件触发的 ADC 中断中执行。

    接收到更新请求后、   下一个中断 CMPA 会更新。 然后 仅在下一个中断中更新 PHS。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    第二个事件更改 PHS 您如何提供同步事件。 PHS 仅在发生同步事件时加载到计数器。

      

    收到更新请求后,   下一个中断 CMPA 将更新。 然后 仅在下一个中断中更新 PHS。
    [/报价]

    这3个事件中断何时发生? pwm1 prd 事件时。

    序列在 由 PWM1 PRD 事件触发的 ADC 中断中执行

    你是说三个中断发生在 ADC 中断内吗?

    谢谢。
    Prarthan.

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Prarthan、


    何时发生这3个事件中断? 在 pwm1 prd 事件上。

    是的、 发生 PWM PRD 事件时、如 pic 所示。

    您是说三个中断发生在 ADC 中断中吗

    否、每个 A/D 转换一个中断。 但是设置 CMPA 和 PHS 之间存在一个间隔(1x 中断)。 它们不会同时加载。

    当将间隔设置为1时、我没有看到 PWM 跳跃、 2倍  设置 CMPA 和  PHS 之间的中断。 根据我的配置、我想1x 中断是不够的。


    感谢您的支持、

    路易斯