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.

[参考译文] TMS320F28377S:具有死区时间的 HRPWM 上行-下行

Guru**** 2445440 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1015097/tms320f28377s-hrpwm-up-down-with-dead-time

器件型号:TMS320F28377S
主题中讨论的其他器件:C2000WARE

Hallo、

我需要扩展现有的 ePWM 配置。 我们基于3个同步的 ePWM 实现了 FOC。

周期和死区时间设置为一次且永不改变、CMPAx 用于占空比。 输出 EPWMxB 反相 EPWMxA。

CMPAx 的影子寄存器在单次触发模式下全局加载。

此外  、SOC_A 由 PWM2:CMPB 触发。 该计时是恒定的。

问题:

CAMPHR 已正确更新在调试器视图中可以看到的内容。 遗憾的是、在输出信号(示波器)中未看到任何结果。 它仍可用作无 HR 扩展的 ePWM。

当我添加 HRPWM 配置函数时、死区时间似乎消失了。 如果我完全删除死区时间支持、那么 HRPWM 将正常工作。

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM3);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRPWM); //sourced from ePWM1 clock source

    while  (m_sfo_status == SFO_INCOMPLETE) // Call until complete
    {
        m_sfo_status = SFO();
        if (m_sfo_status == SFO_ERROR)
        {
            ESTOP0;    // SFO function returns 2 if an error occurs and number of MEP steps/coarse step exceeds maximum of 255.
        }
    }

    // Disable sync(Freeze clock to PWM as well)
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    // ePWM1 - master
    GPIO_setPadConfig(145, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_145_EPWM1A); // phase UH
    GPIO_setPadConfig(146, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_146_EPWM1B);
   // ePWM2
    GPIO_setPadConfig(147, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_147_EPWM2A); // phase VH
    GPIO_setPadConfig(148, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_148_EPWM2B);
    // ePWM3
    GPIO_setPadConfig(149, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_149_EPWM3A);
    GPIO_setPadConfig(150, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_150_EPWM3B);

    // master PWM gets no phase shift
    set_ePWM_config( EPWM1_BASE, m_period, 0, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    // slave PWMs get always phase shift 2
    set_ePWM_config( EPWM2_BASE, m_period, 2, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    set_ePWM_config( EPWM3_BASE, m_period, 2, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );

    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); // EPWM 1 is master and olny sync generator
    EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
    EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave

    // ADC trigger offset (EPWM_COUNTER_COMPARE_B)
    EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, ( adc_trigger_pmwcount ));
    EPWM_setADCTriggerSource(EPWM2_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPB);
    EPWM_setADCTriggerEventPrescale(EPWM2_BASE, EPWM_SOC_A, 1);
    EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);
    EPWM_setCounterCompareShadowLoadMode( EPWM2_BASE,
                                          EPWM_COUNTER_COMPARE_B,
                                          EPWM_COMP_LOAD_ON_CNTR_ZERO);

    // Enable global shadow to active load for CMPA registers. See TRM 13.4.7.2 "One-Shot Load Mode"
    EPWM_enableGlobalLoad(EPWM1_BASE);  //GLDCTL[GLD]=1, individual shadowing is ignored
    EPWM_enableGlobalLoadOneShotMode(EPWM1_BASE); // GLDCTL[OSHTMODE] enable one-shot
    EPWM_enableGlobalLoadRegisters(EPWM1_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR); // GLDCFG - register to be shadow-loaded
    EPWM_setGlobalLoadTrigger(EPWM1_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD); //load on CNT_ZERO - GLDCTL[GLDMODE]
    EPWM_setupEPWMLinks(EPWM1_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger (the same value of GLDCTL2) to ePWM1

    EPWM_enableGlobalLoad(EPWM2_BASE);
    EPWM_enableGlobalLoadOneShotMode(EPWM2_BASE);
    EPWM_enableGlobalLoadRegisters(EPWM2_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
    EPWM_setGlobalLoadTrigger(EPWM2_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);
    EPWM_setupEPWMLinks(EPWM2_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger to ePWM1

    EPWM_enableGlobalLoad(EPWM3_BASE);
    EPWM_enableGlobalLoadOneShotMode(EPWM3_BASE);
    EPWM_enableGlobalLoadRegisters(EPWM3_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
    EPWM_setGlobalLoadTrigger(EPWM3_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);

    // see Technical Reference page 1566: should be enabled after all ePWMs are initialized
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
	
	
	
	
	
void set_ePWM_config(uint32_t epwm_base, uint16_t period, uint16_t offset, uint16_t deadband_delay_rising_edge, uint16_t deadband_delay_falling_edge)
{
    // Set-up TBCLK
    EPWM_setPeriodLoadMode(epwm_base, EPWM_PERIOD_DIRECT_LOAD); //direct load and never change, shadow is not used for period
    EPWM_setTimeBasePeriod(epwm_base, period);
    EPWM_setPhaseShift(epwm_base, offset);
    EPWM_setTimeBaseCounter(epwm_base, offset);
    EPWM_setEmulationMode(epwm_base, EPWM_EMULATION_FREE_RUN);

    // Set up counter mode
    EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP_DOWN);

    EPWM_setClockPrescaler(epwm_base,EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    // if offset == 0 then there is master ePWM
    if( 0 == offset )
    {
        EPWM_disablePhaseShiftLoad(epwm_base);
//        HRPWM_disablePhaseShiftLoad(epwm_base);
    }
    else
    {
        EPWM_enablePhaseShiftLoad(epwm_base);
        EPWM_setCountModeAfterSync(epwm_base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
    }
//    HRPWM_selectPeriodLoadEvent(epwm_base, EPWM_SHADOW_LOAD_MODE_SYNC); //load shadow when sync happens, TODO: no one wants to reload period register
//    HRPWM_setCounterCompareShadowLoadEvent(epwm_base, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_PERIOD); //slaves do not reach CNTR==0 because of phase shift --check it!
    // Set actions
    EPWM_setActionQualifierAction(epwm_base,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    // down counting: Output A low
    EPWM_setActionQualifierAction(epwm_base,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

    // enable rising and falling edge delay (S0, S1)
    EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_RED, true);
    EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_FED, true);
    // set EPWM_A as "lead" signal (S4, S5)
    EPWM_setRisingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
    EPWM_setFallingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
    // invert output logic of B, don't invert A (S2, S3)
    EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
    EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    // set output swapping of out_A/out_B (S6, S7)
    EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_A, true);
    EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_B, true);
    // set delay counts
    EPWM_setFallingEdgeDelayCount(epwm_base, deadband_delay_falling_edge);
    EPWM_setRisingEdgeDelayCount(epwm_base, deadband_delay_rising_edge);

//    HRPWM_disablePeriodControl(epwm_base);
    HRPWM_setMEPControlMode(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); //MEP controlled by value of CMPA
    HRPWM_setMEPEdgeSelect(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);

    HRPWM_setDeadbandMEPEdgeSelect(epwm_base, HRPWM_DB_MEP_CTRL_RED_FED);
//    HRPWM_setChannelBOutputPath(epwm_base, HRPWM_OUTPUT_ON_B_INV_A); //dead time is overwritten?
}

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

    您好!

    请给我一些时间来研究这个问题、并尽早返回给您。 周末后需要回复。

    谢谢、

    Aditya

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

    您好!

    我看不到 CMPAHR 寄存器在您的代码中更新。 您是否错过了将其放入代码段中? 这是 HR 正常工作所必需的。

    24位 CMPAHR 寄存器中的高8位仅构成 HR 配置、因此您可能在表达式窗口中看到的更新可能仅适用于低16位。 您可以参阅 C2000Ware 中的任何可用 HRPWM 示例、简要了解 HRPWM 配置。

    谢谢、

    Aditya

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

    您好!

    你是对的、我没有发布完整的代码。

    这里的函数用于设置3个 ePWM 的占空比、该 PWM 与 PWM 基计时器异步但一次(单次触发)。

    set_ratio( float uvw_from_0to1[] )
    {
        for (uint16_t i=0; i < 3; i++)
        {
            float ratio = uvw_from_0to1[i] * m_period;
            uint16_t ratio_in_ticks = static_cast<uint16_t>(ratio);
            uint16_t mep_ticks = static_cast<uint16_t>(0.5f + (ratio - (float)(ratio_in_ticks))*(float)MEP_ScaleFactor*2);
    		
            // don't allow 0 ticks (see technical reference manual page 1584)
            if (ratio_in_ticks == 0) 
    		    { ratio_in_ticks = 1; }
            if ((ratio_in_ticks < 3)||(ratio_in_ticks > m_period-3))  //TRM 14.3.1: If HRPCTL[HRPE=0]) and CMPA value is less than three cycles, then its CMPAHR must be cleared to zero.
    		    { mep_ticks = 0; }
            if (i == 0) {
                EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM1_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
            }
            else if(i == 1) {
                EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM2_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
            }
            else if(i == 2) {
                EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM3_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
                EPWM_setGlobalLoadOneShotLatch( EPWM3_BASE ); //one-shot update for already linked ePWM1 and ePWM2 on the next CNTR_ZERO event (once)
            }
        }
    }

    如前所述、我可以在调试器的帮助下观察 CMPAHR 变化。

    还有每5秒调用一次 SFO ()函数的代码。 它似乎起作用。 MEP_ScaleFactor 全局变量最初为0x40。 当我的电路板温度达到65摄氏度时 、MEP_ScaleFactor 会更新为0x41。

    我想我应该记得在完成之前没有完成 SFO ()。

    update_millisecond()
    {
        if(( millisecond_counter % 5000 == 0)||(m_sfo_status == SFO_INCOMPLETE)) //5s guard
        {
            m_sfo_status = SFO(); //m_sfo_status is global
            if (m_sfo_status == SFO_ERROR)
            {
                ESTOP0;    // SFO function returns 2 if an error occurs
            }
        }
        millisecond_counter++;
    }

    但是,问题是,以下线路的死区时间消失了:

    HRPWM_setChannelBOutputPath(epwm_base, HRPWM_OUTPUT_ON_B_INV_A);

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

    您好!

    除了您已经完成的配置之外、您还需要启用寄存器 HRPCTL 中的'HRPE'位来启用高分辨率周期。 为此、您可以在代码中适当地使用下面提到的行。

            HRPWM_enablePeriodControl(EPWM_BASE);

    请告诉我这是否有帮助。

    除此之外、仅供参考、您无需禁用和启用 GTBCLKSYNC 和 TBCLKSYNC。 根据应用的不同、只需要使用一个。 全局同步的工作方式超出 CPU1、TBCLKSYNC 则不是这种情况。 您可以在案例中删除全局同步。

    谢谢、

    Aditya

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

    您好、Aditya、

    我应该如何理解它? 我不想控制周期。 我只是想控制占空比。

    我已经尝试过命令、但它对我不起作用。

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

    您好!

    我需要进一步研究这一点。 我在代码中看不到任何与直接初始化相关的问题。 让我与其他专家核实一下、然后再与您联系。 届时、您能否尝试使用 C2000Ware 中提供的参考代码检查初始化配置? 此外、如果您可以共享源代码?

    Aditya

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

    您好!

    您是否能够解决此问题? 我认为问题可能是与全局加载相关的配置。 我看到您为此启用了单次触发模式。 我正在查看提供的代码、请告诉我您是否可以共享完整代码以便我可以从我的结尾检查它是否有任何问题?

    谢谢

    Vasudha

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

    您好!

    我直到现在才解决了我的问题。 如果使用 MEP、我仍然没有死区时间。 为了澄清我发布代码文件的原因、我要对它们进行线对线比较。 第一个文件 配置 ePWM 解决方案、该解决方案工作正常。 第二个文件包含作为第一个文件扩展名的 HRPWM、这适用于"不再死区时间"问题。
    一次性模式在运行时一次性提供全部三个 PWM 更新。 PWM 通道完整性非常重要。 从另一个线程调用:set_ratio()内存模块,也可以被中断。 唯一的洗浴液是一次性的。

    ePWM:

    // Configure ePWM module as master (period == 0) or slave synchronized block.
    void F2837x_Three_Phase_Power_Stage::set_ePWM_config(uint32_t epwm_base,
                                                             uint16_t period,
                                                             uint16_t offset,
                                                             bool invert_high_side_output_logic,
                                                             bool invert_low_side_output_logic,
                                                             uint16_t deadband_delay_rising_edge,
                                                             uint16_t deadband_delay_falling_edge)
    {
        // Set-up TBCLK
        EPWM_setTimeBasePeriod(epwm_base, period);
        EPWM_setPhaseShift(epwm_base, offset);
        EPWM_setTimeBaseCounter(epwm_base, offset);
    
        // Set up counter mode
        EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP_DOWN);
    
        EPWM_setClockPrescaler(epwm_base,EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    
        // Set up shadowing
        if( 0 != offset )
        {
            EPWM_setCounterCompareShadowLoadMode(epwm_base,
                                                 EPWM_COUNTER_COMPARE_A,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
        }
        // if offset == 0 then there is master ePWM
        if( 0 == offset )
        {
            EPWM_disablePhaseShiftLoad(epwm_base);
            EPWM_selectPeriodLoadEvent(epwm_base, EPWM_SHADOW_LOAD_MODE_COUNTER_ZERO); //TODO: no one wants to reload period register
        }
        else
        {
            EPWM_enablePhaseShiftLoad(epwm_base);
            EPWM_setCountModeAfterSync(epwm_base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
            EPWM_selectPeriodLoadEvent(epwm_base, EPWM_SHADOW_LOAD_MODE_SYNC); //TODO: no one wants to reload period register
        }
    
        // Set actions
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        // down counting: Output A low
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    
        // enable rising and falling edge delay (S0, S1)
        EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_FED, true);
        // set EPWM_A as "lead" signal (S4, S5)
        EPWM_setRisingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
        EPWM_setFallingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
        // invert output logic of B, don't invert A (S2, S3)
        EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
        // set output swapping of out_A/out_B (S6, S7)
        EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_A, invert_high_side_output_logic);
        EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_B, invert_low_side_output_logic);
        // set delay counts
        EPWM_setFallingEdgeDelayCount(epwm_base, deadband_delay_falling_edge);
        EPWM_setRisingEdgeDelayCount(epwm_base, deadband_delay_rising_edge);
    
    
    }
    
    
    F2837x_Three_Phase_Power_Stage::F2837x_Three_Phase_Power_Stage( float dc_link_voltage_in_V,
                                                                    uint32_t frequency_in_Hz,
                                                                    bool invert_high_side_output_logic,
                                                                    bool invert_low_side_output_logic,
                                                                    uint16_t deadband_delay_rising_edge_in_ticks,
                                                                    uint16_t deadband_delay_falling_edge_in_ticks,
                                                                    uint16_t adc_trigger_pmwcount) :
            Three_Phase_Power_Stage<float>(),
            m_period( ( system::get_cpu_clock_speed() / frequency_in_Hz ) / 4 ), // for up down count mode
            m_invert_high_side_output_logic(invert_high_side_output_logic),
            m_invert_low_side_output_logic(invert_low_side_output_logic),
            m_state(SWITCHES_OPEN),
            m_dc_link_voltage(dc_link_voltage_in_V)
    {
        debugprintf("F2837x_Three_Phase_Power_Stage %lu Hz\r\n", frequency_in_Hz);
    
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM3);
    
        // Disable sync(Freeze clock to PWM as well)
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // ePWM1 - master
        GPIO_setPadConfig(145, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_145_EPWM1A); // phase UH
        GPIO_setPadConfig(146, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_146_EPWM1B);
    
       // ePWM2
        GPIO_setPadConfig(147, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_147_EPWM2A); // phase VH
        GPIO_setPadConfig(148, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_148_EPWM2B);
    
        // ePWM3
        GPIO_setPadConfig(149, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_149_EPWM3A);
        GPIO_setPadConfig(150, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_150_EPWM3B);
    
        // master PWM gets no phase shift
        set_ePWM_config( EPWM1_BASE, m_period, 0, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
        // slave PWMs get always phase shift 2
        set_ePWM_config( EPWM2_BASE, m_period, 2, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
        set_ePWM_config( EPWM3_BASE, m_period, 2, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); // EPWM 1 is master and olny sync generator
        EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
        EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
    
        // Configure the SOC to occur on the first up-count event, doesn't work if PWM1 is the AD trigger, works with PWM2 without further investigation why
        // The chain of SOC conversions must be so triggered that the last SOC (u/v/w-current) meets PWM center. Calculations in excel sheet.
        EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, ( adc_trigger_pmwcount ));
        EPWM_setADCTriggerSource(EPWM2_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
        EPWM_setADCTriggerEventPrescale(EPWM2_BASE, EPWM_SOC_A, 1);
        EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);
    
        // Enable global shadow to active load for CMPB registers. See TRM 13.4.7.2 "One-Shot Load Mode"
        EPWM_enableGlobalLoad(EPWM1_BASE);  //GLDCTL[GLD]=1, individual shadowing is ignored
        EPWM_enableGlobalLoadOneShotMode(EPWM1_BASE); // GLDCTL[OSHTMODE] enable one-shot
        EPWM_enableGlobalLoadRegisters(EPWM1_BASE, EPWM_GL_REGISTER_CMPB_CMPBHR); // GLDCFG - register to be shadow-loaded
        EPWM_setGlobalLoadTrigger(EPWM1_BASE, EPWM_GL_LOAD_PULSE_CNTR_ZERO); //load on CNT_ZERO - GLDCTL[GLDMODE]
        EPWM_setupEPWMLinks(EPWM1_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger to ePWM1
    
        EPWM_enableGlobalLoad(EPWM2_BASE);
        EPWM_enableGlobalLoadOneShotMode(EPWM2_BASE);
        EPWM_enableGlobalLoadRegisters(EPWM2_BASE, EPWM_GL_REGISTER_CMPB_CMPBHR);
        EPWM_setGlobalLoadTrigger(EPWM2_BASE, EPWM_GL_LOAD_PULSE_CNTR_ZERO);
        EPWM_setupEPWMLinks(EPWM2_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2);
    
        EPWM_enableGlobalLoad(EPWM3_BASE);
        EPWM_enableGlobalLoadOneShotMode(EPWM3_BASE);
        EPWM_enableGlobalLoadRegisters(EPWM3_BASE, EPWM_GL_REGISTER_CMPB_CMPBHR);
        EPWM_setGlobalLoadTrigger(EPWM3_BASE, EPWM_GL_LOAD_PULSE_CNTR_ZERO);
    
        // see Technical Reference page 1566: should be enabled after all ePWMs are initialized
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // if all half bridges are phase synchron and are set to 50% duty cycle, the two zero voltage vectors are set in alternated
        set_ratio(Three_Component_Vector<float>(0.5, 0.5, 0.5));
    
        // switch off at first
        open_switches();
    }
    
    //updating PWM duty works correct
    void F2837x_Three_Phase_Power_Stage::set_ratio( Three_Component_Vector<float> uvw_from_0to1 )
    {
        for (uint16_t i=0; i < 3; i++)
        {
    //      assert( uvw_from_0to1.access_component_by_index(i) <= 1.0f );
    //      assert( uvw_from_0to1.access_component_by_index(i) >= 0.0f );
    
            // saturate
            if( uvw_from_0to1.access_component_by_index(i) > 1.0f ) { uvw_from_0to1.access_component_by_index(i) = 1.0f; }
            if( uvw_from_0to1.access_component_by_index(i) < 0.0f ) { uvw_from_0to1.access_component_by_index(i) = 0.0f; }
            uint16_t ratio_in_ticks = static_cast<uint16_t>(uvw_from_0to1.access_component_by_index(i) * m_period);
    
            // don't allow 0 ticks (see technical reference manual page 1584)
            if (ratio_in_ticks == 0) { ratio_in_ticks = 1; }
    
            if (i == 0) {
                EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, ratio_in_ticks);
            }
            else if(i == 1) {
                EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, ratio_in_ticks);
            }
            else if(i == 2) {
                EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_B, ratio_in_ticks);
                EPWM_setGlobalLoadOneShotLatch( EPWM3_BASE ); //one-shot update for already linked ePWM1 and ePWM2 on the next CNTR_ZERO event (once)
            }
        }
    }
    
    
    
    void F2837x_Three_Phase_Power_Stage::enable_pwm_generation(void)
    {
        uint32_t base(EPWM1_BASE);
        for ( uint16_t i = 0; i < 3; i++ )
        {
            switch(i)
            {
                case 0: default: break;
                case 1: base = EPWM2_BASE; break;
                case 2: base = EPWM3_BASE; break;
            }
            EPWM_setActionQualifierContSWForceAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_SW_DISABLED);
            EPWM_setActionQualifierContSWForceAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_DISABLED);
    
            //(re)enable deadband unit
            EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true);
            EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true);
        }
    
        m_state = OPERATING;
    }
    
    
    void F2837x_Three_Phase_Power_Stage::open_switches(void)
    {
        uint32_t base(EPWM1_BASE);
        for ( uint16_t i = 0; i < 3; i++ )
        {
            switch(i)
            {
                case 1: base = EPWM2_BASE; break;
                case 2: base = EPWM3_BASE; break;
                case 0:
                default:
                    break;
            }
            EPWM_setActionQualifierContSWForceAction( base, EPWM_AQ_OUTPUT_A, (m_invert_high_side_output_logic ? EPWM_AQ_SW_OUTPUT_HIGH : EPWM_AQ_SW_OUTPUT_LOW) );
            EPWM_setActionQualifierContSWForceAction( base, EPWM_AQ_OUTPUT_B, (m_invert_low_side_output_logic ? EPWM_AQ_SW_OUTPUT_HIGH : EPWM_AQ_SW_OUTPUT_LOW) );
    
            // disable rising and falling edge delay (S0, S1): activate bypassing of deadband unit
            EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, false);
            EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, false);
        }
    
        m_state = SWITCHES_OPEN;
    }
    
    float F2837x_Three_Phase_Power_Stage::get_pwm_frequency_in_Hz(void)
    {
        return ( system::get_cpu_clock_speed() / (m_period * 4) );
    }
    
    

    HRPWM:

    extern uint32_t MEP_ScaleFactor = 0; // Global variable used by teh SFO library
    
    #define myEPWM1_BASE EPWM1_BASE
    #define myEPWM2_BASE EPWM2_BASE
    #define myEPWM3_BASE EPWM3_BASE
    
    extern volatile uint32_t ePWM[] = { 0, myEPWM1_BASE, myEPWM2_BASE, myEPWM3_BASE };
    
    // Configure ePWM module as master (period == 0) or slave synchronized block.
    void F2837x_Three_Phase_Power_Stage::set_ePWM_config(uint32_t epwm_base,
                                                             uint16_t period,
                                                             uint16_t offset,
                                                             bool invert_high_side_output_logic,
                                                             bool invert_low_side_output_logic,
                                                             uint16_t deadband_delay_rising_edge,
                                                             uint16_t deadband_delay_falling_edge)
    {
        // Set-up TBCLK
        EPWM_setPeriodLoadMode(epwm_base, EPWM_PERIOD_DIRECT_LOAD); //direct load and never change, shadow is not used for period
        EPWM_setTimeBasePeriod(epwm_base, period);
        EPWM_setPhaseShift(epwm_base, offset);
        EPWM_setTimeBaseCounter(epwm_base, offset);
        EPWM_setEmulationMode(epwm_base, EPWM_EMULATION_FREE_RUN);
    
        // Set up counter mode
        EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP_DOWN);
    
        EPWM_setClockPrescaler(epwm_base,EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    
        // if offset == 0 then there is master ePWM
        if( 0 == offset )
        {
            EPWM_disablePhaseShiftLoad(epwm_base);
            HRPWM_disablePhaseShiftLoad(epwm_base);
        }
        else
        {
            EPWM_enablePhaseShiftLoad(epwm_base);
            EPWM_setCountModeAfterSync(epwm_base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
        }
    
        HRPWM_setCounterCompareShadowLoadEvent(epwm_base, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO); //slaves do not reach CNTR==0 because of phase shift --check it!
        EPWM_setCounterCompareShadowLoadMode( epwm_base,
                                              EPWM_COUNTER_COMPARE_A,
                                              EPWM_COMP_LOAD_ON_CNTR_ZERO); //ADC SOC, exactly only for ePWM2
        // Set actions
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // down counting: Output A low
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
        // enable rising and falling edge delay (S0, S1)
        EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_FED, true);
        // set EPWM_A as "lead" signal (S4, S5)
        EPWM_setRisingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
        EPWM_setFallingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
        // invert output logic of B, don't invert A (S2, S3)
        EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
        // set output swapping of out_A/out_B (S6, S7)
        EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_A, invert_high_side_output_logic);
        EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_B, invert_low_side_output_logic);
        // set delay counts
        EPWM_setFallingEdgeDelayCount(epwm_base, deadband_delay_falling_edge);
        EPWM_setRisingEdgeDelayCount(epwm_base, deadband_delay_rising_edge);
    
        HRPWM_disablePeriodControl(epwm_base);
        HRPWM_setMEPControlMode(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); //MEP controlled by value of CMPA
        HRPWM_setMEPEdgeSelect(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE);
        HRPWM_setChannelBOutputPath(epwm_base, HRPWM_OUTPUT_ON_B_INV_A); //dead time is overwritten, destructed!!!
        HRPWM_setSyncPulseSource(epwm_base, HRPWM_PWMSYNC_SOURCE_PERIOD); //?
    
        HRPWM_setDeadbandMEPEdgeSelect(epwm_base, HRPWM_DB_MEP_CTRL_RED); //no effect of this call
    }
    
    
    F2837x_Three_Phase_Power_Stage::F2837x_Three_Phase_Power_Stage( float dc_link_voltage_in_V,
                                                                    uint32_t frequency_in_Hz,
                                                                    bool invert_high_side_output_logic,
                                                                    bool invert_low_side_output_logic,
                                                                    uint16_t deadband_delay_rising_edge_in_ticks,
                                                                    uint16_t deadband_delay_falling_edge_in_ticks,
                                                                    uint16_t adc_trigger_pmwcount,
                                                                    F2837x_CPU_Timer_0& hw_timer) :
            Three_Phase_Power_Stage<float>(),
            m_period( ( system::get_cpu_clock_speed() / frequency_in_Hz ) / 4 ), // for up down count mode
            m_invert_high_side_output_logic(invert_high_side_output_logic),
            m_invert_low_side_output_logic(invert_low_side_output_logic),
            m_state(SWITCHES_OPEN),
            m_dc_link_voltage(dc_link_voltage_in_V),
            m_ms_cpu_timer(hw_timer),
            m_ms_counter(0),
            m_sfo_status(SFO_INCOMPLETE)
    {
        debugprintf("F2837x_Three_Phase_Power_Stage %lu Hz\r\n", frequency_in_Hz);
    
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM3);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRPWM); //sourced from ePWM1 clock source
    
        while  (m_sfo_status == SFO_INCOMPLETE) // Call until complete
        {
            m_sfo_status = SFO();
            if (m_sfo_status == SFO_ERROR)
            {
                ESTOP0;    // SFO function returns 2 if an error occurs and number of MEP steps/coarse step exceeds maximum of 255.
            }
        }
    
        // Disable sync(Freeze clock to PWM as well)
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
    
        // ePWM1 - master
        GPIO_setPadConfig(145, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_145_EPWM1A); // phase UH
        GPIO_setPadConfig(146, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_146_EPWM1B);
    
       // ePWM2
        GPIO_setPadConfig(147, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_147_EPWM2A); // phase VH
        GPIO_setPadConfig(148, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_148_EPWM2B);
    
        // ePWM3
        GPIO_setPadConfig(149, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_149_EPWM3A);
        GPIO_setPadConfig(150, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_150_EPWM3B);
    
        // master PWM gets no phase shift
        set_ePWM_config( EPWM1_BASE, m_period, 0, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
        // slave PWMs get always phase shift 2
        set_ePWM_config( EPWM2_BASE, m_period, 2, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
        set_ePWM_config( EPWM3_BASE, m_period, 2, m_invert_high_side_output_logic, m_invert_low_side_output_logic, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); // EPWM 1 is master and olny sync generator
        EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
        EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
    
        // Configure the SOC to occur on the first up-count event, doesn't work if PWM1 is the AD trigger, works with PWM2 without further investigation why
        // The chain of SOC conversions must be so triggered that the last SOC (u/v/w-current) meets PWM center. Calculations in excel sheet.
        EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, ( adc_trigger_pmwcount ));
        EPWM_setADCTriggerSource(EPWM2_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPB);
        EPWM_setADCTriggerEventPrescale(EPWM2_BASE, EPWM_SOC_A, 1);
        EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);
        EPWM_setCounterCompareShadowLoadMode( EPWM2_BASE,
                                              EPWM_COUNTER_COMPARE_B,
                                              EPWM_COMP_LOAD_ON_CNTR_ZERO); //ADC SOC, exactly only for ePWM2
    
        // Enable global shadow to active load for CMPA registers. See TRM 13.4.7.2 "One-Shot Load Mode"
        EPWM_enableGlobalLoad(EPWM1_BASE);  //GLDCTL[GLD]=1, individual shadowing is ignored
        EPWM_enableGlobalLoadOneShotMode(EPWM1_BASE); // GLDCTL[OSHTMODE] enable one-shot
        EPWM_enableGlobalLoadRegisters(EPWM1_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR); // GLDCFG - register to be shadow-loaded
        EPWM_setGlobalLoadTrigger(EPWM1_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD); //load on CNT_ZERO - GLDCTL[GLDMODE]
        EPWM_setupEPWMLinks(EPWM1_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger (the same value of GLDCTL2) to ePWM1
    
        EPWM_enableGlobalLoad(EPWM2_BASE);
        EPWM_enableGlobalLoadOneShotMode(EPWM2_BASE);
        EPWM_enableGlobalLoadRegisters(EPWM2_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
        EPWM_setGlobalLoadTrigger(EPWM2_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);
        EPWM_setupEPWMLinks(EPWM2_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger to ePWM1
    
        EPWM_enableGlobalLoad(EPWM3_BASE);
        EPWM_enableGlobalLoadOneShotMode(EPWM3_BASE);
        EPWM_enableGlobalLoadRegisters(EPWM3_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
        EPWM_setGlobalLoadTrigger(EPWM3_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);
    
        // see Technical Reference page 1566: should be enabled after all ePWMs are initialized
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // if all half bridges are phase synchron and are set to 50% duty cycle, the two zero voltage vectors are set in alternated
        set_ratio(Three_Component_Vector<float>(0.5, 0.5, 0.5));
    
        // switch off at first
        open_switches();
    }
    
    //updating PWM duty works correct
    void F2837x_Three_Phase_Power_Stage::set_ratio( Three_Component_Vector<float> uvw_from_0to1 )
    {
        for (uint16_t i=0; i < 3; i++)
        {
    //      assert( uvw_from_0to1.access_component_by_index(i) <= 1.0f );
    //      assert( uvw_from_0to1.access_component_by_index(i) >= 0.0f );
    
            // saturate
            if( uvw_from_0to1.access_component_by_index(i) > 1.0f ) { uvw_from_0to1.access_component_by_index(i) = 1.0f; }
            if( uvw_from_0to1.access_component_by_index(i) < 0.0f ) { uvw_from_0to1.access_component_by_index(i) = 0.0f; }
    
            float ratio = uvw_from_0to1.access_component_by_index(i) * m_period;
            uint16_t ratio_in_ticks = static_cast<uint16_t>(ratio);
            uint16_t mep_ticks = static_cast<uint16_t>(0.5f + (ratio - (float)(ratio_in_ticks))*(float)MEP_ScaleFactor*2); //MEP scaling factor ca. 66
            // don't allow 0 ticks (see technical reference manual page 1584)
            if (ratio_in_ticks == 0) { ratio_in_ticks = 1; }
            if ((ratio_in_ticks < 3)||(ratio_in_ticks > m_period-3)) { mep_ticks = 0; } //TRM 14.3.1: If HRPCTL[HRPE=0]) and CMPA value is less than three cycles, then its CMPAHR must be cleared to zero.
    
            if (i == 0) {
                EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM1_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
            }
            else if(i == 1) {
                EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM2_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
            }
            else if(i == 2) {
                EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, ratio_in_ticks);
                HRPWM_setHiResCounterCompareValueOnly(EPWM3_BASE, HRPWM_COUNTER_COMPARE_A, mep_ticks);
                EPWM_setGlobalLoadOneShotLatch( EPWM3_BASE ); //one-shot update for already linked ePWM1 and ePWM2 on the next CNTR_ZERO event (once)
            }
        }
    }
    
    
    
    void F2837x_Three_Phase_Power_Stage::enable_pwm_generation(void)
    {
        uint32_t base(EPWM1_BASE);
        for ( uint16_t i = 0; i < 3; i++ )
        {
            switch(i)
            {
                case 0: default: break;
                case 1: base = EPWM2_BASE; break;
                case 2: base = EPWM3_BASE; break;
            }
            EPWM_setActionQualifierContSWForceAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_SW_DISABLED);
            EPWM_setActionQualifierContSWForceAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_DISABLED);
            //(re)enable deadband unit
            EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true);
            EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true);
        }
    
        m_state = OPERATING;
    }
    
    
    void F2837x_Three_Phase_Power_Stage::open_switches(void)
    {
        uint32_t base(EPWM1_BASE);
        for ( uint16_t i = 0; i < 3; i++ )
        {
            switch(i)
            {
                case 1: base = EPWM2_BASE; break;
                case 2: base = EPWM3_BASE; break;
                case 0:
                default:
                    break;
            }
            EPWM_setActionQualifierContSWForceAction( base, EPWM_AQ_OUTPUT_A, (m_invert_high_side_output_logic ? EPWM_AQ_SW_OUTPUT_HIGH : EPWM_AQ_SW_OUTPUT_LOW) );
            EPWM_setActionQualifierContSWForceAction( base, EPWM_AQ_OUTPUT_B, (m_invert_low_side_output_logic ? EPWM_AQ_SW_OUTPUT_HIGH : EPWM_AQ_SW_OUTPUT_LOW) );
            // disable rising and falling edge delay (S0, S1): activate bypassing of deadband unit
            EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, false);
            EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, false);
        }
    
        m_state = SWITCHES_OPEN;
    }
    
    float F2837x_Three_Phase_Power_Stage::get_pwm_frequency_in_Hz(void)
    {
        return ( system::get_cpu_clock_speed() / (m_period * 4) );
    }
    
    //called every 60 seconds to update MEP
    void F2837x_Three_Phase_Power_Stage::update(Timer* subject ATTRIBUTE_UNUSED)
    {
        if(( m_ms_counter % 5000 == 0)||(m_sfo_status == SFO_INCOMPLETE)) //0,5s..5s
        {
            m_sfo_status = SFO();
            if (m_sfo_status == SFO_ERROR)
            {
                ESTOP0;    // SFO function returns 2 if an error occurs & # of MEP steps/coarse step
            }              // exceeds maximum of 255.
        }
        m_ms_counter++;
    }
    
    

    大家好

    Maciej Drozd

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

    您好!

    我认为需要设置 HRPE 位来控制周期和占空比。 PFB TRM 中的描述。

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

    您好!

    很难理解 HRPE 下会发生什么。

    当我使用调试器将运行时的 HPRE 与已在工作的 PWM (示波器监控)从0更改为1时、它停止生成 PWM 信号。

    2.当我在提到 HRPE 1 -> 0后恢复时、它将不会再次起作用。 我必须重新启动程序。

    在 sourcecode 和函数 HRPWM_enablePeriodControl()的帮助下设置 HRPE 将导致 PWM 根本不会启动。

    为什么我观察到具有 HRPE 位复位(AS 0)的高分辨率 PWM?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="249" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1015097/tms320f28377s-hrpwm-up-down-with-dead-time/3785615 #3785615"]需要设置 HRPE 位来控制周期和占空比

    如果您使用向上/向下计数模式、请打开高分辨率周期控制、以使占空比在两个边沿上都具有 HR

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

    我可以关闭此问题、因为我已完全重新编写代码。 建议的更改对上述发布的代码没有帮助。