ADC operating above max speed?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC operating above max speed?

Jump to solution
1,583 Views
trichert
Contributor I

Using a timer, I measured my sample rate of my ADC at ~3Msps.

I am using a k60f120 board, which according to k60P144M120SF3, has a max ADC sampling rate of only ~800ksps.

Is it plausible that my ADC is reading that much faster than the rated speed, or am I doing something wrong?

I set my ADC to sample continuously and trigger DMA with the DMAEN flag.  I am sampling with 12 bit resolution.  The DMA just reads the ADC1_RA and writes to a buffer.

To time, I am using the MQX _time_get_ticks and _time_diff_microseconds by triggering a DMA major loop interrupt after 256 samples.  I measure 85 microseconds for 256 samples ~= 3Msps.  I am running in debug mode, not release mode, but I am not setting breakpoints.

Labels (1)
0 Kudos
Reply
1 Solution
1,312 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

The fADCK must below 18Mhz for your 12bit ADC.

I think you can use the ADIV in ADCx_CFG1 to divide down your fADCK.

6 ADCK clock cycles is the subsequent sample time of your 12bit ADC, the total conversion time for all configurations is summarized in the equation below.(For more information you can refer the "37.4.5.5 Sample time and total conversion time" of K60P144M150SF3RM)

ConversionTime=SFCAdder+AverageNum*(BCT+LSTAdder+HSCAdder)

View solution in original post

0 Kudos
Reply
4 Replies
1,312 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Richert

I think the ADC conversion rate in k60P144M120SF3 is right, for 12-bit ADC the max conversion time is about 800ksps.

This can be calculated by using the equation in "37.4.5.5 Sample time and total conversion time" of K60P144M150SF3RM.

Also you can use ADC calculator tool to evaluate the ADC conversion rate of different configuration.

Each time the ADC sampling, you can observed voltage disturbances (voltage drops/peaks) at the ADC input.  AN4373(Cookbook for SAR ADC Measurements)

You can get the waveforms obtained by oscilloscope like below:

By measure the time between each sampling , you can get the real conversion rate.

ADC conversion time.bmp

1,312 Views
trichert
Contributor I

Thanks for pointing me to the sample time subsection.

I now suspect that I am operating at too high of a clock frequency.  The default bus clock frequency is the system clock (50Mhz.).  The max allowable clock frequency is 18Mhz.  I think I have the ADC configured to take 6 ADCK clock cycles.  The DMA requires 11 to read, I think.  50/17 ~= 3Mhz.

I guess if the clock is too fast, the ADC still works, but loses precision?

0 Kudos
Reply
1,313 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

The fADCK must below 18Mhz for your 12bit ADC.

I think you can use the ADIV in ADCx_CFG1 to divide down your fADCK.

6 ADCK clock cycles is the subsequent sample time of your 12bit ADC, the total conversion time for all configurations is summarized in the equation below.(For more information you can refer the "37.4.5.5 Sample time and total conversion time" of K60P144M150SF3RM)

ConversionTime=SFCAdder+AverageNum*(BCT+LSTAdder+HSCAdder)

0 Kudos
Reply
1,312 Views
trichert
Contributor I

My code:

     #define MEMORY_BUFFER_SIZE 256

     #define MEM_BUF_T uint16_t

     MQX_TICK_STRUCT tick_last;

     unsigned int counter = 0;

     uint32_t timer[20];

     dma_ch0_isr(void *ptr){

     bool overflow;

     MQX_TICK_STRUCT tick_temp;

     DMA_CINT = DMA_CINT_CINT(0);//clear interrupt flag

     if(counter < 20){//should use semophore

          _time_get_ticks(&time_temp);

          timer[counter++] = _time_diff_microseconds(&tick_temp);

          tick_last = tick_temp;

     }

}

void MAIN_task(uint32_t initial_data){

MEM_BUF_T dma_dst[MEMORY_BUFFER_SIZE] = {0};

unsigned int index;

_time_get_ticks(&tick_last);

//enable clocks

SIM_SCGC6 |= SIM_SCGC6_DMAMUX0_MASK;

SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK;

_int_install_isr(16, dma_ch0_isr, NULL);

_bsp_int_init(16, 3, 0, TRUE);

ADC_SC2 = ADC_SC2_DMAEN_MASK;//DMA interrupt

ADC1_SC3 = ADC1_SC3_ADC0_MASK;//continuous

ADC1_CFG1 = ADC_CFG1_MODE(1);//12 bit

DMAMUX0_CHCFG0 = 0;//disable hardware DMA request while config

DMAMUX1_CHCFG0 = 0;

DMA_TCD0_SADDR = &ADC1_RA;//read from ADC

DMA_TCD0_SOFF = 0;

DMA_TCD0_SLAST = 0;

DMA_TCD0_DADDR = &dma_dst[0];//write to buffer

DMA_TCD0_DOFF = sizeof(MEM_BUF_T);//destination increment

DMA_TCD0_DLASTSGA = -sizeof(MEM_BUF_T) * MEMORY_BUFFER_SIZE;//reset addr

DMA_TCD0_NBYTES_MLNO = sizeof(MEM_BUF_T);//minor loop 2 bytes

DMA_TCD0_BITER_ELINKNO = MEMORY_BUFFER_SIZE;//256 iterations

DMA_TCD0_CITER_ELINKNO = MEMORY_BUFFER_SIZE;

DMA_TCD0_ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1);//2 bytes transfer size

DMA_TCD0_CSR = DMA_CSR_INTMAJOR_MASK;//interrupt after major loop

DMA_ERQ |= DMA_ERQ_ERQ0_MASK;//allow ADC to trigger DMA

//ADC1 triggers DMA

DMAMUX0_CHCFG0 = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(41);

ADC1_SC1A = ADC_SC1_ADCH(20);//start reading ADC1 potentiometer

while(counter < 20){}

for(index = 1; index < 20; index++){printf(%4d: %6d\n\r", index, timer[index]);}

_mqx_exit(0);

0 Kudos
Reply