To whom this may concern:
Thank you so much for your time and discuss with the problem that I have. I have run into a problem when using ePWM interrupt with ADC sampling in 28335. I have attached my code in the post . As a summary, I have used only one timer counter and one interrupt in my code, all relate to epwm1 timer counter and interrupt. Due to my algorithm, I need to change the compare value of EPwm1Regs.CMPA.half.CMPA each iteration. The switching frequency for my PWM signal sent to converter-inverter is 20 KHz. As a reference, the PWM control signal itself is working, but when I combine the code with ADC sampling into the code, the ADC is not working. Please take a look at the code below:
void main(void)
{
// Step 1. Initialize System Control:
InitSysCtrl();
EALLOW;
#if (CPU_FRQ_150MHZ) // Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
#endif
EDIS;
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK;
EDIS;
// Step 2. Initalize GPIO:
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();
InitEPwm4Gpio();
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.初始化pie控制
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1_timer_isr;//
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize all the Device Peripherals:
InitAdc();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;//Disable TBCLK within the ePWM
EDIS;
InitEPwm1Example();
InitEPwm2Example();
InitEPwm3Example();
InitEPwm4Example();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;// Enable TBCLK within the ePWM//使能ePWM的TBCLK
EDIS;
// Step 5. User specific code, enable interrupts
// Initalize counters and variables:
ConversionCount = 0;
Out_VDCIntegr = 0;
Out_VDCIntegr_Q21 = 0;
IndCurErr = 0;// error for inductor current
VDCErr=0;// error for DC-link voltage
Out_VDCVolRsnt_3=0;
Out_VDCVolRsnt_1_3=0;
Out_VDCVolRsnt_2_3=0;
EPwm1TimerIntCount = 0;
// Enable CPU INT3 which is connected to EPWM1-3 INT:
IER |= M_INT3;
// IER |= M_INT1; // Enable CPU Interrupt 1
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
// Enable ADCINT1 in PIE
// PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// Configure ADC
AdcConfig();
// wait for ADC to interrpt
// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;)
{
asm(" NOP");
}
}
void AdcConfig(void)
{
EALLOW;
AdcRegs.ADCMAXCONV.all=0x0002; //ConversionCount=8dui;33:4dui
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup conv from ADCINA0 & ADCINB0
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup conv from ADCINA1 & ADCINB1
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1=1;//ePWM SOCA enable bit for SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1;//1;//SEQ1 interrupt enable.
EDIS;
}
void InitEPwm1Example()
{
EPwm1Regs.TBPRD = PWM1_TIMER_TBPRD; // Set timer period
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter
// Setup TBCLK= SYSCLKOUT / (HSPCLKDIV * CLKDIV)=150/4*4
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up AND DOWN
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT 000:/1; 001:/2; 010:/4;011:/6
//HSPCLKDIV High Speed Time-base Clock Prescale Bits
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; //TBCLK = SYSCLKOUT / (HSPCLKDIV * CLKDIV)
//CLKDIV Time-base Clock Prescale Bits
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO(保证ADC采样完整)
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE =CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO ;
// Setup compare
EPwm1Regs.CMPA.half.CMPA = 0; // struct CMPA_HRPWM_REG half;
// Set actions
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // active high
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; // Set PWM1A on Zero
EPwm1Regs.AQCTLB.bit.CAD = AQ_SET;
// Active Low PWMs - Setup Deadband
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm1Regs.DBRED = EPWM1_MAX_DB; //Initialized to be zero, will be changed in the main program
EPwm1Regs.DBFED = EPWM1_MAX_DB; //Initialized to be zero, will be changed in the main program
EPwm1_DB_Direction = DB_UP;
// Interrupt where we will change the Deadband
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
// use EPWM1A as the interrupt for ADC_soc
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // Select SOC from from CPMA on upcount
// EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; // Generate pulse on 1st event
EPwm1Regs.ETPS.bit.SOCAPRD = ET_3RD; // Generate pulse on 2nd event
}
// Interrupt routines uses in this example:
interrupt void epwm1_timer_isr(void)
{
EPwm1TimerIntCount++;
Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
ConversionCount++;
Voltage1[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
ConversionCount++;
// If 40 conversions have been logged, start over
if(ConversionCount == 1024)
{
ConversionCount = 0;
}
else ConversionCount++;
Temp1 = (int32) AdcRegs.ADCRESULT0;
//VDC = (Temp1>>12)*VDCVOLLIMIT;
VDC = (Temp1/4096)*VDCVOLLIMIT;
Temp1 = (int32) AdcRegs.ADCRESULT1;
//IndCur =(Temp1>>12)*IndCURLIMIT;
IndCur =(Temp1/4096)*IndCURLIMIT;
// Reinitialize for next ADC sequence
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit
VDCVolControl();
IndCurControl();
PWAM_Control();
if(a>b && a>c && b>c) //a>b>c
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm1Regs.CMPA.half.CMPA = 3750;
EPwm3Regs.CMPA.half.CMPA = 0;
EPwm2Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
if(a>b && a>c && c>b) //a>c>b
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm1Regs.CMPA.half.CMPA = 3750;
EPwm2Regs.CMPA.half.CMPA = 0;
EPwm3Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
if(b>a && b>c && a>c) //b>a>c
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm2Regs.CMPA.half.CMPA = 3750;
EPwm3Regs.CMPA.half.CMPA = 0;
EPwm1Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
if(b>c && b>a && c>a) //b>c>a
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm2Regs.CMPA.half.CMPA = 3750;
EPwm1Regs.CMPA.half.CMPA = 0;
EPwm3Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
if(c>b && c>a && b>a) //c>b>a
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm3Regs.CMPA.half.CMPA = 3750;
EPwm1Regs.CMPA.half.CMPA = 0;
EPwm2Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
if(c>b && c>a && a>b) //c>a>b
{
EPwm4Regs.CMPA.half.CMPA = (int)(3750*Db); //boost duty ratio
EPwm3Regs.CMPA.half.CMPA = 3750;
EPwm2Regs.CMPA.half.CMPA = 0;
EPwm1Regs.CMPA.half.CMPA = (int)(3750*Di); //inverter duty ratio,open loop
}
// Clear INT flag for this timer
EPwm1Regs.ETCLR.bit.INT = 1;
// Acknowledge this interrupt to receive more interrupts from group 3
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
Could someone help me take a look at this code and give me some hint on that.
Thank you so much,
yang