cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743ZI ADC + DMA sampling data acting quite strange

CLeo.1
Senior II

Hi everyone, hope all of you are doing well.

Posting here again about the ADC. I finally got the ADC out of that over run situation and now ready to acquire data!

The way the ADC is setup is by having 4 channels using Pins setup as continuous scanning

PC2 = Channel 0 for ADC 3 Rank 0

PC3 = Channel 1 for ADC 3 Rank 1

PF9 = Channel 2 for ADC 3 Rank 2

PF7 = Channel 3 for ADC 3 Rank 3

and internal temperature sensor = Channel 12 for ADC 3

I am essentially polling for the DMA1 Stream 4 Transfer Complete 4 flag, once this is done I know that the ADC has done all 5 sequential reads, however when I get into the array or even the data there's either nonsense data or zeros. The channels that read zero I have tried hooking up those pins to VDD and it still reads zero. I notice in the ADC3->DR there's a lot of activity going.

What I have tried thus far is, changing DMA to one shot mode, behavior is the same.

I am not sure what's going as it seems to look like the DMA is not transferring from ADC3->DR properly into its memory buffer. The buffer being used is in the x2400 region of memory and there's no error flag set for either DMA1 or ADC3.

ADC, GPIO, Low Level driver initialization

LL_DMA_InitTypeDef       ADC_Config_DMA;
	LL_GPIO_InitTypeDef      ADC_Config_GPIO;
	LL_ADC_InitTypeDef       ADC_Config_Init;
	LL_ADC_CommonInitTypeDef ADC_Config_CommonInit;
	LL_ADC_REG_InitTypeDef   ADC_Config_REG;
 
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC);
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
	LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
	LL_ADC_StructInit(&ADC_Config_Init);
	LL_ADC_CommonStructInit(&ADC_Config_CommonInit);
	LL_ADC_REG_StructInit(&ADC_Config_REG);
	LL_GPIO_StructInit(&ADC_Config_GPIO);
	LL_DMA_StructInit(&ADC_Config_DMA);
 
	//Configure GPIOA
	ADC_Config_GPIO.Mode       = LL_GPIO_MODE_ANALOG;
	ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
	ADC_Config_GPIO.Pin        = LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
	ADC_Config_GPIO.Pull       = LL_GPIO_PULL_DOWN;
	ADC_Config_GPIO.Speed      = LL_GPIO_SPEED_FREQ_VERY_HIGH;
	LL_GPIO_Init(GPIOC, &ADC_Config_GPIO);
 
	//Configure GPIOC
	ADC_Config_GPIO.Mode       = LL_GPIO_MODE_ANALOG;
	ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
	ADC_Config_GPIO.Pin        = LL_GPIO_PIN_9 | LL_GPIO_PIN_7;
	ADC_Config_GPIO.Pull       = LL_GPIO_PULL_DOWN;
	ADC_Config_GPIO.Speed      = LL_GPIO_SPEED_FREQ_VERY_HIGH;
	LL_GPIO_Init(GPIOF, &ADC_Config_GPIO);
 
	ADC_Config_DMA.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
	ADC_Config_DMA.FIFOMode = LL_DMA_FIFOMODE_DISABLE;
	ADC_Config_DMA.MemBurst = LL_DMA_MBURST_SINGLE;
	ADC_Config_DMA.MemoryOrM2MDstAddress = (uint32_t)RxBuffer;
	ADC_Config_DMA.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
	ADC_Config_DMA.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
	ADC_Config_DMA.Mode = LL_DMA_MODE_CIRCULAR;
	ADC_Config_DMA.NbData = 5;
	ADC_Config_DMA.PeriphBurst = LL_DMA_PBURST_SINGLE;
	ADC_Config_DMA.PeriphOrM2MSrcAddress = (uint32_t)&ADC3->DR;
	ADC_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_HALFWORD;
	ADC_Config_DMA.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
	ADC_Config_DMA.PeriphRequest = LL_DMAMUX1_REQ_ADC3;
	ADC_Config_DMA.Priority = LL_DMA_PRIORITY_LOW;
	//Interrupt: DMA
	LL_DMA_Init(DMA1, LL_DMA_STREAM_4, &ADC_Config_DMA);
 
	ADC_Config_Init.LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
	ADC_Config_Init.LowPowerMode = LL_ADC_LP_MODE_NONE;
	ADC_Config_Init.Resolution   = LL_ADC_RESOLUTION_16B;
	LL_ADC_Init(ADC3, &ADC_Config_Init);
 
	ADC_Config_CommonInit.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1;
	ADC_Config_CommonInit.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;
	ADC_Config_CommonInit.Multimode = LL_ADC_MULTI_INDEPENDENT;
	LL_ADC_CommonInit(ADC3_COMMON, &ADC_Config_CommonInit);
 
	ADC_Config_REG.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
	ADC_Config_REG.DataTransferMode =LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
	ADC_Config_REG.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
	ADC_Config_REG.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
	ADC_Config_REG.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS;
	ADC_Config_REG.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
	LL_ADC_REG_Init(ADC3, &ADC_Config_REG);
 
	LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_0);
	LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_1);
	LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_2);
	LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_3);
	LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_TEMPSENSOR);
 
	LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_0);
 
	LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_810CYCLES_5);
	LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_810CYCLES_5);
	LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_2, LL_ADC_SAMPLINGTIME_810CYCLES_5);
	LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_810CYCLES_5);
	LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_4, LL_ADC_SAMPLINGTIME_810CYCLES_5);
 
	LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_0, LL_ADC_SINGLE_ENDED);
	LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED);
	LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_2, LL_ADC_SINGLE_ENDED);
	LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);
 
	LL_ADC_SetCommonPathInternalCh(ADC3_COMMON, LL_ADC_PATH_INTERNAL_TEMPSENSOR);
	LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);
	LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
	//LL_ADC_SetOffsetSignedSaturation(ADC3, LL_ADC_OFFSET_4, LL_ADC_OFFSET_SIGNED_SATURATION_ENABLE);
	//LL_ADC_SetDataRightShift(ADC3, LL_ADC_OFFSET_4, LL_ADC_OFFSET_RSHIFT_ENABLE);
 
	LL_RCC_PLL2_SetM(4);
	LL_RCC_PLL2_SetN(9);
	LL_RCC_PLL2_SetP(4);
	LL_RCC_PLL2_SetFRACN(6144);
	LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
	LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
	LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL2P);
	LL_RCC_PLL2FRACN_Enable();
	LL_RCC_PLL2P_Enable();
	LL_RCC_PLL2_Enable();
 
	LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET, LL_ADC_SINGLE_ENDED);
	while (LL_ADC_IsCalibrationOnGoing(ADC3));
 
	LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
	LL_ADC_DisableDeepPowerDown(ADC3);
	LL_ADC_EnableInternalRegulator(ADC3);
	LL_ADC_ClearFlag_ADRDY(ADC3);
	LL_ADC_Enable(ADC3);
	while (LL_ADC_IsActiveFlag_ADRDY(ADC3) == 0);
	LL_ADC_ClearFlag_ADRDY(ADC3);
	LL_ADC_REG_StartConversion(ADC3);

