cancel
Showing results for 
Search instead for 
Did you mean: 

ADC in STM32F415ZG, how can i reached the Conversion time in the Datasheet ?

Ed Raab
Associate II
Posted on June 27, 2018 at 11:24

hallo,

i am trying to program the ADC in the STM32F415ZG. I use the hal library and have written interface functions and modifications to adapted it to my application. I have tried out the dma and the Interrupt driven adc conversion via SW-Trigger starts in a loop with other procedures. The shortes ADC conversion time of a single value measured to approximately 6 Mikroseconds. I used an ADC clock of 24MHz. According to the data sheet there are Conversion times below 0,5 Mikroseconds reachable. Is there anybody who have a code example for this.

Thanks.

best regards

Ed

Note: this post was migrated and contained many threaded conversations, some content may be missing.
9 REPLIES 9
AvaTar
Lead
Posted on June 27, 2018 at 12:50

By reducing the resolution to 6 bit, for instance.

The reference manual says:

The minimum conversion time for each resolution is then as follows:

• 12 bits: 3 + 12 = 15 ADCCLK cycles

• 10 bits: 3 + 10 = 13 ADCCLK cycles

• 8 bits: 3 + 8 = 11 ADCCLK cycles

• 6 bits: 3 + 6 = 9 ADCCLK cycles
Posted on June 27, 2018 at 16:30

hallo,

i have read this. But with 12Bits resolution with 15 ADCCLK cycles and 24MHz the conversion time is 0,625 mikroseconds. I measure more than 6 mikroseconds. There is a big difference??

best regards

Ed

Posted on June 27, 2018 at 16:43

What exactly do you mean with 'conversion time' ?

The quote from the reference manual refers to the conversion alone.

For an ADC value, you have sampling time + conversion time.

Posted on June 27, 2018 at 17:17

Show the code, the code initializing the ADC and that for the clocks. That way we don't have to guess how you arrived at 6ms

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 28, 2018 at 12:04

hallo,

thank for the reply.

A correction: ADC-CLK is 21MHz and not 24MHz; (SYSCLK=168MHz; APB2-dvider=2 -> PCLK2=84MHz; ADC_divider =4 -> ADCCLK=21MHz)

Here is a Code snippet from the ADC-functions.

The switch ADC_DMA is not defined in order to use ADC-Interrupt.

Functions:

ADC_Config(xxx) : configure the ADC;

ADC_Start() starts the ADC-Conversion;

HAL_ADC_ConvCpltCallback () stores the ADC-value;

Get_ADC_Value(yyy) reads the ADC-Value  by the application.

The Timing  measurment is realised by the HAL_GPIO_WritePin-Commands in funtions ADC_Start and  HAL_ADC_ConvCpltCallback.

Here are the code snippets.

// ******************************************************

static void SystemClock_Config(void)

{  

if(ret != HAL_OK)

{

while(1) { ; }

}

/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2

clocks dividers */

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; //RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // RCC_HCLK_DIV2;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; //RCC_HCLK_DIV1;

ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);

if(ret != HAL_OK)

{

while(1) { ; }

}

}

// ******************************************************

static void ADC_Config(void)

{

ADC_ChannelConfTypeDef sConfig;

ADC_AnalogWDGConfTypeDef AnalogWDGConfig;

/* Configuration of ADCx init structure: ADC parameters and regular group */

AdcHandle.Instance = ADCx;

AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;

AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;

AdcHandle.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */

AdcHandle.Init.ContinuousConvMode = ENABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */

AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */

AdcHandle.Init.NbrOfDiscConversion = 0;

&sharpif defined ADC_TRIGGER_FROM_TIMER_

&sharpelse

&sharpifdef ADC_DMA

&sharpelse // ADC_IT

AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Conversion start trigged at each external event */

AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; //ADC_EXTERNALTRIGCONV_T1_CC1;

AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;

AdcHandle.Init.NbrOfConversion = 1;

AdcHandle.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */

AdcHandle.Init.DMAContinuousRequests = DISABLE;

AdcHandle.Init.EOCSelection = DISABLE;

&sharpendif

&sharpendif

if (HAL_ADC_Init(&AdcHandle) != HAL_OK)

{

/* ADC initialization error */

ADC_Error_Handler();

}

sConfig.Channel = ADCx_CHANNEL;

sConfig.Rank = 1;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)

{

// Channel Configuration Error

ADC_Error_Handler();

}

}

// ******************************************************

uns_32 ADC_Start ( void )

