Skip to main content
LVolp.2
Associate II
Aug 19, 2022 8:52 AM UTC
Question

How to correctly read ADC internal channels with DMA

Hello, 

I am using a p-nucleo-WB55 and I am trying to use DMA to read two internal channels : 

- Internal temperature sensor 

- Vbat

Here is my code :

#define VDDA_APPLI (3300U)
 
uint16_t ReadVbat(uint16_t value)
{
	return (value/65536)*VDDA_APPLI*3;
}
 
int main(void)
{
 HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
 
 uint16_t ADC_Results[2];
 uint16_t ADC_TEMP = 0;
 uint16_t ADC_VBAT = 0;
 
 while (1)
 {
 HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Results, 2);
	 if (overflow == 1)
	 {
		 ADC_TEMP = __LL_ADC_CALC_TEMPERATURE(VDDA_APPLI, ADC_Results[0], LL_ADC_RESOLUTION_12B);
		 ADC_VBAT = ReadVbat(ADC_Results[1]);
	 }
	 overflow = 0;
 HAL_Delay(100);
 }
}

Here is the configuration of the ADC :

/** Common config
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 hadc1.Init.ContinuousConvMode = ENABLE;
 hadc1.Init.NbrOfConversion = 2;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_VBAT;
 sConfig.Rank = ADC_REGULAR_RANK_2;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

The value that I get are not good and I think maybe it is a calibration issue

Results :

0693W00000QO42rQAD.png ADC_TEMP should be between 25 and 30 and ADC_VBAT should be at 3300.

Had you once this issue ? Do you know what could be wrong ?

Have a nice day

This topic has been closed for replies.

1 reply

waclawek.jan
Super User
Aug 19, 2022 11:14 AM UTC

> uint16_t value

> return (value/65536)*VDDA_APPLI*3;

This is always zero, due to truncating integer division.

> __LL_ADC_CALC_TEMPERATURE

Look at that macro in Cube, check all values in that macro (in headers and subsequently reading out from the system memory), check if the ADC readout value is within the expected range.

JW