Part Number:DRV8329AEVMOther Parts Discussed in Thread:DRV8329, CSD19506KTT, UCC27284, , C2000WARE
半桥栅极驱动器用3个UCC27284替换DRV8329+CSD19506KTT控制BLDC,问题如下:
1、在hal.c中配置PWM, 实测EPWM3无波形,其他两相有PWM波
// GPIO227->EPWM3A->M1_UH
GPIO_setPinConfig(GPIO_227_EPWM3_A);
GPIO_setDirectionMode(227, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(227, GPIO_PIN_TYPE_STD);
// GPIO230->EPWM3B->M1_UL
GPIO_setPinConfig(GPIO_230_EPWM3_B);
GPIO_setDirectionMode(230, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(230, GPIO_PIN_TYPE_STD);
// GPIO0->EPWM1A->M1_VH
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
// GPIO1->EPWM1B->M1_VL
GPIO_setPinConfig(GPIO_1_EPWM1_B);
GPIO_setDirectionMode(1, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
// GPIO2->EPWM2_A->M1_WH
GPIO_setPinConfig(GPIO_2_EPWM2_A);
GPIO_setDirectionMode(2, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD);
// GPIO3->EPWM2_B->M1_WL
GPIO_setPinConfig(GPIO_3_EPWM2_B);
GPIO_setDirectionMode(3, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD);
2、参照DRV8329AEVM控制流程,换成非SPI接口的UCC27284,软件怎么移植,能否提供参考文档?
谢谢
liang zuxing:
软件基于c2000\C2000Ware_MotorControl_SDK_4_02_01_00\solutions\universal_motorcontrol_lab\f280013x工程
,
Cherry Zhou:
您好,您的问题我们需要升级到英文论坛寻求帮助,如有答复将尽快回复您。
,
Cherry Zhou:
您好,
抱歉回复晚了。
1)请问您使用的C2000器件是什么-是 F280013x 吗?
2)用于 ePWM3与 ePWM1和2的 ePWM 配置代码是否有差异? 如果是基于通用电机控制实验,还请检查是否使用了 ePWM6而不是 ePWM3 -几种不同的 C2000/逆变器器件组合就是该问题。
3)如果您想了解通用电机控制实验室代码的移植,UMCL 用户指南中有一个部分讨论了如何移植到其他 C2000 MCU 和逆变器板。
,
liang zuxing:
感谢Cherry Zhou支持。 现在三组PWM波形出来。但是PWM波中的死区配置没起作用。PWM波使用的ePWM1,ePWM2,ePWM3,
代码里也确认对DB有配置,麻烦看看为什么没起作用呢。代码如下:
void HAL_setupPWMs(HAL_MTR_Handle handle){
HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle; uint16_t cnt;
uint16_t pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM); uint16_t numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
// disable the ePWM module time base clock sync signal // to synchronize all of the PWMs SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
// turns off the outputs of the EPWM peripherals which will put the power // switches into a high impedance state. EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST);
for(cnt=0; cnt<3; cnt++) { // setup the Time-Base Control Register (TBCTL) EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt], EPWM_COUNTER_MODE_UP_DOWN);
EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]);
EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_DIRECT_LOAD);
EPWM_enableSyncOutPulseSource(obj->pwmHandle[cnt], EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setCountModeAfterSync(obj->pwmHandle[cnt], EPWM_COUNT_MODE_UP_AFTER_SYNC);
EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN);
// setup the Timer-Based Phase Register (TBPHS) EPWM_setPhaseShift(obj->pwmHandle[cnt], 0);
// setup the Time-Base Counter Register (TBCTR) EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0);
// setup the Time-Base Period Register (TBPRD) // set to zero initially EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0);
// setup the Counter-Compare Control Register (CMPCTL) EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_C, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_D, EPWM_COMP_LOAD_ON_CNTR_ZERO);
// setup the Action-Qualifier Output A Register (AQCTLA) EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
// setup the Dead-Band Generator Control Register (DBCTL) EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true);
// select EPWMA as the input to the dead band generator EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt], EPWM_DB_INPUT_EPWMA);
// configure the right polarity for active high complementary config. EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
// setup the Dead-Band Rising Edge Delay Register (DBRED) EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBRED_CNT);
// setup the Dead-Band Falling Edge Delay Register (DBFED) EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBFED_CNT);
#endif //!MOTOR1_ISBLDC
// setup the PWM-Chopper Control Register (PCCTL) EPWM_disableChopper(obj->pwmHandle[cnt]);
// setup the Trip Zone Select Register (TZSEL) EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], HAL_TZSEL_SIGNALS_ALL);
// setup the Event Trigger Selection Register (ETSEL) EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
EPWM_enableInterrupt(obj->pwmHandle[0]);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
// ADC SOC trigger for the 1st dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[1], EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_A);
// ADC SOC trigger for the 2nd dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[1], EPWM_SOC_B, EPWM_SOC_TBCTR_U_CMPD);
EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_B);
// ADC SOC trigger for the 3rd dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[2], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_A);
// ADC SOC trigger for the 4th dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[2], EPWM_SOC_B, EPWM_SOC_TBCTR_D_CMPD);
EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_B);#else //!(MOTOR1_ISBLDC || MOTOR1_DCLINKSS) // setup the Event Trigger Selection Register (ETSEL) EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
EPWM_enableInterrupt(obj->pwmHandle[0]);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);#endif // !(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
// setup the Event Trigger Prescale Register (ETPS) if(numPWMTicksPerISRTick > 15) { numPWMTicksPerISRTick = 15; } else if(numPWMTicksPerISRTick < 1) { numPWMTicksPerISRTick = 1; }
EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B, numPWMTicksPerISRTick);
#if defined(MOTOR1_DCLINKSS) EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_B, numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_B, numPWMTicksPerISRTick);#endif //MOTOR1_DCLINKSS
// setup the Event Trigger Clear Register (ETCLR) EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]); EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_B);
// since the PWM is configured as an up/down counter, the period register is // set to one-half of the desired PWM period EPWM_setTimeBasePeriod(obj->pwmHandle[0], pwmPeriodCycles); EPWM_setTimeBasePeriod(obj->pwmHandle[1], pwmPeriodCycles); EPWM_setTimeBasePeriod(obj->pwmHandle[2], pwmPeriodCycles);
// write the PWM data value for ADC trigger EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10);
// write the PWM data value for ADC trigger#if defined(MOTOR1_DCLINKSS) EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_B);
EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_B);
EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1); EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1); EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
#endif //MOTOR1_DCLINKSS
return;
}
,
Cherry Zhou:
您好,
liang zuxing said:但是PWM波中的死区配置没起作用。
请问您能否具体再说明一下是如何判断其不起作用? 在示波器中看到的哪种行为指示 DB 子模块未正确配置?
此外,您发送的代码中有4个大括号{和3个右大括号},因此不太可能正确编译-同样由于这个原因,我们无法分辨 for 循环的结尾在哪里。
,
liang zuxing:
感谢Cherry Zhou支持。找到原因了,是DB模块配置的死区太小,示波器上展开波形都不明显。我把死区时间加大就明显了。现在PWM波控制BLDC还有一个问题,查阅各种资料了解到每一组PWM波需要做成互补波形并带死区配置,防止同一组MOS同时导通导致短路,根据TI的Universal Motor Control Project and Lab User’s Guide开发文档三组PWM波的相位是要错开的,但是对3组波形的相位差距怎么配置没有找到,导致我现在的3组PWM波的高变的相位完全相同,MOS管工作异常,拉动输入电源频繁波动。请指点一下驱动三相BLDC的PWM波相位需要配置成什么样子,怎么配置。下面贴出TI开发板PWM设置的完整函数,其中宏定义用的是MOTOR1_DCLINKSS,
void HAL_setupPWMs(HAL_MTR_Handle handle){ HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle; uint16_t cnt;
uint16_t pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM); uint16_t numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
// disable the ePWM module time base clock sync signal // to synchronize all of the PWMs SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
// turns off the outputs of the EPWM peripherals which will put the power // switches into a high impedance state. EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST);
#if defined(BSXL8323RS_REVA) || defined(BSXL8323RH_REVB) || \ defined(BSXL8353RS_REVA) || defined(BSXL8316RT_REVA) || \ defined(BSXL3PHGAN_REVA) || defined(HVMTRPFC_REV1P1) || \ defined(DRV8329AEVM_REVA)
for(cnt=0; cnt<3; cnt++) { // setup the Time-Base Control Register (TBCTL) EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt], EPWM_COUNTER_MODE_UP_DOWN);
EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]);
EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_DIRECT_LOAD);
EPWM_enableSyncOutPulseSource(obj->pwmHandle[cnt], EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setCountModeAfterSync(obj->pwmHandle[cnt], EPWM_COUNT_MODE_UP_AFTER_SYNC);
EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN);
// setup the Timer-Based Phase Register (TBPHS) EPWM_setPhaseShift(obj->pwmHandle[cnt], 0);
// setup the Time-Base Counter Register (TBCTR) EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0);
// setup the Time-Base Period Register (TBPRD) // set to zero initially EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0);
// setup the Counter-Compare Control Register (CMPCTL) EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_C, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_D, EPWM_COMP_LOAD_ON_CNTR_ZERO);
#if defined(MOTOR1_ISBLDC) // setup the Action-Qualifier Output A Register (AQCTLA) EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
// setup the Action-qualifier Continuous Software Force Register (AQCSFRC) EPWM_setActionQualifierContSWForceAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_OUTPUT_LOW);
// setup the Dead-Band Generator Control Register (DBCTL) EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, false); EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, false);
#else //!MOTOR1_ISBLDC
#if defined(MOTOR1_DCLINKSS) // setup the Action-Qualifier Output A Register (AQCTLA) EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);#else // !(MOTOR1_DCLINKSS) // setup the Action-Qualifier Output A Register (AQCTLA) EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
#endif // !(MOTOR1_DCLINKSS)
// setup the Dead-Band Generator Control Register (DBCTL) EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true);
// select EPWMA as the input to the dead band generator EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt], EPWM_DB_INPUT_EPWMA);
// configure the right polarity for active high complementary config. EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
// setup the Dead-Band Rising Edge Delay Register (DBRED) EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBRED_CNT);
// setup the Dead-Band Falling Edge Delay Register (DBFED) EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBFED_CNT);
#endif //!MOTOR1_ISBLDC
// setup the PWM-Chopper Control Register (PCCTL) EPWM_disableChopper(obj->pwmHandle[cnt]);
// setup the Trip Zone Select Register (TZSEL) EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], HAL_TZSEL_SIGNALS_ALL); }
// BSXL8323RS_REVA || BSXL8323RH_REVB || BSXL8353RS_REVA || \ // BSXL8316RT_REVA || BSXL3PHGAN_REVA || HVMTRPFC_REV1P1 || \ // DRV8329AEVM_REVA#else#error The PWM is not configured for motor_1 control#endif // boards
#if defined(MOTOR1_ISBLDC) // setup the Event Trigger Selection Register (ETSEL) EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
EPWM_disableInterrupt(obj->pwmHandle[0]);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_B, EPWM_SOC_TBCTR_U_CMPB);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_B);#elif defined(MOTOR1_DCLINKSS) // setup the Event Trigger Selection Register (ETSEL) EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
EPWM_enableInterrupt(obj->pwmHandle[0]);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
// ADC SOC trigger for the 1st dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[1], EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_A);
// ADC SOC trigger for the 2nd dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[1], EPWM_SOC_B, EPWM_SOC_TBCTR_U_CMPD);
EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_B);
// ADC SOC trigger for the 3rd dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[2], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_A);
// ADC SOC trigger for the 4th dc-link current sampling EPWM_setADCTriggerSource(obj->pwmHandle[2], EPWM_SOC_B, EPWM_SOC_TBCTR_D_CMPD);
EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_B);#else //!(MOTOR1_ISBLDC || MOTOR1_DCLINKSS) // setup the Event Trigger Selection Register (ETSEL) EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
EPWM_enableInterrupt(obj->pwmHandle[0]);
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);#endif // !(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
// setup the Event Trigger Prescale Register (ETPS) if(numPWMTicksPerISRTick > 15) { numPWMTicksPerISRTick = 15; } else if(numPWMTicksPerISRTick < 1) { numPWMTicksPerISRTick = 1; }
EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B, numPWMTicksPerISRTick);
#if defined(MOTOR1_DCLINKSS) EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_B, numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_A, numPWMTicksPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_B, numPWMTicksPerISRTick);#endif //MOTOR1_DCLINKSS
// setup the Event Trigger Clear Register (ETCLR) EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]); EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_B);
// since the PWM is configured as an up/down counter, the period register is // set to one-half of the desired PWM period EPWM_setTimeBasePeriod(obj->pwmHandle[0], pwmPeriodCycles); EPWM_setTimeBasePeriod(obj->pwmHandle[1], pwmPeriodCycles); EPWM_setTimeBasePeriod(obj->pwmHandle[2], pwmPeriodCycles);
// write the PWM data value for ADC trigger EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10);
// write the PWM data value for ADC trigger#if defined(MOTOR1_DCLINKSS) EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_B);
EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_B);
EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1); EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1); EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
#endif //MOTOR1_DCLINKSS return;
}
,
Cherry Zhou:
好的,另外的问题我们跟进给工程师看下,应该会在下周工作日给到您答复。
,
Cherry Zhou:
您好,
要查找单个 ePWM 高侧和低侧之间的死区(在 ePWM 时钟节拍中),请在 hal.h 文件中搜索 MTR1_PWM_DBRED_CNT 和 MTR1_PWM_DBFED_CNT。 默认值通常是没有问题的,但如果更改了这些值,请确保它们彼此相等。
对于三相输出,容易混淆的地方是,Universal Lab中的三组 PWM 波形及类似波形在该过程中的任何点都不会手动偏移。 相反的是,因为电机的三相由于电机的性质而相互偏移,来自 ADC 的测量值将会反映这一点。 对于三个不同的 ADC 值,SVGEN_run() 空间矢量调制例程和 HAL_writePWMData() PWM CMPx 计算函数将始终会导致三个 ePWM 之间的 CMPx 值存在明显差异。如果计算出的三个电流相位彼此同相,请检查下 ADC 采样硬件和软件或用于单分流器重建例程的参数。 这里有些地方可能会有问题。 您能否分享下从示波器观察到的波形?
,
liang zuxing:
感谢Cherry Zhou回复。我现在按照TI开发文档,设置系统编译级别是DMC_BUILDLEVEL=1,这个阶段只是检测MCU PWM波形输出和ADC采样,不涉及采样后波形计算。我想确认这个阶段3组PWM正常波形是什么样子。我现在的PWM波确认了带死区。
,
Cherry Zhou:
您好,
非常开心看到DB已被确认。
在build level1中,根据 Universal Motor Control Lab user's guide, PWM 波形不会偏移:
,
liang zuxing:
感谢Cherry Zhou回复。 从你贴的开发文档的图看出,3组PWM的波形相位相同,每一组波形互补并且带死区。仔细对比我的波形图可以确认PWM波设置正确了。问题正如你上面的分析,应该出现在软件ADC的配置或者是硬件问题。先从ADC软件角度找原因。关于ADC配置问题有以下疑问,请解答:
1、ADC_BASE问题,如下,如果复用脚选A4是否就应该配置ADCA_BASE?如果服用脚选C14是否就应该配置ADCC_BASE?两种随意配置吗?
#define MTR1_VU_ADC_BASE ADCA_BASE // ADCA-A6*#define MTR1_VV_ADC_BASE ADCA_BASE // ADCC-A3*/C5#define MTR1_VW_ADC_BASE ADCA_BASE // ADCA-A2*/C9#define MTR1_VDC_ADC_BASE ADCA_BASE // ADCA-A15*/C7#define MTR1_POT_ADC_BASE ADCC_BASE // ADCC-C6*
2、ADC_NUMBER问题,如下,看不懂每一路SOC NUMBER是怎么配置的。为什么ADCA-A6* 配成ADC_SOC_NUMBER1 ,ADCA-A15*/C7却配置成 ADC_SOC_NUMBER4?
#define MTR1_VU_ADC_SOC_NUM ADC_SOC_NUMBER1 // ADCA-A6* -SOC1#define MTR1_VV_ADC_SOC_NUM ADC_SOC_NUMBER2 // ADCC-A3*/C5 -SOC2#define MTR1_VW_ADC_SOC_NUM ADC_SOC_NUMBER3 // ADCA-A2*/C9 -SOC3#define MTR1_VDC_ADC_SOC_NUM ADC_SOC_NUMBER4 // ADCA-A15*/C7 -SOC4#define MTR1_POT_ADC_SOC_NUM ADC_SOC_NUMBER4 // ADCC-C6* -SOC4
3、中断配置问题,如下,MTR1_ADC_INT_BASE为什么配置成ADCA_BASE ,和ADC采样的引脚有关吗?MTR1_ADC_INT_NUM为什么配置成NUMBER1, 和ADC采样的引脚有关吗?MTR1_ADC_INT_SOC 为什么配置成ADC_SOC_NUMBER4 ,和ADC采样的引脚有关吗?
// interrupt#define MTR1_PWM_INT_BASE MTR1_PWM_U_BASE // EPWM1
#define MTR1_ADC_INT_BASE ADCA_BASE // ADCA-A15 -SOC4#define MTR1_ADC_INT_NUM ADC_INT_NUMBER1 // ADCA_INT1-SOC4#define MTR1_ADC_INT_SOC ADC_SOC_NUMBER4 // ADCA_INT1-SOC4
4、IDC问题,如下,代码里还有IDC的配置,请问IDC是什么功能,是否必须配置?
#define MTR1_IDC1_TRIGGER_SOC ADC_TRIGGER_EPWM2_SOCA // EPWM2_SOCA#define MTR1_IDC2_TRIGGER_SOC ADC_TRIGGER_EPWM2_SOCB // EPWM2_SOCB#define MTR1_IDC3_TRIGGER_SOC ADC_TRIGGER_EPWM6_SOCA // EPWM6_SOCA#define MTR1_IDC4_TRIGGER_SOC ADC_TRIGGER_EPWM6_SOCB // EPWM6_SOCB#endif // !FAST_DCLINKSS
#define MTR1_IDC1_ADC_BASE ADCC_BASE // ADCC-A11/C0*#define MTR1_IDC2_ADC_BASE ADCC_BASE // ADCC-A11/C0*#define MTR1_IDC3_ADC_BASE ADCC_BASE // ADCC-A11/C0*#define MTR1_IDC4_ADC_BASE ADCC_BASE // ADCC-A11/C0*
#define MTR1_IDC1_ADCRES_BASE ADCCRESULT_BASE // ADCC-A11/C0*#define MTR1_IDC2_ADCRES_BASE ADCCRESULT_BASE // ADCC-A11/C0*#define MTR1_IDC3_ADCRES_BASE ADCCRESULT_BASE // ADCC-A11/C0*#define MTR1_IDC4_ADCRES_BASE ADCCRESULT_BASE // ADCC-A11/C0*
以上疑问是我根据自己的板子做了ADC配置之后,在build level1中debug, motorVars_M1.ISRCount不刷新,而用开发包原来的配置是可以刷新的。
,
Cherry Zhou:
已转达给工程师。
,
Cherry Zhou:
您好,请参阅以下答复:
您的问题大多数与 ADC 外设基本原理有关。 建议您通读 C2000 Academy chapter 4. Analog Subsystems, section 1, Analog to Digital Converter (ADC)-并非每个问题都有详细解答,但其提供了一套很好的基准知识,可解决 ADC 问题。 此外, F280013x TRM ADC chapter 一章是非常有用的资源。
liang zuxing said:1、ADC_BASE问题,如下,如果复用脚选A4是否就应该配置ADCA_BASE?如果服用脚选C14是否就应该配置ADCC_BASE?两种随意配置吗?
本质上,F280013x MCU 有2个不同的 ADC 外设- ADCA 和 ADCC。 每个外设都可以访问不同的引脚集。 要执行模数转换,您使用的 ADC 外设必须进行正确配置。
这意味着如果您想转换引脚 A6上的模拟信号,您需要使用 ADCA。 如果您要转换 C5上的模拟信号,则需要使用 ADCC。 两个 ADC 外设确实共用几个引脚(例如引脚 A7/C3),从而允许它们转换相同的输入信号,但是它们是不同的外设。
liang zuxing said:2、ADC_NUMBER问题,如下,看不懂每一路SOC NUMBER是怎么配置的。为什么ADCA-A6* 配成ADC_SOC_NUMBER1 ,ADCA-A15*/C7却配置成 ADC_SOC_NUMBER4?
C2000 Academy ADC 部分可以很好地回答您的问题。 基本上每个 ADC 可配置为进行多达16次转换。 为了便于使用,ADC 文档主要通过 SOC 启动转换来指代每次转换。 要转换引脚 A6,您需要在 ADCA 上设置1个 SOC,但您可以选择任一种。
例如,假设我要转换引脚 A6,并且我已经任意决定使用 ADCA SOC12。 现在我需要在 ADCA.ADCSOC12CTL寄存器中设置正确的配置值。 ADCSOC12CTL[CHSEL] = 0x6,因为它是 ADCA 输入6,ADCSOC12CTL[TRIGSEL]允许我可以决定该转换何时发生。
对于Universal Motor Control Lab,我们已在 hal. 文件中为您设置了所有适当的 driverlib 函数。 您所需要做的就是确保正确设置预定义即可(如 MTR1_VU_ADC_SOC_NUM)。
要将 MTR1 VU 设置为输入引脚 A6,通道 SOC12,您需要设置:
#define MTR1_VU_ADC_BASEADCA_BASE // ADCA-A6* // Pin *A*6 requires ADC*A* #define MTR1_VU_ADC_SOC_NUM ADC_SOC_NUMBER12 // ADCA-A6* -SOC12 // In our example, we're arbitrarily setting SOC12 #define MTR1_ADC_TRIGGER_SOCADC_TRIGGER_EPWM1_SOCA // EPWM1_SOCA // This configures ePWM1 SOCA as the trigger for all of motor 1's SOCs.liang zuxing said:3、中断配置问题,如下,MTR1_ADC_INT_BASE为什么配置成ADCA_BASE ,和ADC采样的引脚有关吗?MTR1_ADC_INT_NUM为什么配置成NUMBER1, 和ADC采样的引脚有关吗?MTR1_ADC_INT_SOC 为什么配置成ADC_SOC_NUMBER4 ,和ADC采样的引脚有关吗?
a. 对于 ADC,中断通常在任意选择的 SOC 完成转换时触发。 我们想要在电机1的一个 SOC 结束时触发 motor1CtrlISR ()。
–MTR1_ADC_INT_BASE 必须与我们要用于触发的 SOC 相同的 ADC (ADCA 或 ADCC)。 如上所述,SOC 与特定 ADC 相关联,这意味着我们要使用的引脚通常决定我们必须使用什么基极。 在这种情况下,我们要使用由 ADCA SOC4转换的引脚 A15,因此我们选择 MTR1_ADC_INT_base 作为 ADCA_BASE。
b. 每个 ADC 可以生成多达4个中断(ADCINT1至 ADCINT4)。 我们只需要1个,因此只选择第一个开放时隙 ADCINT1。 这意味着我们选择 MTR1_ADC_INT_NUM 为 ADC_INT_NUMBER1。
c. 我们基本上可以选择任意 SOC 来触发中断,只要确信在开始中断之前所有必要的转换都已经结束即可。 一般来说,这意味着你要将中断设置为最低优先级的 SOC -尽管需要仔细检查代码以确保正确无误,但我们可以确定这是通用实验室的功能,或者至少是非常相似的功能。 由于我们希望触发 SOC4,因此将 MTR1_ADC_INT_SOC 设置为 ADC_SOC_Number4。
liang zuxing said:4、IDC问题,如下,代码里还有IDC的配置,请问IDC是什么功能,是否必须配置?
MTR1_IDCx 是通用电机控制实验室使用的惯例,用来指用于转换单分流器硬件的通道。 您在代码中会注意到每个 IDC SOC 都指向同一引脚,但由不同的事物触发。 这只是意味着我们要在几个不同的时间点测量同一个引脚。 要了解其配置方式,请在 hal.c 文件中搜索 MOTOR1_DCLINKSS。 在这些#if defined(MOTOR1_DCLINKSS)部分中,您可以找到与单分流器硬件相关的特定配置。
如果您还有其他有关 ADC 的问题,尤其是如果问题与 ADC 相关的术语相关,我们强烈建议您通读 TRM,它可以帮助您解决很多问题。