2018-06-27 02:24 AM
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.2018-06-27 03:50 AM
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 cycles2018-06-27 09:30 AM
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
2018-06-27 09:43 AM
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.
2018-06-27 10:17 AM
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
2018-06-28 05:04 AM
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 &sharpendifif (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_Valuebest regards
Ed
2018-06-28 05:22 AM
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.
2018-06-28 10:40 AM
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
2018-06-29 12:20 AM
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).2018-06-29 02:01 AM
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