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.

difference in ADC between 28035 and 28335

Other Parts Discussed in Thread: CONTROLSUITE

Hi, everyone~

I am currently working on the ADC of 28335. Got some sample example on 28035, but it seems that the program to define ADC is different in 28035 and 28335. Can anyone give me some hint on this problem and told me the difference between these two?

Thank you so much,

yang 

  • Hi Yang,

    Yes, these ADCs have different architectures and some significant differences in the digital wrappers.  You can get a pretty good idea of the difference from this migration guide in the peripherals section:

    http://www.ti.com/lit/an/sprab40b/sprab40b.pdf

  • Hi Devin:

    Thank you so much for the information, I will look through this document and get the idea from that. In the same while, do we have any example program that can run for 28335 which have the functionality of using EPWM to trigger and interrupt ADC_SOC. And in the same while, I ma working on a closed-loop control for DC-DC converter. I am wondering can I use same ePWM signal to interrupt ADC as well as using it as the gate signal for my DC-DC converter?

    Thank you so much for the information and previous time.

    all best,

    yang 

  • Yang,

    If you haven't already, download ControlSUITE, which has a variety of example programs.  To get the ePWM to trigger the ADC, I think the example in

    ...\TI\controlSUITE\device_support\f2833x\vXXX\DSP2833x_examples_ccsv4\adc_soc

    is what you are looking for.

    You should be able to do with the ePWM what you describe.  Inside ControlSUITE, you can also check out some of the application examples in 

    ...\TI\controlSUITE\development_kits

    This includes the code to go along with our development kits, which include a variety of power conversion systems ( you can check them out here: http://www.ti.com/lsds/ti/microcontroller/32-bit_c2000/tools.page).  Even if you don't want to buy the actual application kit, all the schematics, layout, and code are available.  It may be helpful to pick the kit closest to the DC-DC you want to do and use the code/schematics as a base for your application.   

  • Dear Devin:

    Thank you so much for your information and I have tested with my experimental kit these days.

    I have downloaded the controlsuite from our TI website and I am right now building my system with the F28335 which comes with the docking station and peripheral kit. I have written the open loop program for my system and it is working fine, when I tested with the ADC program itself, it also works well. Now I am building them together and writing my own code for the closed loop control of my DC-DC converter. I used the scope the show the signal I sent to each ADC pin and it seems right, but when I read it from the code, it shows some random value which I have no idea what is wrong with my code. The question I may have is:

    1. Instead of using ADC interrupt (interrupt void  adc_isr(void)), can I combine the interrupt of ADC with my ePWM interrupt? Which I am using only one interrupt for both ADC sampling and sending gate signal for my converter?

    2. Do we have any standard code with the ADC initialization and ePWM interrupt? I have saw quite some different code from website, but after I tried them, since all of them give me some weird signal, although I hook the scope to check the signal I sent to the pin is correct. 

    3. I am not sure if I post out my code with the ADC initialization and interrupt, can you help me troubleshoot the program, I have been stucked here for quite some time.

    Thank you so much for your time and all my best wishes,

     

  • It should be possible to create one ISR to take the ADC results and then update ePWM output settings.  One thing you should have to be concerned about is when the ADC results will be valid.

    If you have ePWM trigger the ADC start of conversion and the ePWM interrupt at the same time, you may need to count cycles in the ISR and wait until the ADC results are ready.

    If you trigger the ADC from one ePWM compare event, then a later event triggers the ISR, just make sure there is enough time for the ADC to complete.

    Is there a specific thing that doesn't work about it?

  • Dear Devin:

    Thank you so much for your response. I will try and make sure the thing you mentioned have been taken care in my code. I will revised the code and post it later on, then maybe you can help me figure out what is the problem with it. The code is kind of long since I am doing some algorithm there, I will pick up the part that relates to my ADC conversion and PWM output.

    I will keep you updated and thank you so much for your kind help.

    have  a nice weekend.

    all best,

    yang 

  • Dear Devin:

    Thank you so much for your continuous attention and discuss with the problem that I have. I have attached my code in the post and I have examined the part that you remind me to take a look at, but the problem is still there, I hope you can look at my code and help me troubleshoot the problem. 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 and 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, it is working any more. 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;

    }

     

  • A quick look at the code doesn't reveal anything obviously wrong. 

    Perhaps it would be helpful to diagram out the PWM1 cycle to show where you want the ADC to be triggered and where you want the PWM interrupt to occur.  Then setup some GPIO to clearly delineate the PWM cycle, when the EPWM ISR is entered and exited, and also you could enable the ADC interrupt and also toggle a GPIO when the ADC ISR is entered/exited.  You could then view on a scope and compare with expectations?