Part Number: TMS320F280025C
Hi,
I have a question regarding the ADC, in my project I use 3 ePWMs for semi conductor control, and I synchronize the ADC to one ePWM channel for state machine issues. So I have defined several SOCs that correspond to each input of the ADC, these are chained but I would like to get several samples on a period of cutting of the other ePWM. I tried to configure the TBPRD register differently from the other ePWMs but it doesn't work. In this case I don't enter an interrupt. Knowing that I have configured the interrupt on the end of conversion.
Currently the sampling works but not at the desired frequency I wish to have more points on a switch period
Why it does not work if I put a higher frequency on the ePWM channel used for the ADC synchronization?
Thanks
/**ePWM initialization with phase shift*/
void epwm_init(uint32_t base, uint16_t phi)
{
/**Parameters*/
EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
EPWM_setTimeBasePeriod(base, EPWM_TBPRD);
EPWM_setTimeBaseCounter(base, 0U);
EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_4, EPWM_HSCLOCK_DIVIDER_4);
/**Set up shadowing*/
EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
/**Set actions
For boost assembly*/
EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
/**For buck assembly*/
EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierContSWForceAction(SPWM_U, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);
EPWM_setActionQualifierContSWForceAction(SPWM_V, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);
EPWM_setActionQualifierContSWForceAction(SPWM_W, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);
EPWM_setActionQualifierContSWForceAction(SPWM_U, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
EPWM_setActionQualifierContSWForceAction(SPWM_V, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
EPWM_setActionQualifierContSWForceAction(SPWM_W, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
if(base == SPWM_FOR_ADC)
{
-> EPWM_setTimeBasePeriod(base, EPWM_TBPRD);
/**Initialize PWM to add samples ADC in loop close regulation*/
EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, CMPA_EPWM_ADC);
}
/**Configure ePMWs*/
// Todo comments to explain
if(phi == 0)
{
EPWM_disablePhaseShiftLoad(base);
EPWM_setPhaseShift(base, phi);
EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
}
else
{
uint16_t tbphs = epwm_get_tbphs_from_phi(base, phi);
EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
EPWM_enablePhaseShiftLoad(base);
EPWM_selectPeriodLoadEvent(base, EPWM_SHADOW_LOAD_MODE_SYNC);
EPWM_setPhaseShift(base, tbphs);
EPWM_setTimeBaseCounter(base, tbphs);
}
}
ADC configuration
/**
* Configure ADC set pulse at End Of Conversion to enter on interrupt when ADC register is full
*/
void adc_config(uint32_t adc_base)
{
/**
* Enable ADC with external reference A4 (3V)
*/
ADC_setVREF(adc_base, ADC_REFERENCE_EXTERNAL, ADC_REFERENCE_3_3V);
ADC_setPrescaler(adc_base, ADC_CLK_DIV_1_0);
/**
* Set pulse ADCINTx at the end of conversion
*/
ADC_setInterruptPulseMode(adc_base, ADC_PULSE_END_OF_CONV);
if(adc_base == ADCA_BASE)
{
/**
* Configure the SOC to occur on the first up-count event
*/
EPWM_setADCTriggerSource(SPWM_FOR_ADC, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
/**
* Sets the SOC event count that determines the number of events that have to occur before an SOC is issued.
*/
EPWM_setADCTriggerEventPrescale(SPWM_FOR_ADC, EPWM_SOC_A, PRESCALE_COUNT_ADC_SOC);
EPWM_enableADCTrigger(SPWM_FOR_ADC, EPWM_SOC_A);
}
ADC_enableConverter(adc_base);
/**
* Delay to allow ADC time to power up
*/
DEVICE_DELAY_US(ADC_DELAY_POWERUP_US);
}
/**
* Corresponding module ADCx -> SOC -> pin.
* Enchainement des SOC une fois la conversion terminée sur un SOC. SOC0 will start at 1 / PWM_FREQ and an another SOC0 at 1 / PWM_FREQ after.
* See notes for ADC_ACQPS_WINDOW details.
* Two conversions per SOC : the first on ADCA and the other on ADCC.
*/
void adc_init_soc(void)
{
/**MU_TRAC_BATT_FLT with pin ADCINA3*/
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN3, ADC_ACQPS_WINDOW);
/**MU_FUEL_CELL_FLT with pin ADCINA2*/
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN2, ADC_ACQPS_WINDOW);
/**MI_TRAC_BATT_FLT with pin ADCINA14*/
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN14, ADC_ACQPS_WINDOW);
/**MU_FUEL_CELL_PCH_FLT with pin ADCINA0*/
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER3, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN0, ADC_ACQPS_WINDOW);
/**MU_TRAC_BATT_PCH_FLT with pin ADCINC6*/
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN6, ADC_ACQPS_WINDOW);
/**MT_COLD_PLATE_FLT with pin ADCINC0*/
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN0, ADC_ACQPS_WINDOW);
/**MI_L_U_FLT with pin ADCINC14*/
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN14, ADC_ACQPS_WINDOW);
/**MI_L_V_FLT with pin ADCINC8*/
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER3, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN8, ADC_ACQPS_WINDOW);
/**MI_L_W_FLT with pin ADCINC10*/
ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER4, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN10, ADC_ACQPS_WINDOW);
/**Corresponding EOC to ADCINTX pulse to enter on interrupt for read ADCRESULTx registers. Refer to ADCINTSEL1N2 and ADCRESULTx registers.*/
ADC_setInterruptSource(ADCC_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER4);
ADC_enableInterrupt(ADCC_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);
}
/**Enter on interrupt when SOC4 on ADCC will end. Only average samples in interrupt and not conversion to have more time available.
See requirement REQ_SYST0006*/
__interrupt void isr_adc(void)
{
//
// Save IER register on stack
//
//volatile uint16_t tempPIEIER = HWREGH(PIECTRL_BASE + PIE_O_IER1);
//
// Set the global and group priority to allow CPU interrupts
// with higher priority
//
/*IER |= M_INT1;
IER &= MINT1;
HWREGH(PIECTRL_BASE + PIE_O_IER1) &= MG1_3;
//
// Enable Interrupts
//
Interrupt_clearACKGroup(0xFFFFU);
__asm(" NOP");
EINT;*/
/**Read samples results in ADCARESULT registers and stock them.*/
MU_TRAC_BATT_PCH_FLT_SAMPLE = ADC_readResult(ADCCRESULT_BASE, ADC_SOC_NUMBER0);
MT_COLD_PLATE_FLT_SAMPLE = ADC_readResult(ADCCRESULT_BASE, ADC_SOC_NUMBER1);
MI_L_U_FLT_SAMPLE = ADC_readResult(ADCCRESULT_BASE, ADC_SOC_NUMBER2);
MI_L_V_FLT_SAMPLE = ADC_readResult(ADCCRESULT_BASE, ADC_SOC_NUMBER3);
MI_L_W_FLT_SAMPLE = ADC_readResult(ADCCRESULT_BASE, ADC_SOC_NUMBER4);
MU_TRAC_BATT_FLT_SAMPLE = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
MU_FUEL_CELL_FLT_SAMPLE = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER1);
MI_TRAC_BATT_FLT_SAMPLE = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER2);
MU_FUEL_CELL_PCH_FLT_SAMPLE = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER3);
average();
/**Clear the interrupt flag*/
ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);
/**Check if overflow has occurred*/
if(ADC_getInterruptOverflowStatus(ADCC_BASE, ADC_INT_NUMBER1) == true)
{
ADC_clearInterruptOverflowStatus(ADCC_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);
}
/**Acknowledge the interrupt, see PIE Interrupt Vectors table*/
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
//
// Disable interrupts and restore registers saved:
//
/*DINT;
HWREGH(PIECTRL_BASE + PIE_O_IER1) = tempPIEIER;*/
}