This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

F28377s ADC trigger by ePWM2

Other Parts Discussed in Thread: CONTROLSUITE

Hello,
I have two questions regarding the ADC module of the F28377s.

I've been working with the F28335 for a while and now I want to migrate my code to the F28377s Launchpad. Basicaly what I want to do is start the ADC conversion when the zero event of ePWM2 occurs.

First question: I had a hard time figuring out what value should I define in the AdcaRegs.ADCSOC0CTL.bit.TRIGSEL register. Is there a document that describes every register of the 28377s like the SPRU812A for the 28335?
Second: After some research I'm able to trigger the ADC SOC and generate an interrupt at the end of conversion, but the value AdcaResult register never change, regardless the voltage applied at the pin. 

This is the code I'm using to configure the ADC module:

EALLOW;

// Re-map function used by ADCA interrupt 1
PieVectTable.ADCA1_INT = &ADC_A1_ISR;


EDIS;

// Enable CPU interrupts from group 1
IER |= M_INT1;

// Enable ADCA interrupt 1 in the PIE: Group 1 interrupt 1
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

EALLOW;

// Reset ADCA
DevCfgRegs.SOFTPRES13.bit.ADC_A = 1;

// Release ADCA from reset
DevCfgRegs.SOFTPRES13.bit.ADC_A = 0;

// Set ADCA clock divider - SYSCLOCKOUT /4
AdcaRegs.ADCCTL2.bit.PRESCALE = 6;

// Set ADCA mode
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);

//Set pulse positions to End of conversion
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;

// Power up the ADC
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;

// ADC power up delay
DELAY_US (1000);

// SOC0 will convert pin A0
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;

// Sample window size (75 ns)
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14;

// Trigger SOC0 on ePWM2
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x7;

// End of SOC0 will set interrupt 1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0;

// Enable ADC A interrupt 1
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;

// Clear interrupt flag for ADC A interrupt 1
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

EDIS;

Can someone please help me on this?

