主题中讨论的其他器件: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?
}
