cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot cofigure the ADC on STM32L431KB. ADEN always set to 1.

NMill.3
Associate II

Hi,

I am having trouble configuring the ADC on my STM32L431KB. The calibration procedure appears to go well until it gets to the step where the program waits for the calibration to finish. It is never able to finish. I think the problem may be related to the fact that ADC1_CR_ADEN is always set 1, and I am unable to change it to 0. Does anyone know why this might be happening?

Thanks,

1 ACCEPTED SOLUTION

Accepted Solutions

Do you call this function repeatedly, or only after reset?

> // Ensure that ADEN = 0

> ADC1->CR &= ~ADC_CR_ADEN;

You can't switch off ADEN by writing 0 to it, it's a rs bit. If you need to switch off ADEN, you have to write 1 to ADDIS (but do it ONLY if ADEN == 1).

Read carefully ADC_CR bits description. It's tricky, but mostly the description is there.

JW

View solution in original post

4 REPLIES 4

Post code.

JW

NMill.3
Associate II
retval_t adc_init(){
 
	// Enable clock to ADC peripheral
	RCC->AHB2ENR |= RCC_AHB2ENR_ADCEN;
 
	// Ensure that ADEN = 0
	ADC1->CR &= ~ADC_CR_ADEN;
 
	// Configure ADC pins PB0
	pinCtrl_config_T BATT_cfg = {.base = ADC_BATT_PORT, .pin = ADC_BATT_PIN, .mode = pinMode_disabledOrAnalog};
	pinCtrl_pinInit(BATT_cfg);
 
	// Configure ADC registers
	ADC1->CFGR |= ADC_CFGR_CONT | ADC_CFGR_OVRMOD;			// Set ADC for continuous conversion, overwrite data during overrun
	ADC1_COMMON->CCR |= 0b01 << ADC_CCR_CKMODE_Pos;			// Set ADC to use HCLK
	ADC1->SQR1 = 15 << ADC_SQR1_SQ1_Pos;	// Puts the desired channel in the sample queue, only sample 1 channel
 
	// Configure ADC Sample time to 640 ADC clock (8uS)
	ADC1->SMPR2 |= 0b111 << ADC_SMPR2_SMP15_Pos;
	ADC1->SMPR1 |= 0b111 << ADC_SMPR1_SMP8_Pos;
 
	// Exit ADC deep power down mode
	ADC1->CR &= ~ADC_CR_DEEPPWD;
 
	// Enable ADC internal voltage regulator
	ADC1->CR |= ADC_CR_ADVREGEN;
	// Wait for ADC internal voltage regulator to start-up
	_delay_ms(1);
 
	// Start ADC internal calibration procedure
	ADC1->CR &= ~ADC_CR_ADCALDIF;	// Set calibration mode for single ended input
	_delay_ms(10);
	ADC1->CR |= ADC_CR_ADCAL;		// Start Calibration
	_delay_ms(10);
	// Wait calibration is done
	if(checkRetry(&ADC1->CR, ADC_CR_ADCAL_Msk, 0, ADC_CAL_MAXRETRY) == RET_ERROR){
		return RET_ERROR;
	}
 
	// Enable ADC
	ADC1->ISR |= ADC_ISR_ADRDY; //Clear the ADRDY bit in the ADC_ISR register by writing ‘1’.
	ADC1->CR |= ADC_CR_ADEN;
 
	// Wait until ADRDY is set to 1, which indicates that the ADC has finished startup
	if(checkRetry(&ADC1->ISR, ADC_ISR_ADRDY_Msk, ADC_ISR_ADRDY, ADC_START_MAXRETRY) == RET_ERROR){
		return RET_ERROR;
	}
 
	// Start regular conversion
	ADC1->CR |= ADC_CR_ADSTART;
 
	return RET_SUCCESS;
}

Do you call this function repeatedly, or only after reset?

> // Ensure that ADEN = 0

> ADC1->CR &= ~ADC_CR_ADEN;

You can't switch off ADEN by writing 0 to it, it's a rs bit. If you need to switch off ADEN, you have to write 1 to ADDIS (but do it ONLY if ADEN == 1).

Read carefully ADC_CR bits description. It's tricky, but mostly the description is there.

JW

That worked! I set ADDEN to 1 and now the calibration works. Thank you.