Dear all,
I implemented voltage and current measurement on ADCINA5 and ADCINB5, respectively using simultaneous mode. The SOCA bit is generated by ePWM1 module, which is in up-count mode with 50% duty cycle. Furthermore, the SOCA bit is generated when COMPA and the time base counter (when incrementing) match. The PWM waveforms are as expected.
I also get proper ADC readings within the ADC ISR and am therefore now trying to measure the ISR execution time. For that, I set a GPIO at the beginning of the ISR, which I clear at the end of the ISR. However, my measurements show that the ISR is entered much more often than the ePWM is generated. I attached a waveform of the PWM (magenta, 50% duty with approx. 600ns dead band) and the GPIO within the ISR (blue).
I also attached my theoretical waveforms based on my understanding when reading the documents SPRU812A and SPRAAP6A.
Any ideas on what I am doing wrong? Much appreciated.
/* * 23. Nov. 2016: Open loop for now - only PWM generation - no phase shift implemented * 13. Dec. 2016: Program to flash functionality added * 16. Dec. 2016: Phase shift for open loop PWM generation added * 04. Jan. 2017: ADC measurements added - to be cont'd */ #include "DSP28x_Project.h" void InitialADC(); void InitePWM1(); void InitePWM2(); void InitePWM5(); void InitePWM6(); __interrupt void ADC_isr(); // Flash functionality extern Uint16 RamfuncsLoadStart; extern Uint16 RamfuncsLoadEnd; extern Uint16 RamfuncsRunStart; // Variables #define DT 100 // Dead time calc: DT = Value/CLKfreq -> 100/150MHz = 666ns Uint16 phaseshift; Uint16 ConversionCount; Uint16 Voltage1[128]; Uint16 Current[128]; void main(void) { // Initialize PLL, Watchdog, enable peripheral clocks InitSysCtrl(); // Used to program to flash MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); // Initialize ePWM InitEPwmGpio(); // Initialize PIE control registers InitPieCtrl(); IER = 0x0000; IFR = 0x0000; // Initialize PIE vector table to default ISR InitPieVectTable(); // Remap the ISR function to the PIE vector table EALLOW; PieVectTable.ADCINT = &ADC_isr; EDIS; // First step of setting up the ADC sampling rate EALLOW; SysCtrlRegs.HISPCP.all = 3; // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz EDIS; // Synchronization already done in the InitSysCtrl() function --> Ask the TI support to verify /* EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable time base clock synchronization with SYSCLKOUT from DSP EDIS; */ InitFlash(); PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // Group 1, bit 6 for ADC IER |= M_INT1; // Sets the interrupt enable bit of group 1 EINT; // Enable global interrupts INTM ConversionCount = 0; // Initialize the count // Initialize the ADC InitAdc(); phaseshift = 102; // Initializing the phase shift InitialADC(); InitePWM1(); InitePWM2(); InitePWM5(); InitePWM6(); /* * Set GPIO4 as output to measure execution time within ISR */ EALLOW; // Set GPIO10 as a GPIO - already done in InitGpio() GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0; // Set GPIO10 as an output GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; EDIS; for(;;) { } } __interrupt void ADC_isr(void) { GpioDataRegs.GPASET.bit.GPIO4 = 1; Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4; // Read value from ADCINA5 Current[ConversionCount] = AdcRegs.ADCRESULT1 >>4; // Read value from ADCINB5 // If 128 conversions have been logged, start over if(ConversionCount == 127) { ConversionCount = 0; } else { ConversionCount++; } /* * Calculating the phaseshift between two bridges */ EPwm5Regs.TBPHS.half.TBPHS = phaseshift; EPwm6Regs.TBPHS.half.TBPHS = phaseshift; // Re-initialize for next ADC AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clears the interrupt flag bit PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE GpioDataRegs.GPACLEAR.bit.GPIO4 = 1; } void InitialADC(void) { // Configure ADC AdcRegs.ADCTRL3.bit.ADCCLKPS = 12; // Set the ADC sampling rate: 25MHz/(2*12+1) = 1MHz AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // Cascaded mode AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Continuous conversion mode AdcRegs.ADCTRL3.bit.SMODE_SEL = 1; // Simultaneous sampling mode AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM starts SOCA trigger AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; // One conversion AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 5; // ADCINA5 and ADCINB5 AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Interrupt request enabled } void InitePWM1(void) { // Enable SOCA for ADC measurements EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOCA EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Generate SOCA pulse at 50% duty cycle EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event EPwm1Regs.TBPRD = 1499; // Set the PWM period time EPwm1Regs.CMPA.half.CMPA = (1499+1)/2; EPwm1Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm1Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Sets pin when CTR=PRD EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clears pin when CTR=COMPA EPwm1Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm1Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm1Regs.DBRED = DT; EPwm1Regs.DBFED = DT; } void InitePWM2(void) { EPwm2Regs.TBPRD = 1499; // Set the PWM period time EPwm2Regs.CMPA.half.CMPA = (1499+1)/2; EPwm2Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Master module EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm2Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clears pin when CTR=PRD EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Sets pin when CTR=COMPA EPwm2Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm2Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm2Regs.DBRED = DT; EPwm2Regs.DBFED = DT; } void InitePWM5(void) { EPwm5Regs.TBPRD = 1499; // Set the PWM period time EPwm5Regs.CMPA.half.CMPA = (1499+1)/2; EPwm5Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm5Regs.TBCTL.bit.PRDLD = TB_SHADOW; //EPwm5Regs.TBCTL.bit. EPwm5Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Sync down-stream module EPwm5Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm5Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm5Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm5Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clears pin when CTR=PRD EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // Sets pin when CTR=COMPA EPwm5Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm5Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm5Regs.DBRED = DT; EPwm5Regs.DBFED = DT; } void InitePWM6(void) { EPwm6Regs.TBPRD = 1499; // Set the PWM period time EPwm6Regs.CMPA.half.CMPA = (1499-1)/2; EPwm6Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Sync down-stream module EPwm6Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm6Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm6Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // Sets pin when CTR=PRD EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clears pin when CTR=COMPA EPwm6Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm6Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm6Regs.DBRED = DT; EPwm6Regs.DBFED = DT; }