cancel
Showing results for 
Search instead for 
Did you mean: 

Reading in ADC on STM32H753

JWolf.3
Associate II

I am trying to run a simple program that can read in data from a potentiometer through ADC. The pot is connected to PF10 or A5 on the nucleo board. My code is below:

When I run this it prints "Value is: 32767" once then stops. Because I am in continuous mode, it should keep printing a value. Also, even if I turn the pot and rerun the code, it always prints 32767 which makes me believe that value is not correct.

Any help is greatly appreciated! I am mostly unsure about the clock setup but it could be some other dumb mistake.

#include "stm32h7xx.h"
#include "printUSART.h"
 
#define ADC_ISR_LDORDY 0x1 << 12U
 
// ADC3_INP6 on PF10
// ADC3 on AHB4
 
/*	Function prototypes	*/
int ADC3_Calibration(void);
void ADC3_Init(void);
void ADC3_IRQHandler(void);
 
int main(void){
 
	USART3_Init();
 
//	printf("\nCalibration factor is: %d", (int)ADC3_Calibration());
	ADC3_Init();
 
	ADC3->IER |= ADC_IER_EOCIE;							// enable end of conversion interupts
	NVIC_EnableIRQ(ADC3_IRQn);							// enable on the NVIC
 
	ADC3->PCSEL |= ADC_PCSEL_PCSEL_6;					// preselect channel
	ADC3->SQR1 |= ADC_SQR1_SQ1_1 | ADC_SQR1_SQ1_2;		// select channel 6 as first in sequence
	ADC3->SMPR1 |= ADC_SMPR1_SMP6_0 | ADC_SMPR1_SMP6_1 | ADC_SMPR1_SMP6_2; // max sampling speed
	ADC3->CFGR |= ADC_CFGR_CONT;						// continuous mode
	ADC3->CR |= ADC_CR_ADSTART;							// start conversions
 
	while(1){
 
	}
}
 
void ADC3_IRQHandler(void){
	if(ADC3->ISR & ADC_ISR_EOC){						// if EOC flag is set
		printf("\nValue is: %d", (int)ADC3->DR);		// print value in data register
	}
}
 
void ADC3_Init(void){
	ADC3->CR &= ~ADC_CR_ADEN;							// ensure that the ADC is off
	RCC->AHB4ENR |= RCC_AHB4ENR_GPIOFEN;				// enable clock for port F
	RCC->AHB4ENR |= RCC_AHB4ENR_ADC3EN;					// enable clock for ADC3
	ADC3_COMMON->CCR |= ADC_CCR_CKMODE_0;				// (25.4.3) choosing the clock source for ADC
 
	GPIOF->MODER = GPIO_MODER_MODE10_0 | GPIO_MODER_MODE10_1;		// setting PF10 as alternate function
 
	ADC3->CR &= ~ADC_CR_DEEPPWD;						// (25.4.6) takes ADC out of deep power down mode
 
	ADC3->CR |= ADC_CR_ADVREGEN;						// (25.4.6) enable the voltage regulator
	while(!(ADC3->ISR & ADC_ISR_LDORDY)){}				// (25.4.6) waits for reg to startup
 
	/*	Turning on the ADC (25.4.9)	*/
	ADC3->ISR |= ADC_ISR_ADRDY;							// clear the ADRDY bit
	ADC3->CR |= ADC_CR_ADEN;							// enable the ADC
	while(!(ADC3->ISR & ADC_ISR_ADRDY)){}				// wait for ADC to be ready
	ADC3->CR &= ~ADC_CR_ADSTART;
}
 
int ADC3_Calibration(void){
	/*	Calibrating the ADC	*/
	ADC3->CR &= ~ADC_CR_ADEN;							// ensure that the ADC is off
	ADC3->CR |= ADC_CR_ADCAL;							// start calibration
	while(ADC3->CR & ADC_CR_ADCAL){}					// wait until ADCAL is 0 and cal is complete
 
	printf("\nCalibration is complete");
	return (int)ADC3->CALFACT;
}

1 REPLY 1
houssemeddine
Associate II

Hello @JWolf.3​ 

I can see that you are using this define:

#define ADC_ISR_LDORDY 0x1 << 12U

To check the ISR register:

while(!(ADC3->ISR & ADC_ISR_LDORDY)){}				// (25.4.6) waits for reg to startup

Actually there is no "bit 12" in the ADC ISR register, try to remove the mentioned check from your code.

If this doesn't resolve your issue, try to activate the overrun interrupt by adding "ADC_IER_OVRIE" in the L.21:

ADC3->IER |= ADC_IER_EOCIE | ADC_IER_OVRIE;	

Hope my answer helped you.