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.

F28335 ADC sampling delay



hi all,

 

I am using a PWM to trigger my ADC ISR, when I toggle an output in the ADC ISR, The delay between each sampling is 400Khz. I need 800Khz at least.

has anyone an idea of what I am doing wrong to be so slow ???.

 

Thanks a million for your support,

 

greg.

 

 

void InitCan(void)
{
    // Specific clock setting
    SysCtrlRegs.HISPCP.all = ADC_MODCLK;    // HSPCLK = SYSCLKOUT/2*ADC_MODCLK
 
     // init the ADC, calibration
    InitAdc();

    // ADC SETUP

    //sequential sampling mode
    AdcRegs.ADCTRL3.bit.SMODE_SEL   = 0x0;

    AdcRegs.ADCMAXCONV.all             = 0x0000;
    // Set up ADC to perform 1ere conversions on A0
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;

    // selection reference exterieure 2.048V
    AdcRegs.ADCREFSEL.bit.REF_SEL = 0x1;

    //enable ISR to CPU
    AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0x0;
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;

    AdcRegs.ADCTRL1.bit.ACQ_PS   = ADC_SHCLK;
    //ADC operates as a 16-state sequencer
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 0x1;
    AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;

    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;
}

 

interrupt void  adc_isr(void)
{

    GpioDataRegs.GPASET.bit.GPIO2 = 1;
    g_AdcMesure.uiVoieMes[g_iCptMes]    = AdcRegs.ADCRESULT0   >>4;
    // Reinitialize for next ADC sequence
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit

   // Acknowledge interrupt to PIE
    PieCtrlRegs.PIEACK.bit.ACK6 = 1;

    GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;

}

 

 

