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 at 12.5 MHz not working

Hi,

I am working on the F28335 Peripheral Explorer board. I am trying to run the ADC in the continuous run mode at the maximum sampling rate of 12.5MSPS.

I think that i have programmed the ADC in the correct configuration and i do get a correct sampled input waveform at low sampling rates. The input waveform is a 40KHz sawtooth waveform.

However at  high sampling rates such as of 8.3MSPS (HSPCLK = 150MHZ, ADC_CLKPS = 3, ACQ_PS = 1)the sampled waveform looks something like this.

and for even higher rate i.e 12. 5MHZ (HSPCLK = 150MHZ, ADC_CLKPS = 3, ACQ_PS = 0) the  wave form looks like this

To view this graph in code composer studio  I am using the code from the Example_2833x AdcSeq_ovdTest.c  which basically uses the main loop to look for interrupt from the ADC after every seven conversions and then copies the data into the memory buffer. The contents of the memory buffer i then display using single time plot in the code composer studio . 

My understanding of these observations is that at the higher ADC sampling rates the CPU is unable to read the ADC registers before they are overwritten.

This implies that the F28335 can not be used with ADC running at 8.3MHz or higher smapling rates. At least not with this code. This would mean that will have to go into assembly?I read in another post on this forum that this should not be the case. 

Can anybody please help me in this regard.? 

The detailed code is given below

void main(void)
{

Uint16 i;

Uint16 array_index;

//--- CPU Initialization
InitSysCtrl(); // Initialize the CPU (FILE: SysCtrl.c)
InitGpio(); // Initialize the shared GPIO pins (FILE: Gpio.c)
InitPieCtrl(); // Initialize and enable the PIE (FILE: PieCtrl.c)
InitWatchdog(); // Initialize the Watchdog Timer (FILE: WatchDog.c)

//--- Peripheral Initialization
InitAdc(); // Initialize the ADC (FILE: Adc.c)
InitEPwm(); // Initialize the EPwm (FILE: EPwm.c)
InitECap(); // Initialize the ECap (FILE: ECap.c)

AdcRegs.ADCTRL1.bit.ACQ_PS = 1; // Sequential mode: Sample rate = 1/[(2+ACQ_PS)*ADC clock in ns]
// = 1/(3*40ns) =8.3MHz (for 150 MHz SYSCLKOUT)
// = 1/(3*80ns) =4.17MHz (for 100 MHz SYSCLKOUT)
// If Simultaneous mode enabled: Sample rate = 1/[(3+ACQ_PS)*ADC clock in ns]

AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;

AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 Cascaded mode

AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run

AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1; // Enable Sequencer override feature
AdcRegs.ADCCHSELSEQ1.all = 0x2; // Initialize all ADC channel selects to A0
AdcRegs.ADCCHSELSEQ2.all = 0x2;
AdcRegs.ADCCHSELSEQ3.all = 0x2;
AdcRegs.ADCCHSELSEQ4.all = 0x2;
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x7; //

DelayUs(5000); // Wait 5ms before using the ADC

//--- Enable global interrupts
asm(" CLRC INTM, DBGM");

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

// Enable global interrupts and realtime debug

//--- Main Loop

while(1)
{


array_index = 0;
for (i=0; i<(ADC_BUF_LEN/16); i++)
{

// Wait for int1
while (AdcRegs.ADCST.bit.INT_SEQ1== 0){}
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;

SampleTable[array_index++]= ( (AdcRegs.ADCRESULT0)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT1)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT2)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT3)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT4)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT5)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT6)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT7)>>4);

while (AdcRegs.ADCST.bit.INT_SEQ1== 0){}
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;

SampleTable[array_index++]= ( (AdcRegs.ADCRESULT8)>>4);

