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");
}
}