cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7A3ZI-Q getting random values from ADC

ikok07
Associate

Hello, I'm currently trying to develop a bare-metal ADC driver for my Nucleo STM32H7A3ZI-Q Board. I have done all the necessary steps in order to setup the ADC, however I still get random values from the data register, even though I have my PF11 (or A5) connected to the GND.

Here is my current code:

#define ADC1EN					(1U<<5)
#define GPIOFEN					(1U<<5)
#define ADC_CH2					(1U<<7)
#define ADC_SEQ_LEN_1			        (0x00)

#define ADC_DEEPPWDEN			        (1U<<29)
#define ADC_REGEN				(1U<<28)
#define ADC_LDORDY				(1U<<12)
#define ADC_PRESC_2				(1U<<18)
#define ADC_CKMODE_SCLK_1		        (2U<<16)
#define ADC_ADCALDIF			        (1U<<30)
#define ADC_ADCALLIN			        (1U<<16)
#define ADC_ADCAL				(1U<<31)
#define ADC_ADEN				(1U<<0)
#define ADC_ADSTART				(1U<<2)
#define ADC_ADRDY				(1U<<0)

#define ADC_EOC					(1U<<2)

void pf11_adc_init(void) {

	// Configure the ADC GPIO pin

	RCC->AHB4ENR |= GPIOFEN; 				// Enable clock access to GPIOF
	GPIOF->MODER |= (1U<<23) | (1U<<22); 	// Set mode of PF11 to analog

	// Configure the ADC module

	RCC->AHB1ENR |= ADC1EN; // Enable clock access to ADC1

	// Conversion sequence start
	ADC1->SQR1 = ADC_CH2;

	// Conversion sequence length
	ADC1->SQR1 |= ADC_SEQ_LEN_1;

	// Disable ADC deep-power-down mode
	ADC1->CR &=~ ADC_DEEPPWDEN;

	// Start the voltage regulator
	ADC1->CR |= ADC_REGEN;

	// Wait for the regulator to start up
	while (!(ADC1->ISR & ADC_LDORDY)) {}

	// Select prescaler -> 2
//	ADC12_COMMON->CCR |= ADC_PRESC_2;

	// Select kernel clock (derive from AHB clock)
	ADC12_COMMON->CCR |= ADC_CKMODE_SCLK_1;

	// Set single-ended calibration mode
	ADC1->CR &=~ ADC_ADCALDIF;

	// Enable linearity calibration
	ADC1->CR |= ADC_ADCALLIN;

	// Start ADC calibration
	ADC1->CR |= ADC_ADCAL;

	// Wait for calibration to finish
	while (ADC1->CR & ADC_ADCAL) {}

	// Enable the ADC module
	ADC1->ISR |= ADC_ADRDY; // clear ready state
	ADC1->CR |= ADC_ADEN;

	// Wait for the ADC to be ready
	while (!(ADC1->ISR & ADC_ADRDY)) {}
}

void start_conversion(void) {

	// Start the ADC conversion
	ADC1->CR |= ADC_ADSTART;
}

uint32_t adc_read(void) {
	// Wait for conversion to be complete
	while (!(ADC1->ISR & ADC_EOC)) {}

	// Read converted result
	return ADC1->DR;
}

 

1 REPLY 1
Imen.D
ST Employee

Hello @ikok07 ,

What values/range are you getting?

Make sure that the ADC clock is running at the correct frequency. Check if the ADC channels are properly enabled and configured.

I advise you to test and run the ready-to-use ADC example, this helps isolate the issue and ensures that the problem seems related to the hardware or software : STM32CubeH7/Projects/NUCLEO-H7A3ZI-Q/Examples/ADC at master · STMicroelectronics/STM32CubeH7 · GitHub

Also, refer to the errata sheet for your product and check whether you have an ADC limitation that is described in the documentation.

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen