2025-01-05 12:07 PM
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;
}