Skip to main content
Senior
February 11, 2024
Solved

Help Needed on A/D Conversion

  • February 11, 2024
  • 7 replies
  • 1865 views

Hi,

I am trying to do multi-channel single conversion in polling mode in a scan sequence on an Nucleo-STM32G070 board, there is a multi-channel ADC example with this board, but it needs a trigger for every channel. What I need is:

start the conversion for all channels successively, one by one, and after one second,

collect the result in an array and start the conversion again.

So the questions are:

1. how to configure so that the multi-channels could be converted one by one with just one trigger?

2. how to retrieve the conversion data for all channels?

I checked the HAL driver stm32g0xx_hal_adc.c, it provides only one function to get the result: 

uint32_t HAL_ADC_GetValue(const ADC_HandleTypeDef *hadc)

It returns the DR register value. I did not find a similar function that returns a pointer which points to an array of the conversion values for the multi-channels.

The following is my MX_ADC1_Init:

static void MX_ADC1_Init(void)

{

ADC_ChannelConfTypeDef sConfig = {0};

/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;

hadc1.Init.Resolution = ADC_RESOLUTION_12B;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

hadc1.Init.LowPowerAutoWait = DISABLE;

hadc1.Init.LowPowerAutoPowerOff = DISABLE;

hadc1.Init.ContinuousConvMode = ENABLE;

hadc1.Init.NbrOfConversion = 3;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc1.Init.DMAContinuousRequests = DISABLE;

hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;

hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;

hadc1.Init.OversamplingMode = DISABLE;

hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

Error_Handler();

}

/** Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_4;

sConfig.Rank = ADC_REGULAR_RANK_1;

sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;

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

{

Error_Handler();

}

/** Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;

sConfig.Rank = ADC_REGULAR_RANK_2;

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

{

Error_Handler();

}

/** Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_VREFINT;

sConfig.Rank = ADC_REGULAR_RANK_3;

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

{

Error_Handler();

}

}

Please help!

Regards

Chao

This topic has been closed for replies.
Best answer by AScha.3

SystemCoreClock as 56MHz -> cpu at this clk. right.

+

cycles of adc :  = adc clk cycles ; you set the adc clk in Cube - so you should know (look, what you set..)

if ADC_CLOCK_SYNC_PCLK_DIV2 : 56M /2 = 28M  (adc clk)

x 79 cyc = about 2,8 us , so set more sampling cycles, to fulfill 5us . 

set : 160.5 cyc -> about 5,9us , seems good.

7 replies

AScha.3
Super User
February 11, 2024

Hi,

ADC works on a sequence of conversions - you set it . (in >Cube)

>1. how to configure so that the multi-channels could be converted one by one with just one trigger?

Then start sequence...doing exactly this.

>2. how to retrieve the conversion data for all channels?

You set/start sequence with "INT" , so you get an interrupt after each conversion, and you store result ...in array or what you like. So you see: ADC is no magic , you have to store results, or you use a DMA , to do this for you.

(But little bit more complex,to set up. Trigger->ADC sequence ->DMA writes to array. )

If you feel a post has answered your question, please click on " Best Answer ".
ChaoAuthor
Senior
February 13, 2024

Thank you so much, now I use DMA to do it. But the mcu internal temperature calculation using predefined macro __LL_ADC_CALC_TEMPERATURE in stm32g0xx_ll_adc.h  gives result from -42 to -72 for a Nucleo-STM32G070 board, while room temperature is about +18°C.

Chao_0-1707835654074.png

The following is the macro:

Chao_1-1707835759807.png

and this is the use of the macro:

uint32_t vrefAnalogVoltage = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(convertedData[2], ADC_RESOLUTION_12B);

int32_t McuTemp = __HAL_ADC_CALC_TEMPERATURE(vrefAnalogVoltage, convertedData[1], ADC_RESOLUTION_12B);

where convertedData[2] is the measured value for VrefInt, and convertedData[1] is the measured value of the internal TempSensor.

Where is wrong in my calculation ?

Regards

Chao

AScha.3
Super User
February 13, 2024

Did you set the adc for temp measuring ? (Needs special setup...slow...and wait time; read rm !! )

->

AScha3_0-1707837985775.png

 

If you feel a post has answered your question, please click on " Best Answer ".