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.

Maximizing ADC Channel's Sampling Rate



Hi,`

I ran Example_2833xAdcToDMA.c and I am only getting a sampling rate of 13.333KSPS on each of the four channels.  According to the comments, I should be getting  12.5MSPS (so a 3.125MSPS on each channel?).  I would like it to run at max speed.  Am I doing something wrong?  Below is the code I've been running, but it's pretty much the original example code.

It appears to take 4 consecutive samples at a higher sampling frequency(possibly 12.5MSPS), but it doesn't take the next 4 samples until 1/13333 secs later. So it takes four samples at rate of 13.333KSPS, i think.  I've tried changing ADC_MODCLK 

   ADC_MODCLK
   AdcRegs.ADCTRL1.bit.ACQ_PS
   AdcRegs.ADCTRL1.bit.CPS
   AdcRegs.ADCTRL3.bit.ADCCLKPS

But the program still runs at 13.333KSPS for each channel.  I don't know if its the ISR or something with calling the SOC. How do you get each channel to sample at max frequency?

//###########################################################################
//
// FILE:   Example_2833xAdcToDMA.c
//
// TITLE:  DSP2833x ADC To DMA
// ASSUMPTIONS:
//
//    This program requires the DSP2833x header files.
//
//    Make sure the CPU clock speed is properly defined in
//    DSP2833x_Examples.h before compiling this example.
//
//    Connect the signals to be converted to channel A0, A1, A2, and A3.
//
//    As supplied, this project is configured for "boot to SARAM"
//    operation.  The 2833x Boot Mode table is shown below.
//    For information on configuring the boot mode of an eZdsp,
//    please refer to the documentation included with the eZdsp,
//
//       $Boot_Table:
//
//         GPIO87   GPIO86     GPIO85   GPIO84
//          XA15     XA14       XA13     XA12
//           PU       PU         PU       PU
//        ==========================================
//            1        1          1        1    Jump to Flash
//            1        1          1        0    SCI-A boot
//            1        1          0        1    SPI-A boot
//            1        1          0        0    I2C-A boot
//            1        0          1        1    eCAN-A boot
//            1        0          1        0    McBSP-A boot
//            1        0          0        1    Jump to XINTF x16
//            1        0          0        0    Jump to XINTF x32
//            0        1          1        1    Jump to OTP
//            0        1          1        0    Parallel GPIO I/O boot
//            0        1          0        1    Parallel XINTF boot
//            0        1          0        0    Jump to SARAM        <- "boot to SARAM"
//            0        0          1        1    Branch to check boot mode
//            0        0          1        0    Boot to flash, bypass ADC cal
//            0        0          0        1    Boot to SARAM, bypass ADC cal
//            0        0          0        0    Boot to SCI-A, bypass ADC cal
//                                              Boot_Table_End$
//
//
// DESCRIPTION:
//
// ADC is setup to convert 4 channels for each SOC received, with  total of 10 SOCs.
// Each SOC initiates 4 conversions.
// DMA is set up to capture the data on each SEQ1_INT.  DMA will re-sort   
// the data by channel sequentially, i.e. all channel0 data will be together
// all channel1 data will be together.
//
// Code should stop in local_DINTCH1_ISR when complete
//
// Watch Variables:
//      DMABuf1
//
//###########################################################################
//
// Original source by: M.P.
//
// $TI Release: 2833x/2823x Header Files and Peripheral Examples V133 $
// $Release Date: June 8, 2012 $
//###########################################################################

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// 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  0x15   // 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   80    // Sample buffer size

// Global variable for this example
Uint16 j=0;

#pragma DATA_SECTION(DMABuf1,"DMARAML4");
volatile Uint16 DMABuf1[80];

volatile Uint16 *DMADest;
volatile Uint16 *DMASource;
interrupt void local_DINTCH1_ISR(void);

void main(void)
{
   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:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();  // Skipped for this example

// 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;

// 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 DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
   EALLOW;    // Allow access to EALLOW protected registers
   PieVectTable.DINTCH1= &local_DINTCH1_ISR;
   EDIS;   // Disable access to EALLOW protected registers
      
   IER = M_INT7 ;                                 //Enable INT7 (7.1 DMA Ch1)
   EnableInterrupts();
   
// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
   InitAdc();  // For this example, init the ADC

// Specific ADC setup for this example:
   AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;
   //AdcRegs.ADCTRL1.bit.CPS = 0;
   AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
   AdcRegs.ADCTRL1.bit.SEQ_CASC = 0;        // 0 Non-Cascaded Mode
   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;
   AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;
   AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;
   AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;
   AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
   AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
   AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x0;
   AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x1;
   AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x2;
   AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x3;
   AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 3;   // Set up ADC to perform 4 conversions for every SOC
   
//Step 5. User specific code, enable interrupts:
  // Initialize DMA
    DMAInitialize();

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

    
// Configure DMA Channel
    DMADest   = &DMABuf1[0];              //Point DMA destination to the beginning of the array
    DMASource = &AdcMirror.ADCRESULT0;    //Point DMA source to ADC result register base
    DMACH1AddrConfig(DMADest,DMASource);
    DMACH1BurstConfig(3,1,20);
    DMACH1TransferConfig(19,1,0);
    DMACH1WrapConfig(1,0,0,1);
    DMACH1ModeConfig(DMA_SEQ1INT,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,
                     OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);

 

 

    StartDMACH1();

   

   // Start SEQ1
   AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1;
   for(i=0;i<20;i++){
        for(j=0;j<1000;j++){}
        AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;    //Normally ADC will be tied to ePWM, or timed routine
   }                                         //For this example will re-start manually                   

}

// INT7.1
interrupt void local_DINTCH1_ISR(void)     // DMA Channel 1
{
 
  // To receive more interrupts from this PIE group, acknowledge this interrupt
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;

  // Next two lines for debug only to halt the processor here
  // Remove after inserting ISR Code
 //  asm ("      ESTOP0");
  // for(;;);
}


  • Hi Angelo,

    The above code seems to be fine. Please check the adc initialization file and update.

    Regards,

    Gautam

  • Hey Angelo,

    You are correct that it is possible to achieve 3.125 MSPS x 4 = 12.5MSPS total sampling rate.  The code you have won't sample nearly this fast; it has a delay loop of 1000 iterations between each time it triggers the sequencer.  Since the 4 sample will only take about 50 cycles to complete, there is significant idle time.  

    In order to get the maximum sampling rate, you want to keep the converter constantly busy so that it never has idle time. Based on some code I have, you will want to do something like:

    Set the sequencer in cascaded mode. Setup CHSEL for CONV0 to CONV3 to your 4 channels, but also setup CONV4 to CONV7, CONV8 to CONV11, and CONV12 to CONV15 to the same 4 channels.  Set MAX_CONV to 7 (8 samples per trigger). Set the SEQ_OVRD bit to 1.

    Then to collect data:

    while(need more data){

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

        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;

        move first 8 results to buffer

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

        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;

        move second 8 results to buffer

    }

    You may be able to find some full speed sampling code on the forum or in TI collateral.  If you can't find any and the above description above is not enough to get things working for you, I can try and cleanup and release the code I have (but this will take some time as this is old code that I didn't write and which wasn't intended for external release).  

  • Look at the line "#define ADC_SHCLK  0x15   // S/H width in ADC module periods                        = 16 ADC clocks"

    so, do you really want  21 or only 16 clocks?