void InitEPwm(void)
{
   // Initialize ePWM2

//---------------------------------------------------------------------
//--- Must disable the clock to the ePWM modules if you      
//--- want all ePMW modules synchronized.
//---------------------------------------------------------------------
    asm(" EALLOW");                        // Enable EALLOW protected register access
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    asm(" EDIS");                        // Disable EALLOW protected register access


//---------------------------------------------------------------------
//--- Configure ePWM2 to trigger the ADC at 800 kHz rate
//---------------------------------------------------------------------
    EPwm2Regs.TBCTL.bit.CTRMODE = 0x3;        // Disable the timer

    EPwm2Regs.TBCTL.all = 0xC033;            // Configure timer control register
// bit 15-14     11:     FREE/SOFT, 11 = ignore emulation suspend
// bit 13        0:      PHSDIR, 0 = count down after sync event
// bit 12-10     000:    CLKDIV, 000 => TBCLK = HSPCLK/1
// bit 9-7       000:    HSPCLKDIV, 000 => HSPCLK = SYSCLKOUT/1
// bit 6         0:      SWFSYNC, 0 = no software sync produced
// bit 5-4       11:     SYNCOSEL, 11 = sync-out disabled
// bit 3         0:      PRDLD, 0 = reload PRD on counter=0
// bit 2         0:      PHSEN, 0 = phase control disabled
// bit 1-0       11:     CTRMODE, 11 = timer stopped (disabled)

    EPwm2Regs.TBCTR = 0x0000;                // Clear timer counter
    EPwm2Regs.TBPRD = ADC_SAMPLE_PERIOD;    // // 187 = (187.5-1) = 150 MHz SYSCLKOUT / 800 KHz sampling
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000;    // Set timer phase

    EPwm2Regs.ETPS.all = 0x0100;            // Configure SOCA
// bit 15-14     00:     EPWMxSOCB, read-only
// bit 13-12     00:     SOCBPRD, don't care
// bit 11-10     00:     EPWMxSOCA, read-only
// bit 9-8       01:     SOCAPRD, 01 = generate SOCA on first event
// bit 7-4       0000:   reserved
// bit 3-2       00:     INTCNT, don't care
// bit 1-0       00:     INTPRD, don't care

    EPwm2Regs.ETSEL.all = 0x0A00;            // Enable SOCA to ADC
// bit 15        0:      SOCBEN, 0 = disable SOCB
// bit 14-12     000:    SOCBSEL, don't care
// bit 11        1:      SOCAEN, 1 = enable SOCA
// bit 10-8      010:    SOCASEL, 010 = SOCA on PRD event
// bit 7-4       0000:   reserved
// bit 3         0:      INTEN, 0 = disable interrupt
// bit 2-0       000:    INTSEL, don't care

    EPwm2Regs.TBCTL.bit.CTRMODE = 0x0;        // Enable the timer in count up mode


//---------------------------------------------------------------------
//--- Enable the clocks to the ePWM module.                  
//--- Note: this should be done after all ePWM modules are configured
//--- to ensure synchronization between the ePWM modules.
//---------------------------------------------------------------------
    asm(" EALLOW");                            // Enable EALLOW protected register access
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;    // HSPCLK to ePWM modules enabled
    asm(" EDIS");                            // Disable EALLOW protected register access
 
}

  • Hi!

    Your timer causes an interrupt every 188 clock cycles. Hence, your ADC interrupt service routine must be (a lot) faster than that. If it is not, you will miss interrupts. You use gpio2 as monitor for your isr runtime. How long does it take?

    Best regards,
    Edwin Krasser

  • hi !!!

     

     

    the period is 6.24µsec, the duty cycle almost 50%. 

     

    best regards,

     

     

    greg.

  • Hi!

    This means that you are approximately 3 us in your interrupt service routine? Hence you cannot get every interrupt because you are still in the isr when the next interrupt request occurs.

    Best regards,
    Edwin Krasser

  • Hi !,

     

    does it mean I can reach a sampling rate of 1/3µsec ?. I can not figure out what the DSP is doing during the other 3µsec ?.

    Anyway, I want to achieved a 800Khz sampling rate, is it possible with the F28335 and how ?. I have lowered the set-up and hold to its minimum, my ADC freq is 25Mhz so can I reach the 12.5MSPS rate ?.

  • Hi!

    Well, the ADC is able to achieve 12.5 MSPS. But how do you want to process this data? At 12.5 MSPS you have got 12 clock cycles per sample. Hence you cannot work with interrupts, you have to start a free running adc at maximum sampling rate and a synchronous data acquisition loop with exactly 12 clock cycles storing the conversion results into a buffer. But in this time, your processor cannot handle anything else. And after storing all the data you can process it.

    At 1 MSPS you will have 150 clock cycles per sample. This might be enough for calling the isr and store the data (and perhaps some very simple processing). But: How many cycles does your processing function need? Do you have any other interrupts in your system?

    Best regards,
    Edwin Krasser

  • Hi !!!,

     

    In my application I can acquire all the 8192 samples and then handle them. So The solution would be:

     

    1/ start a free running ADC @ 1MSPS

    2/ acquire and store data in SRAM 8192 times

    3/ stop ADC and process data

     

    Am I correct ?. How do you garantee that the storing of conversion match exactly the sampling time ?

     

    Best regards,

     

    greg Wauters.

     

  • Hi!

    If you just need 1 MHz sampling rate, you can try the interrupt concept. But keep your isr short. And if you want to use a synchronous loop it's the best to write a short assembler function which disables interrupts, starts the adc and does the data acquisition loop 8192 times. Of course, your loop will be much too fast. Just insert some NOPs (rpt #n || nop ... n+1 NOPs).

    Best regards and good luck,
    Edwin Krasser

  • Hi edwin,

     

    just to thank you for the time you spend on my issue, It works grand now. One big timing improvement was to run my code from RAM.

     

    best regards,

     

    greg.

  • Hello,

    I am having some problems with an application that is similar to the one described in this thread.

    I want to:

    1) Sample 1000 ADC values on A0 with 12.5MSPS and store the values in an array

    2) Analyze the values

    3) Send result by SCI to PC

    4) Repeat

    So the main difference to the problem described in this thread is that I need 12.5MSPS. Based on the example Example_2833xAdcSeq_ovdTest I have written a program that does step 1-4. However my sampling frequency is just about 1MSPS, how do i setup my ADC to sample at 12.5MSPS?

    Here is an extract of my code:

    // ADC start parameters
    #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
    #define ADC_CKPS 0x1 // ADC module clock = HSPCLK/2*ADC_CKPS = 25.0MHz/(1*2) = 12.5MHz
    #define ADC_SHCLK 0xf // S/H width in ADC module periods = 16 ADC clocks
    #define AVG 1000 // Average sample limit
    #define ZOFFSET 0x00 // Average Zero offset
    #define BUF_SIZE 2048 // Sample buffer size

    //declare global vars and functions

    main()
    {
    Uint16 i;

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
    InitSysCtrl();

    // Specific clock setting for this example:
    EALLOW;
    SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
    EDIS;

    // Step 2. Initialize GPIO:
    // For this example, only init the pins for the SCI-A port.
    // This function is found in the DSP2833x_Sci.c file.
    InitSciaGpio();

    // 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 DSP2833x_PieCtrl.c file.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    // Output on GPIO34
    EALLOW;
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // GPIO
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // output
    EDIS;

    // For this example, init the ADC
    InitAdc();

    // Specific ADC setup for this example:
    AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;
    AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 Cascaded mode
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;
    AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run


    // Step 5. User specific code, enable interrupts:

    scia_fifo_init(); // Initialize the SCI FIFO
    scia_echoback_init(); // Initalize SCI for echoback


    // Clear SampleTable
    for (i=0; i<BUF_SIZE; i++)
    {
    SampleTable[i] = 0;
    }

    // Start SEQ1
    AdcRegs.ADCTRL2.all = 0x2000;

    // Take ADC data and log the in SampleTable array
    for(;;)
    {
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34 is high

    //sample and put values in SampleTable
    for (i=0; i<AVG; i++)
    {

    while (AdcRegs.ADCST.bit.INT_SEQ1== 0) {} // Wait for interrupt
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
    SampleTable[i] =((AdcRegs.ADCRESULT0>>4) );
    }
    // print contents of SampleTable on SCI
    for(i = 0; i < AVG; i++)
    {

    if(i%10 == 0)
    scia_msg("\r\n");
    else
    scia_msg(" ; ");
    printNum(SampleTable[i]);
    }
    scia_msg("\r\n...done!\r\n");

    GpioDataRegs.GPBCLEAR.all = 0x4; // GPIO34 is low

    //wait until next cycle
    pause(100);
    }
    }

    //define functions

  • Hi!

    You have got a sample time of 16 clock cycles. Not okay, you need to sample as fast as possible. Now you just can achieve 25 MHz / 16 samples per second, even if the adc was infinitely fast.

    Best regards and good luck,

    Edwin Krasser

  • Hi Edwin,

    Thanks for your fast reply!

    I've changed

    #define ADC_SHCLK  0xf   // S/H width in ADC module periods                        = 16 ADC clocks

    to

    #define ADC_SHCLK  0x0

    and it works much better now! However, I still only get around 5MSPS :( Could it be that I loose half my sampling rate when I write the ADC value to the SamplingTable array in:

    //sample and put values in SampleTable
    for (i=0; i<AVG; i++)
    {
    while (AdcRegs.ADCST.bit.INT_SEQ1== 0) {} // Wait for interrupt
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
    SampleTable[i] =((AdcRegs.ADCRESULT0>>4) );
    }

    Or is it some register that I have set to the wrong value?

    Thanks!

  • Hi!

    I think your loop is not fast enough. Just think about the cpu clock frequency. At 12.5 MHz sampling rate you just have 12 ticks for storing the adc results. For high speed adc sampling I suggest to write a free running loop that stores the adc results into an array. Write it in assembler and be sure every loop cycle takes exactly 12 ticks (insert nops ifyou need). Something like that:

      AVG -> ar0
      SampleTable -> xarn
    loop:
      adcresult -> acc
      acc -> *xarn++
      nop ; some nops to get exactly 12 ticks per loop
    banz loop,ar0--

    Best regards and good luck
    Edwin Krasser

  • Thanks a lot Edwin, I havent worked with assembler before but I guess this is a good opportunity to learn. I'll try to write the sampling loop in assembler as you suggest.

    Best wishes!