cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F303 ADC1 calibration stuck

AAnth.1
Senior

Hi

I'm porting my STM32F103 code to the STM32F303, and noticed the significant difference in the ref manual regarding the ADC module. Being a beginner in STM32 MCUs, I'm struggling to get my calibration run correctly.

I feel like I am doing as I'm supposed to, but my calibration gets stuck in line 38. Debugging the register bits, ADCAL remains 1, even though it should be cleared by hardware once calibration is over.

Can anyone see what I'm doing wrong?

PS: If I don't run the calibration, my ADC works, but gives the wrong values, which is why I would like to run my calibration

Thank you.

/**
 * STM32F303CC ADC
 * Uses ADC1
 * Reads the temperature from the internal temp sensor.
 * Also, SWV is implemented. PB3 on MCU is used for TRACESWO
 * NOT DONE YET
 */
 
#include <stdint.h>
#include <stdio.h>
#include "stm32f3xx.h"
 
#define AVG_SLOPE	4.3	// mV per C
#define V25			1.43	// V
volatile uint32_t msTicks = 0;
 
int main(void)
{
	__NVIC_EnableIRQ(ADC1_2_IRQn);
	SystemCoreClockUpdate();
	SysTick_Config(SystemCoreClock / 1000);	// 1ms interrupt
 
	// Setup of ADC1
	uint16_t i = 0;
	RCC->AHBENR |= RCC_AHBENR_ADC12EN;
	for(;i<255;i++);
	i=0;
 
	ADC1->IER |= ADC_IER_EOCIE;
	ADC1->CR &= ~ADC_CR_ADVREGEN;
	ADC1->CR |= ADC_CR_ADVREGEN_0;
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;	// Enables SysTick
	while(msTicks<1);
	msTicks = 0;
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	// Disables SysTick until next delay call
 
	ADC1->CR |= ADC_CR_ADCAL;	//ADCALDIF = 0
	while(ADC1->CR && ADC_CR_ADCAL);	// Wait for calibration to be over
 
	ADC1->CFGR |= ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1;
	ADC1->SMPR1 |= ADC_SMPR1_SMP1_2;
	ADC12_COMMON->CCR |= ADC12_CCR_TSEN | ADC12_CCR_CKMODE_0;
	ADC1->SQR1 |= (16<<ADC_SQR1_SQ1_Pos);	// ADC channel 16 for Temp sensor
 
	ADC1->CR |= ADC_CR_ADEN;
	while(!(ADC1->ISR && ADC_ISR_ADRDY));
 
	ADC1->CR |= ADC_CR_ADSTART;
 
	// Enables Port A on APB2 bus to set PA1 to AF
	RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
	for(;i<255;i++);
	i=0;
	GPIOA->MODER |= GPIO_MODER_MODER1_1;
	GPIOA->AFR[0] |= (1<<GPIO_AFRL_AFRL1_Pos);
 
	// Enables TIM2 bus
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	for(;i<255;i++);
	i=0;
	TIM2->DIER |= TIM_DIER_UIE;
	TIM2->PSC = 7999;
	TIM2->ARR = 1000;
	TIM2->CCR2 = 500;
	TIM2->EGR |= TIM_EGR_CC2G;
	TIM2->CCER |= TIM_CCER_CC2E;
	TIM2->CCMR1 |= TIM_CCMR1_OC2PE | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
 
	TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_URS | TIM_CR1_CEN;
 
	/* Loop forever */
	for(;;);
}
 
void ADC1_2_IRQHandler(void)
{
	// Handles the IRQ of ADC1. EOC flag is cleared by reading data register
	static uint32_t temp = 0;
	static uint32_t temp_sensor = 0;
	temp = ADC1->DR;
	temp_sensor = (V25-temp*3.3/4095)/(AVG_SLOPE)*1000+25;
	printf("Temperature is: %lu\n", temp_sensor);
}
 
void SysTick_Handler(void)
{
	msTicks++;
}

1 ACCEPTED SOLUTION

Accepted Solutions

> ADC need be disable before calibration.

Yes, but only if it was enabled before, which it does not appear to be the case.

> ADC1->CR && ADC_CR_ADCAL

You want mask, not perform a logical AND, so

ADC1->CR & ADC_CR_ADCAL

Similarly below for

while(!(ADC1->ISR && ADC_ISR_ADRDY));

Also, make sure you have a valid clock for ADC, so you'll need to set ADCxx_CCR.CKMODE (and if set to 0, select proper clock in RCC) before you start calibration.

JW

View solution in original post

3 REPLIES 3
zzzzz
Senior

ADC need be disable before calibration. disable bit in CR need be set. Add the following code before line 37

ADC1->CR|=ADC_CR_ADDIS

ADC1->ISR=(ADC_FLAG_EOSMP | ADC_FLAG_RDY) // clear these two flags by write 1.

> ADC need be disable before calibration.

Yes, but only if it was enabled before, which it does not appear to be the case.

> ADC1->CR && ADC_CR_ADCAL

You want mask, not perform a logical AND, so

ADC1->CR & ADC_CR_ADCAL

Similarly below for

while(!(ADC1->ISR && ADC_ISR_ADRDY));

Also, make sure you have a valid clock for ADC, so you'll need to set ADCxx_CCR.CKMODE (and if set to 0, select proper clock in RCC) before you start calibration.

JW

AAnth.1
Senior

Hi guys,

thank you very much for your input. Jan's input brought me in the right direction. I'm performing the calibration BEFORE defining the ADC clock (line 41). So line 41 needs to be moved before the ADC calibration in order to activate the proper ADC clock.

Thank you both for your feedback. It now works as expected (after some small other corrections :))