{

uint16_t i;

if ( !bADCConvStartEnable ) return ( 0 );

nADCCounter = nADCCounter_1;

for ( i = 0; i < nADCCounter+1/*ADCCONVERTEDVALUES_BUFFER_SIZE*/; i++ )

aADCxConvertedValues[i] = 0;

HAL_GPIO_WritePin ( SA_KOM_TEST_PIN2_PORT, SA_KOM_TEST_PIN2, GPIO_PIN_SET );

&sharpifdef ADC_DMA

if (HAL_ADC_Start_DMA(&AdcHandle,

(uint32_t *)aADCxConvertedValues,

nADCCounter+1 /* ADCCONVERTEDVALUES_BUFFER_SIZE */

) != HAL_OK)

&sharpelse // ADC_IT

if (HAL_ADC_Start_IT(&AdcHandle) != HAL_OK)

&sharpendif

{

/* Start Error */

//Error_Handler();

return ( 0 );

}

else

{

bADCConvStartEnable = 0;

return ( 1 );

}

} // ADC_Start

// ******************************************************

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)

{

&sharpifdef ADC_DMA

&sharpelse

uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);// lese DR

&sharpendif

bADCConvCplt = 1;

HAL_GPIO_WritePin ( SA_KOM_TEST_PIN2_PORT, SA_KOM_TEST_PIN2, GPIO_PIN_RESET );

}

// ******************************************************

uns_32 Get_ADC_Value ( uns_32 *pADCValue )

{

uint32_t i,uExtremMin,uExtremMax;

uint32_t ntemp = 0;

if ( bADCConvCplt > 0 )

{

&sharpifdef ADC_DMA // ADC_DMA

// **********

&sharpelse // ADC_IT

ntemp = (uint32_t)uhADCxConvertedValue;

&sharpendif

ntemp = ntemp>>4; //nur fuer Test

*pADCValue = ntemp;

bADCConvCplt = 0;

bADCConvStartEnable = 1;

return ( 0 ); // neuer ADC-Wert vorhanden

}

else

return ( 1 ); // kein neuer ADC-Wert vorhanden

} // Get_ADC_Value

best regards

Ed

Posted on June 28, 2018 at 12:22

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)

{

uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);// lese DR

...

HAL_GPIO_WritePin ( SA_KOM_TEST_PIN2_PORT, SA_KOM_TEST_PIN2, GPIO_PIN_RESET );

If you measure across HAL callbacks, you surely get longer times.

Posted on June 28, 2018 at 17:40

hallo AvaTar,

of course this command have some cycles but not the time of 5 or 6 mikroseconds. The call is from the ADC-ISR. Its very close to the detection of adc conversion finished (EOC).  With the system cyle time of approx. 6ns (168MHz) there are 1000 cycles of code in this time. I cant believe this.  I dont want change the HAL-functions not more than neccessary. I think a conversion time below 1Mikrosecond may be reachable with this measure method. 

best regards

Ed

Posted on June 29, 2018 at 07:20

You are measuring across the interrupt, the callback and the HAL_ADC_GetValue call, involving a lot of irrelevant code.

Several ADCs (like the F407) have a inter-cycle delay, i.e. a configurable number of cycles between conversions. Check your code for this setting, or the reference manual for the default value. I used to leave it at 5 cycles (using SPL).
Posted on June 29, 2018 at 09:01

hallo AvaTar,

thanks for the hints. I will look for this.

by the way some introductions of the code: the function ADC_Start

 

() sets the GPIO-Signal and starts the ADC Conversion in Interupt mode. The function  HAL_ADC_ConvCpltCallback(), which is called from the ADC-ISR, has only three lines code (store the ADC-Value, sets the Cplt-Flag and clear the GPIO-Signal finished the ADC Conversion of the HW after reti). The function Get_ADC_Value

 ()

 is called from the main-loop and checks the Cplt-Flag and reads the ADC-Value (finished the ADC Conversion for the Application). There is no callback here. Further a next ADC_Start is prepared with the ADCStartConvEnable-Flag. The time between two ADC_Start calls is aprox. 100..200usec. depending on other actions.  The time i am looking for is between the

ADC_Start and the HAL_ADC_ConvCpltCallback. 

I will  check the code in the functions called from ADC_Start and the HAL-ADC-ISR. I found several calls like unlock, lock, disable and enable and a wait-loop after enable. 

Until now i have only used the HAL-Lib. I will take a look at SPL.

best regards

Ed