Thanks in advance.

  • Hi Renan,

    We now put the information that used to be in individual module user guides (ADC user guide, ePWM user guide, etc.) into a single "Technical Reference Manual" document. You can find this on the product page for F28377S as the third main link (DS is the first, errata is the second) here: www.ti.com/.../TMS320F28377S

    As far as triggering on ePWM2 Zero count, you can use either 'SOCA' or 'SOCB' trigger from ePWM2. These are triggers 0x7 and 0x8 - see page 1251 in the TRM - it looks like you have this setup already.

    I did a quick read through the code and comments and I think your understanding is good and everything looks like it is setup correctly from the ADC side. You may want to focus on the ePWM module configurations (and maybe the PIE settings if the ADCINT flag is getting set, but the interrupt is not occurring).
  • Thanks for the info on the Reference Manual, this will help a lot.
    Regarding the ePWM configuration: The interrupt is working properly. Every zero event on ePWM2 generate an interrupt. I also tested some example codes from TI and in all of them the AdcaResult doesn't change.
  • Problem solved. I changed all the settings of the ePWM to use SOCB instead of SOCA and the TRIGSEL to 0x8 and now everything works. Thanks a lot.
  • Hi.

    I'll join my question to this thread because I am fighting with similar problem right now on 377s LaunchPad.

    I'm trying to get ADC results just after EPWM interrupt occurs. So I've got working EPWM interrupt with 10kHz frequency, and now I want to start ADC at the beginnig of that interrupt.
    I'm using SOCB form EPWM2, and all registers are set correctly in "Expressions" window. But there is 0 all the time in AdcResult register.
    Any ideas?
    Thanks for help ;)

    Main function:

    void main(void)
    {
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xS_SysCtrl.c file.
        InitSysCtrl();
    
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xS_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
        InitGpio();
    
    // enable PWM2
        CpuSysRegs.PCLKCR2.bit.EPWM2 = 1;
    
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
        DINT;
    
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xS_PieCtrl.c file.
        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).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xS_DefaultIsr.c.
    // This function is found in F2837xS_PieVect.c.
        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.EPWM2_INT = &epwm2_isr;
    	EDIS;   // This is needed to disable write to EALLOW protected registers
    
    // For this example, only initialize the ePWM
    	EALLOW;
    	CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    	EDIS;
    	InitEPwm();
    	EALLOW;
    	CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    	EDIS;
    
    // Step 4. User specific code, enable interrupts:
    	InitAdc();
    
    // Enable CPU INT3 which is connected to EPWM1-3 INT:
    	IER |= M_INT3; //PWM
    
    // Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
    	PieCtrlRegs.PIEIER3.bit.INTx2 = 1; //PWM2
    
    // Enable global Interrupts and higher priority real-time debug events:
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
    // Step 5. IDLE loop. Just sit and loop forever (optional):
        while (1)
        {
        	//nothing
        }
    }

    and InitAdc()

    void InitAdc(void)
    {
    	EALLOW;
    
    	CpuSysRegs.PCLKCR13.bit.ADC_A = 1; //ADCCLK on
    	DevCfgRegs.SOFTPRES13.bit.ADC_A = 1; //Reset ADC
    	DevCfgRegs.SOFTPRES13.bit.ADC_A = 0;
    
    	AdcaRegs.ADCCTL2.bit.PRESCALE = 0;
    	AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
    	AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
    	AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    	DELAY_US(1000);
    
    	AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;
    	AdcaRegs.ADCSOC0CTL.bit.ACQPS = 3;
    	AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x8;
    
    	EDIS;
    }

    and InitEPwm():

    void InitEPwm(void)
    {
    	EALLOW;
    //-----------EPWM2 SETUP------------//
    	EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
    	EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    	EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    	EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
    	EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
    	EPwm2Regs.TBCTR = 0;
    	EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    	EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    	EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    	EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    	EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    	EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    	EPwm2Regs.DBFED = DB_FED;
    	EPwm2Regs.DBRED = DB_RED;
    	EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;
    	EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR;
    	EPwm2Regs.TBPHS.bit.TBPHS = 0;
    	EPwm2Regs.TBPRD = TBPRD_Ts;
    
    
       // Interrupt where we will change the Compare Values
       EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
       EPwm2Regs.ETSEL.bit.INTEN = 1;                // Enable INT
       EPwm2Regs.ETPS.bit.INTPRD = ET_1ST;           // Generate INT on 1st event
       // SOCA interrupt
       EPwm2Regs.ETSEL.bit.SOCBSEL = 2;	// SOCA at TBCTR=0
       EPwm2Regs.ETSEL.bit.SOCBEN = 1; //SOCA enable
       EPwm2Regs.ETPS.bit.SOCBPRD = 1; //Generate interrupt on 1st event
       EDIS;
    }

  • Hello,

    I stuck your code into a project (although, I had to make up values for DB_FED, DB_RED, and TBPRD_Ts) and it worked fine. I was able to pull up AdcaResultRegs.ADCRESULT0 in the Expressions window, turn on Continuous Refresh, and watch the value change. Granted, I was using a controlCARD instead of a LaunchPad, but I doubt that would make a difference.

    Do you read the result register somewhere in your code? Can you see the value change if you read it in the code instead of just looking at it in the Expressions or Register views?

    Thanks,

    Whitney

  • Problem is still occurring, no matter if I check AdsResult0 in Expressions window or using it in a code. I'm slowly freaking out about it. Should I change something in system configuration registers or in clocks registers, or default settings form examples in ControlSuite are fine?

  • The default controlSUITE code should be fine.

    Can you tell from the ADC registers whether or not the conversion is happening? For example, if you enable an ADC interrupt and watch the ADCINTFLG, do you see it get set?

    Whitney

  • Example code form ControlSuite called adc_soc_epwm_tempsensor_cpu01 works fine. I can see changing values in Expressions window. However adc_soc_epwm_cpu01 isn't working.

    edit:
    Now it's working. New project with the same code works fine! I had to make some mess in project properties probably.

    Thanks for help!