cancel
Showing results for 
Search instead for 
Did you mean: 

Help Needed: STM32H750 ADC1 PA0 Not Reading Continuously

electrohighlow
Associate

Issue Description:
I am trying to configure ADC1 on PA0 (Channel 16) in continuous mode on the STM32H750 microcontroller. However, the code gets stuck at:

 

while (!(ADC1->ISR & ISR_EOC) && --timeout); // ‌‌ Wait for End-of-Conversion

 

This suggests that EOC (End-of-Conversion) is never set, meaning the ADC is not completing a conversion.

*What I Have Done:
-Enabled clocks for GPIOA and ADC1 (RCC->AHB4ENR and RCC->AHB1ENR)
-Configured PA0 as Analog Mode (GPIOA->MODER |= (3U << 0);)
-Set the correct ADC clock source in CCR
-Exited deep power-down mode and enabled the ADC voltage regulator
-Performed ADC calibration and waited for completion
-Enabled ADC and waited for ISR_ADRDY (ADC Ready flag)
-Enabled PA0 in PCSEL
-Set CFGR_CONT for continuous mode
-Configured SQR1 for a single-channel sequence (Channel 16, Rank 1)
-Set maximum sampling time for PA0 (SMPR1)
-Started ADC conversion (CR_ADSTART)
-Full Code:

 

#include "stm32h7xx.h" #include <stdint.h> // Define Register Bit Masks #define GPIOAEN (1U << 0) // Enable GPIOA Clock #define ADC1EN (1U << 5) // Enable ADC1 Clock #define CR_ADVREGEN (1U << 28) // Voltage Regulator Enable #define CR_DEEPPWD (1U << 29) // Deep Power-Down Disable #define ADC_CALIBRATION (1U << 31) // ADC Calibration #define CFGR_CONT (1U << 13) // Continuous Mode Enable // Define ADC Control Register Bits #define CR_ADEN (1U << 0) // ADC Enable Bit #define CR_ADSTART (1U << 2) // ADC Start Conversion #define CR_ADDIS (1U << 1) // ADC Disable Bit // Define ADC Status Register Bits #define ISR_EOC (1U << 2) // End of Conversion Flag #define ISR_ADRDY (1U << 0) // ADC Ready Flag #define ISR_LDORDY (1U << 12) // ADC LDO Ready Flag // Define ADC Channel Configuration #define CH16_RANK1 (16U << 6) // Channel 16 (PA0) as Rank 1 volatile uint32_t adc_value; // Store ADC result // Function to Initialize ADC for PA0 (Channel 16) in Continuous Mode void adc1_init(void) { // 1-Enable Clocks for GPIOA and ADC1 RCC->AHB4ENR |= GPIOAEN; // Enable GPIOA Clock RCC->AHB1ENR |= ADC1EN; // Enable ADC1 Clock // ‌‌ Ensure ADC is using the correct clock ADC12_COMMON->CCR &= ~(0b11 << 16); // Clear clock source ADC12_COMMON->CCR |= (0b01 << 16); // Select AHB clock for ADC //2-Configure PA0 as Analog Mode GPIOA->MODER |= (3U << 0); // Set PA0 to Analog Mode GPIOA->PUPDR &= ~(3U << 0); // No Pull-up, No Pull-down // 3-Exit Deep Power Down & Enable Voltage Regulator ADC1->CR &= ~CR_DEEPPWD; // Exit deep power-down ADC1->CR |= CR_ADVREGEN; // Enable voltage regulator while (!(ADC1->ISR & ISR_LDORDY)); // ‌‌ Wait for LDO Ready // 4-Ensure ADC is Disabled Before Calibration if (ADC1->CR & CR_ADEN) { ADC1->CR |= CR_ADDIS; // ADC Disable while (ADC1->CR & CR_ADEN); } // 5-Start Calibration ADC1->CR |= ADC_CALIBRATION; while (ADC1->CR & ADC_CALIBRATION); // ‌‌ Wait for calibration // 6-Enable ADC ADC1->CR |= CR_ADEN; while (!(ADC1->ISR & ISR_ADRDY)); // ‌‌ Wait for ADC Ready // 7-Enable Channel 16 (PA0) in PCSEL ADC1->PCSEL |= (1U << 16); // ‌‌ Must enable the channel in PCSEL // 8-Configure ADC for Continuous Mode ADC1->CFGR |= CFGR_CONT; // ‌‌ Enable Continuous Mode ADC1->SQR1 &= ~(0xF << 0); // Clear sequence length ADC1->SQR1 |= CH16_RANK1; // Set Channel 16 (PA0) as Rank 1 // 9-Set Correct Sampling Time for Channel 16 ADC1->SMPR1 |= (0b111 << 18); // Max sampling time for PA0 // 10-Start ADC Conversion (Only if ADC is Ready) ADC1->ISR |= ISR_EOC; // ‌‌ Clear any previous EOC flag ADC1->CR |= CR_ADSTART; } // Function to Read ADC Value uint32_t adc_read(void) { uint32_t timeout = 1000000; // Prevent infinite loop while (!(ADC1->ISR & ISR_EOC) && --timeout); // ‌‌ Wait for End-of-Conversion if (timeout == 0) { return 0xFFFFFFFF; // Error: Timeout occurred } ADC1->ISR |= ISR_EOC; // ‌‌ Clear EOC flag to allow next conversion return ADC1->DR; // Read ADC value } int main(void) { adc1_init(); // Initialize ADC1 for Continuous Conversion on PA0 while (1) { adc_value = adc_read(); // Continuously Read ADC } }
View more

 


*****What I Need Help With***
Why does the ADC get stuck at while (!(ADC1->ISR & ISR_EOC));?

Is ADSTART getting cleared automatically after the first conversion?
Should I manually restart ADSTART?
Is PCSEL being set correctly before conversion starts?

I am enabling PCSEL (ADC1->PCSEL |= (1U << 16);) before configuring the sequence.
Are there any additional settings required in CCR, CFGR, or SMPR?

Should I explicitly configure DIFSEL or LTR registers?
Are there better debugging methods to check if the ADC is running?

Should I use an oscilloscope to check PA0 input?
Are there any status bits I should read to confirm ADC is running?
******System Information*****
Microcontroller: STM32H750
IDE: STM32CubeIDE
Debugger: ST-LINK V2

Edit: code formatting

1 REPLY 1
mƎALLEm
ST Employee

Hello,

To speed up the process, I suggest you to use HAL: create your example with CubeMx and generate the code. Then inspire from that implementation to do the direct access to the registers. It's difficult to follow each line and check each shift from your code.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.