ADC Task to read 5 channels

void ADC::ADC_Daemon(void * parameter) {
 
	int tempSensor = 0;
	int inputVoltage = 0;
	int inputCurrent = 0;
	int outputVoltage = 0;
	int outputCurrent = 0;
 
	while(1) {
		vTaskDelay(ADC_Checkin_Interval / portTICK_PERIOD_MS);
 
		if (LL_DMA_IsActiveFlag_TC4(DMA1)) {
 
			inputVoltage = dataStructure->getRxBuffer()[0];
			inputCurrent = dataStructure->getRxBuffer()[1];
 
			outputVoltage = dataStructure->getRxBuffer()[2];
			outputCurrent = dataStructure->getRxBuffer()[3];
 
			tempSensor = (TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP)/(*TEMPSENSOR_CAL2_ADDR - *TEMPSENSOR_CAL1_ADDR) * dataStructure->getRxBuffer()[4] + 30;
			LL_DMA_ClearFlag_TC4(DMA1);
		}
	}
}

Data within the buffer once Transfer Completed flag 4 from the DMA1 is triggered. Just pure nonsense data. The pins are pull down and not in used but here there's some kind of voltage.

0693W00000GW7jBQAT.jpg

20 REPLIES 20

it depends, if the pins driven or floating. in case of floating, pulled down should lead to 0mV for ADC.​

Super weird then. I am usinf a nucelo stm32h743zi board

all channrls used for the adc is pulled down however they are all affected by this random voltage offset. Setting pins pc2-3 to gnd sets it to zero but pins pf7-9 doesnt do anything even the physical pins are set to gnd

I try based on the example project: 

STM32Cube_FW_H7_V1.9.0 -> NUCLEO-H743ZI\Examples\ADC\ADC_InternalChannelConversion, the pins are floating basically, pulled down to GND will lead to 0mV, pulled up to Vdda=3.3V will lead to 3300mV,

connected to potentiometer and voltages are in line with values measured by multi-meter, OK for both PF7 and PF9

That's really interesting. My PF7 or PF9 don't react if being pulled up or down. In my code in the initialization part both of the pins in questions are also configured as pulled down. Any ideas?

jiangfan
ST Employee

in fact, I did not configure the GPIO pins (PF7, PF9), the default config should be analog. or use below config:

 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

So just tried it with the example and it worked flawlessly, obviously. The only difference I saw was that AFL was set to 15 I tried no cigar.

Whats the proper procedure to setup your GPIO for analog?

just follow the proper example for ADC

I may need help here. So following the internalChannelConversion example the pins are doing what they are suppose to do. When the pin is set to GND it goes to 0 Count and 3.3V goes to FS.

The only initiation I see the code doing is the ADC, System Clock. However my ADC settings are the exact same, so I dont know what else it could be.

STM32Cube_FW_H7_V1.9.0\Projects\NUCLEO-H743ZI\Examples\ADC

ADC_RegularConversion_Polling or ADC_AnalogWatchdog examples, the pins are configured, like:

 /*##-2- Configure peripheral GPIO ##########################################*/

 /* ADC Channel GPIO pin configuration */

 GPIO_InitStruct.Pin = ADCx_CHANNEL_PIN;

 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 HAL_GPIO_Init(ADCx_CHANNEL_GPIO_PORT, &GPIO_InitStruct);