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.

TM4C123GE6PM: ADC sampling time delay according to variable type

Part Number: TM4C123GE6PM

Hi, This is namha. 

I found a strange phenomenon in calculating the ADC sampling time.

The ADC result values are stored in variables. The total sampling time depends on the type of the variable.

2048 ADC data are received using two ADC modules with two variables.

I set the sampling frequency to 450kHz.

I measured the time when I completed the for loop.

However, when the type of the FFT_Buffer array is declared as uint16_t or uint32_t, the for loop's operation time is 4520us, and when it is declared as float32_t, the operation time is 5560us.

(In other words, float32_t type takes 250ns more than uint16_t or uint32_t type to store in one variable.)

1. Does the time to store the ADC value in the variable depend on the type of variables? If so, why?

2. what is the error rate of the sampling frequency of the ADC module?

My source is below.

******************************************************* MAIN*************************************************************

int main(void)
{
uint32_t ADCCurrentIndex = 0;

ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_24MHZ); // Set the clocking to run from the PLL
ROM_FPUEnable();
ROM_FPULazyStackingEnable();

GPIO_initGeneral(); // Enable the GPIO pins for the LED (PF2 & PF3).
GPIO_NMIdisable();
g_bUSBConfigured = false; // Not configured initially.
SystemTick_enable(); // Enable the system tick.

SPIInit();
I2CInit();
ADCInit();
AFEInit();
PLLInit();
//USBBulk_init();
SetPllFreq(2); //2Mhz
delay_ms(1000); // AEF Setup wait
GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0); // PortB pin0 '0'초기화
ADCEnable();

while(1)
{
      // Progress time of for loop??? 
      GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0); // GPIO period test, low
      for(ADCCurrentIndex=0; ADCCurrentIndex < 2048; ADCCurrentIndex++)
      {
           ROM_ADCIntClear(ADC0_BASE, 3);
           ROM_ADCIntClear(ADC1_BASE, 3);
           while(!ROM_ADCIntStatus(ADC0_BASE, 3, 0));
           while(!ROM_ADCIntStatus(ADC1_BASE, 3, 0));
           FFT_Buffer[2*ADCCurrentIndex + 0] = HWREG(ADC0_BASE + ADC_O_SSFIFO3); //
           FFT_Buffer[2*ADCCurrentIndex + 1] = HWREG(ADC1_BASE + ADC_O_SSFIFO3);
      }
     ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0); // GPIO period test, low

     //AFEChannelSelect(0);
     //DoFFT(FFT_POINTS, 0);
     //delay_ms(1);
}
}

**************************************************** ADCInit() ********************************************************

void ADCInit()
{
uint32_t samplePeriod = 0;
//Initialize ADC
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); //ADC peripheral
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

//Pins used for ADC channels
ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
ROM_ADCSequenceConfigure(ADC0_BASE, ADC_SEQUENCE_NUMBER, ADC_TRIGGER_TIMER, 0);
ROM_ADCSequenceConfigure(ADC1_BASE, ADC_SEQUENCE_NUMBER, ADC_TRIGGER_TIMER, 0);

ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQUENCE_NUMBER, 0, ADC_CTL_D | ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);
ROM_ADCSequenceStepConfigure(ADC1_BASE, ADC_SEQUENCE_NUMBER, 0, ADC_CTL_D | ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
ROM_ADCHardwareOversampleConfigure(ADC0_BASE, txLeakageOversamplingNumber);
ROM_ADCHardwareOversampleConfigure(ADC1_BASE, txLeakageOversamplingNumber);

ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
samplePeriod = (ROM_SysCtlClockGet() / 450000); // calculate timerperiod for 450KHz, PASS
ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, samplePeriod - 1); // sampling frequency
ROM_TimerEnable(TIMER0_BASE, TIMER_A);
ROM_TimerControlTrigger(TIMER0_BASE, TIMER_A, true);

ROM_ADCSequenceEnable(ADC0_BASE, ADC_SEQUENCE_NUMBER);
ROM_ADCSequenceEnable(ADC1_BASE, ADC_SEQUENCE_NUMBER);
ROM_ADCIntEnable(ADC0_BASE, ADC_SEQUENCE_NUMBER);
ROM_ADCIntEnable(ADC1_BASE, ADC_SEQUENCE_NUMBER);
}

Best Regards, 

Namha

  • The return value from the function HWREG() is of type "volatile uin32_t". Storing that as a uint16_t is trivial and requires no extra cycles. However, storing it as a float requires an integer to float conversion which takes extra cycles. Look at the assembly code generated in the disassembly window and you will see the additional instructions.

    When using the timer to trigger the ADC converter, as long as the ADC is not busy with another sequence, the accuracy of the sample frequency is equal to the accuracy of the system clock.