SampleTable[array_index++]= ( (AdcRegs.ADCRESULT9)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT10)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT11)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT12)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT13)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT14)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT15)>>4);
}

}

} //end of main()

  • I think your assessment of the situation is correct; you are probably having issues where the CPU does not read the ADC data quickly enough. 

    Your code looks ok after a first-pass read through.  Some thoughts:

    I think you may want to use the ADC mirror registers instead of the ADC result registers.  I believe these registers are 0-wait state read, whereas the result registers have some wait-states, since they are part of the peripheral frame.  These are also right aligned instead of left aligned, so no need to shift each result (I am not sure if this will save you time, since the C28x CPU architecture should be such that a move can happen in parallel with a shift).

    You may want to move the samples to the buffer using pointer arithmetic instead of array indexing.  e.g. declare

    Uint16* ptr = &SampleTable[0]; //I think Uint16* ptr = SampleTable also works

    and then

    SampleTable[array_index++] = ...

    would be replaced with

    *ptr++ = ...

    This should result in the compiler generating more efficient code.

  • Dear Devin,

    Thanks for your quick reply. I have modified my code according to your suggestions but it did not help at all. I am still getting the same error.

    There is one more information that i did not mention in my original post. The error in the sawtooth waveform at 8.3MHz sampling rate is not there in every buffer length. Sometimes i get correct waveform for several buffers and then i get a one or more buffers with the error. Its completely random

    Could you think of any reason why this error would not be present all the time. I mean if the CPU is not fast enough to read the registers before ADC-overwrite ..it should be doing it all the time ...since CPU only reads the registers after it sees the interrupt status flag. 

    I am not sure if there is variable wait time between the ADC Interrupt and the CPU recognizing the flag bit.

    Another thing is that while the CPU is reading the first 8 registers the ADC is writing to the next 8 registers. So I really cant seem to understand that how does the CPU fail to read 8 registers at 150MHZ clock and ADC is able to write more than 8 registers at 8.3MHz clock...

    I will highly appreciate if you can shed some light on this.

    Thanks

  • Hi,

    As your sampling rate is very high, you might experience this issue. When I was experimenting with various ADC sampling rates I did observe the same thing. One solution for this problem was averaging the values. 

    Regards,

    Gautam

  • Farasat,

    Do you have anything else running on the device while the ADC sampling code is taking place?  Maybe an ePWM or XINTF? Is XCLKOUT enabled? What are you using to drive the 40kHz ramp? Does it have a strong or weak drive strength?

    I am wondering if something else on the board has a switching edge that is corrupting your ADC results.  Depending on how fast you sample and how fast the other signal is, you would expect to see some difference based on how fast you sample (this might explain the difference between 12.5MSPS and 8.3MSPS). If you are synchronized with it at 8.3MSPS, then you might only see the corruption sometimes - depending on where the edge falls with respect to the sample and hold window - do you sometimes see the issue with 8.3MSPS but always see the issue at 12.5MSPS?

  • Devin,

    • Yes I have the EPWM running to generate a 2KHz digital waveform, XCLKOUT is enabled.But my understanding is that they dont affect the CPU? None of the interrupts is enabled from these sources.
    • The 40Khz ramp is a common Lab  agilent waveform generator so i dont think that it has a weak drive strength.
    • I see the issue with both sampling rates only sometimes. Its not always for either rate. Although the nature of error is different for both rates. For 8.3Msps I only see one data sample to be wrong every few samples, whereas at 12.5MSPS i see a whole range of valued that appear to be a from a previous waveform. This is evident from the two figures in the original post.
    What are your impressions on this.
    I will turn off the XCLKOUT and the EPWM and then evaluate the performance.
    Thanks for your time.
  • My concern was that these were actually affecting the analog value of the input signal (by coupling in switching noise), not the CPU.  

    However, if the ePWM is triggering an ISR to change say the ePWM duty cycle, then this could potentially cause timing issues with ADC results copying.  Subsequent runs could start with the ePWM timebase at a different position, which could explain the somewhat random nature of the error in the results.  

  • Hi,

    I know that it's probably too late, but it's better late than never.

    Actually I'm very new to working with it, but I had the same issue and I fixed it by connecting 10K resistor between the ADC pin to the measured circuit.

    It seems like in high speeds it pulls current from the circuit.

    Hope this will help you or to anyone who will encounter this too.

    Best regards!