Skip to main content
Mahendra Sondagar
Associate III
October 19, 2021
Solved

STM32WB Multi-channel ADC with DMA, buffer sequence issue

Hello geeks..

Hope all are doing well

I'm using multi channel ADC with STM32WB having DMA activated

My issue is, every time when i perform the power ON reset, at the same time the channel sequence getting change!

It means, the conversion buffer in HAL_ADC_ConvCpltCallback function sequence is getting change

I have verified the same thing manually by connecting the 3.3V & GND at the particular channels

For example, when i connect the 3.3v at PC4 then the allocated buffer variable shows 4096 samples. However when i do the power on reset then some different buffer shows the value 4096

I have activated the 6 channels here with DMA

I have shared ADC initialization code snippet here

Can any one help me here ?

All suggestions & comments welcome

Thanks

0693W00000FD0mfQAD.png 

/**
 * @brief ADC1 Initialization Function
 * @param None
 * @retval None
 */
int32_t BSP_ADC1_Init(void) {
 
	/* USER CODE BEGIN ADC1_Init 0 */
 
	/* USER CODE END ADC1_Init 0 */
 
	ADC_ChannelConfTypeDef sConfig = { 0 };
 
	/* USER CODE BEGIN ADC1_Init 1 */
 
	/* USER CODE END ADC1_Init 1 */
	/** Common config
	 */
	hgasadc1.Instance = ADC1;
	hgasadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6;
	hgasadc1.Init.Resolution = ADC_RESOLUTION_12B;
	hgasadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	hgasadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
	hgasadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
	hgasadc1.Init.LowPowerAutoWait = DISABLE;
	hgasadc1.Init.ContinuousConvMode = ENABLE;
	hgasadc1.Init.NbrOfConversion = 6;
	hgasadc1.Init.DiscontinuousConvMode = DISABLE;
	hgasadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
	hgasadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
	hgasadc1.Init.DMAContinuousRequests = ENABLE;
	hgasadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
	hgasadc1.Init.OversamplingMode = DISABLE;
	if (HAL_ADC_Init(&hgasadc1) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_10;
	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(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_13;
	sConfig.Rank = ADC_REGULAR_RANK_2;
	if (HAL_ADC_ConfigChannel(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_14;
	sConfig.Rank = ADC_REGULAR_RANK_3;
	if (HAL_ADC_ConfigChannel(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_15;
	sConfig.Rank = ADC_REGULAR_RANK_4;
	if (HAL_ADC_ConfigChannel(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_9;
	sConfig.Rank = ADC_REGULAR_RANK_5;
	if (HAL_ADC_ConfigChannel(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/** Configure Regular Channel
	 */
	sConfig.Channel = ADC_CHANNEL_16;
	sConfig.Rank = ADC_REGULAR_RANK_6;
	if (HAL_ADC_ConfigChannel(&hgasadc1, &sConfig) != HAL_OK) {
		Error_Handler();
	}
	/* USER CODE BEGIN ADC1_Init 2 */
 
	/* USER CODE END ADC1_Init 2 */
 
}

/**
 * @brief Conversion complete callback in non-blocking mode.
 * @param hadc ADC handle
 * @retval None
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
	if (hadc->Instance == ADC1) {
		adc_0 = AdcRawSamples[0]; /* -> PC4 -> BSP_GM_402B_CHANNEL */
		adc_1 = AdcRawSamples[1]; /* -> PC5 -> BSP_GM_512B_CHANNEL */
		adc_2 = AdcRawSamples[2]; /* -> PA8 -> BSP_GM_702B_CHANNEL */
		adc_3 = AdcRawSamples[3]; /* -> PA9 -> BSP_TGS8100_CHANNEL */
		adc_4 = AdcRawSamples[4]; /* -> PA4 -> BSP_GM_802B_CHANNEL */
		adc_5 = AdcRawSamples[5]; /* -> PA5 -> BSP_GM_502B_CHANNEL */
	}
}

This topic has been closed for replies.
TDK
TDKBest answer
October 23, 2021

> All the channels are floating expect the channel that I'm testing with 3.3V

> However by connecting the GND to very next channels shows the batter result

Measuring the voltage of an infinite impedance source (open circuit) is not useful. If you want it to be 0V when open, you'll need a pulldown resistor.

"If you feel a post has answered your question, please click ""Accept as Solution""."

6 replies

TDK
October 19, 2021

I don't think there's an issue in the code you've shown. I would imagine there's a bug somewhere else, perhaps in how you're calling HAL_ADC_Start*.

Note that 6 samples don't fit evenly into a buffer of 4096.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Mahendra Sondagar
Associate III
October 22, 2021

Hi.. @TDK​ 

Thanks for your feedback

You're right!

Actually, I'm using the BLE Stack to send the Analog sensors data to android app with custom GATT services

I was triggering the DMA of the ADC when user start the services from the app and stopping it when user stop the services

The issue with the stop api that i was using previously

Instead of the stopping the DMA, i was stopping the ADC by calling HAL_ADC_Stop

So, when again user trigger the GATT services from smart phone then,, HAL_ADC_Start_DMA calling which was failing as the ADC engine went off from the previous cycle

Adding the HAL_ADC_Stop_DMA api to stop the adc has been solved the issue

However, one strange thing that i have Noticed here,

When i changing the ADC voltage of the one channel then, it's also affecting the very next channel !!

Normally, the very next channel show 340 samples at open circuit condition, however when i touch to the 3.3V to the previous channel at whom i need to sense, it's affecting the next channels from 340 to above 1000 !

Any advice ?

Thanks

TDK
October 22, 2021

> When i changing the ADC voltage of the one channel then, it's also affecting the very next channel !!

> Normally, the very next channel show 340 samples at open circuit condition, however when i touch to the 3.3V to the previous channel at whom i need to sense, it's affecting the next channels from 340 to above 1000 !

You shouldn't see that much variation. Is the channel floating or at a very high impedance? What happens if you directly ground it?

The ADC has a single sampling capacitor. For higher impedance sources, increasing the sampling time can help.

https://www.st.com/resource/en/application_note/cd00211314-how-to-get-the-best-adc-accuracy-in-stm32-microcontrollers-stmicroelectronics.pdf

"If you feel a post has answered your question, please click ""Accept as Solution""."
Mahendra Sondagar
Associate III
October 23, 2021

Hi.. @TDK​ 

All the channels are floating expect the channel that I'm testing with 3.3V

However by connecting the GND to very next channels shows the batter result

The near by channel floating between 0-1 samples

I got your point

Thanks for the Reference pdf

For now, all the issues have been solved

TDK
TDKBest answer
October 23, 2021

> All the channels are floating expect the channel that I'm testing with 3.3V

> However by connecting the GND to very next channels shows the batter result

Measuring the voltage of an infinite impedance source (open circuit) is not useful. If you want it to be 0V when open, you'll need a pulldown resistor.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Mahendra Sondagar
Associate III
October 27, 2021

sure.. Thanks