2021-06-22 07:09 PM
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;
}
2021-07-12 04:21 AM
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.