2025-03-25 11:06 PM - last edited on 2025-03-26 12:25 AM by mƎALLEm
I need help. I couldn't get any adc value whether with live expressions or UART . UART is working fine so the problem is within the ADC configuration code. have i miss or overcomplicated anything?
#include "stdio.h"
#include "stdint.h"
#include "stm32h573xx.h"
#include "uart.h"
//volatile uint16_t sensor_value;
__IO uint16_t sensor_value;
void PA4_PA5_ADC_Init(void) {
//RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; //Enable Clock for GPIOA
GPIOA->MODER &= ~((3U << (4 * 2)) | (3U << (5 * 2))); //Reset PA4 & PA5
GPIOA->MODER |= ((3U << (4 * 2)) | (3U << (5 * 2))); //Set PA4 & PA5 as analog input
GPIOA->PUPDR &= ~((3U << (4 * 2)) | (3U << (5 * 2))); //Set no pullup or pulldown
}
void adcclk_init(void){
// Configure ADC clock source
//
//hsi_ck selected as system clk in uart.c
//
RCC->AHB2ENR |= (1U << 10); //Enable ADC Clock
RCC->CCIPR5 &= ~(7U << 0); // Clear ADCSEL bits; rcc_hclk as clock source (default after reset)
RCC->CCIPR5 |= (1U<<0); //sys_ck slected as kernel clk for ADC
ADC12_COMMON->CCR &= ~(0x1F<<0); //Set ADC1 and ADC2 to independent mode
ADC12_COMMON->CCR &= ~(15U<<18); //PRESC[3:0] | ADC prescaler; Input ADC clock not divided
ADC12_COMMON->CCR &= ~(3U<<16); //CKMODE[1:0] | 00 ADC clock scheme: adc_ker_ck
ADC12_COMMON->CCR |= (1U<<16); //CKMODE[1:0] | 01 ADC clock scheme: adc_hclk/1
//This configuration must be enabled only if the AHB clock prescaler is set to 1 (HPRE[3:0] = 0XXX in RCC_CFGR register)
//and if the system clock has a 50% duty cycle. RCC_CFGR HPRE[3:0] wasset in uart.c
}
void adcinit(void) {
VREFBUF->CSR &= ~(7U<<4); //Set to VREFBUF0
// Enable VREFBUF
VREFBUF->CSR &= ~(1U<<1); //Set HIZ to 0
VREFBUF->CSR &= ~(1U<<0);
VREFBUF->CSR |= (1U<<0); //Set ENVR to 1
while (!(VREFBUF->CSR & VREFBUF_CSR_VRR)) {}
//while (!(VREFBUF->CSR & (1U<<3))) {} //Wait until Voltage ref buffer output has stabilized.
ADC1->SMPR2 &= ~(7U <<24); // Set ADC CH18 sample time to 2.5ADC cycles
ADC1->DIFSEL |= (1U << 18); // Set ADC Channel 18 as diff. mode (PA4 is INP18 while PA5 is INN18)
//ADC1->DIFSEL &= ~(1U << 18); // Set ADC Channel 18 as single-ended mode (PA4 is INP18 while PA5 is INN18)
ADC1->SQR1 &= ~(15U << 0); // Set Seq length to single conversion
ADC1->SQR1 &= ~(31U << 6); // Clear bits 6-10
ADC1->SQR1 |= (18U << 6); // Write 18 (dec) on bits 6-10 to set Channel 18 as the 1st sequence for ADC conversion
ADC1->CFGR &= ~((1U << 11) | (1U << 10)); // Select sw trigger for ADC conversion
ADC1->CFGR &= ~((1U << 4) | (1U << 3)); // Set 12-bit resolution (default)
ADC1->CFGR &= ~(1U << 15); // Set to right alignment
ADC1->CFGR |= ADC_CFGR_CONT; // Set ADC to continuous mode
ADC1->CFGR |= ADC_CFGR_OVRMOD; // Set ADC to overwrite when register is full
ADC1->CR &= ~ADC_CR_DEEPPWD; // Take ADC voltage regulator out of deep power down mode
ADC1->CR |= ADC_CR_ADVREGEN; // Enable ADC regulator
for (volatile int i = 0; i < 10000; i++); // Implement delay > TADCVREG_STUP which is 10us
ADC1->ISR &= ~(1U << 4); // Clear OVR status
ADC1->ISR &= ~(1U << 3); // Clear EOS status
ADC1->CR &= ~ADC_CR_ADDIS; // Clear ADC disable command
}
//
void start_conversion(void) {
ADC1->ISR &= ~ADC_ISR_ADRDY; // Clear ADC ready status
ADC1->CR |= ADC_CR_ADEN; // Enable ADC
for (volatile int i = 0; i < 10000; i++); // Small delay
while (!(ADC1->ISR & ADC_ISR_ADRDY)) {}
for (volatile int i = 0; i < 10000; i++); // Small delay
ADC1->CR |= ADC_CR_ADSTART; // Start conversion
}
uint16_t ADC_Read(void) {
int timeout = 1000000;
while (!(ADC1->ISR & ADC_ISR_EOC)) { //if End of Conversion is reached
//if (--timeout == 0) {
// printf("ADC Timeout! \n\r");
// return 0;
//}
}
return (uint16_t)ADC1->DR;
}
int main(void)
{
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
usart1_rxtx_init();
PA4_PA5_ADC_Init();
adcclk_init();
adcinit();
while(1)
{
start_conversion();
sensor_value = ADC_Read();
printf("Sensor Value: %d \n", sensor_value);
//usart1_write('Y');
//printf("UART is working fine........\n\r");
for (volatile int i = 0; i < 100000; i++);
printf("UART is working fine........\n\r");
}
}
2025-04-01 3:35 PM
anybody?
2025-04-03 7:27 AM
Hello,
Better to start by using the HAL and inspire from the examples provided in STM32CubeH5 package:
https://github.com/STMicroelectronics/STM32CubeH5/tree/main/Projects/NUCLEO-H563ZI/Examples/ADC
Or simply start by using CubeMX to generate the code base on your configuration.
Then if you succeed with that you can inspire from the HAL implementation to develop your specific direct access to the registers.