From 17ee40dafa93e28ea1e05fd739a5e793980c3cb0 Mon Sep 17 00:00:00 2001 From: crasbe Date: Tue, 19 Nov 2024 16:26:31 +0100 Subject: [PATCH] cpu/stm32l1: fix ADC initialization & resolution setting Co-authored-by: benpicco --- cpu/stm32/periph/adc_l1.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cpu/stm32/periph/adc_l1.c b/cpu/stm32/periph/adc_l1.c index d7c97003c4d8..eeab76d99753 100644 --- a/cpu/stm32/periph/adc_l1.c +++ b/cpu/stm32/periph/adc_l1.c @@ -131,8 +131,6 @@ int adc_init(adc_t line) ADC->CCR |= ADC_CCR_TSVREFE; } - /* enable the ADC module */ - ADC1->CR2 = ADC_CR2_ADON; /* turn off during idle phase*/ ADC1->CR1 = ADC_CR1_PDI; @@ -157,12 +155,17 @@ int32_t adc_sample(adc_t line, adc_res_t res) /* lock and power on the ADC device */ prep(); - /* set resolution, conversion channel and single read */ - ADC1->CR1 |= res & ADC_CR1_RES; + /* mask and set resolution, conversion channel and single read */ + ADC1->CR1 = (ADC1->CR1 & ~ADC_CR1_RES) | (res & ADC_CR1_RES); ADC1->SQR1 &= ~ADC_SQR1_L; ADC1->SQR5 = adc_config[line].chan; - /* wait for regulat channel to be ready*/ + /* only set ADON when ADONS bit is cleared (ADC not ready) */ + if (!(ADC1->SR & ADC_SR_ADONS)) { + ADC1->CR2 |= ADC_CR2_ADON; + } + + /* wait for regular channel to be ready*/ while (!(ADC1->SR & ADC_SR_RCNR)) {} /* start conversion and wait for results */ ADC1->CR2 |= ADC_CR2_SWSTART; @@ -171,6 +174,10 @@ int32_t adc_sample(adc_t line, adc_res_t res) sample = (int)ADC1->DR; ADC1 -> SR &= ~ADC_SR_STRT; + /* wait for ADC to become ready before disabling it */ + while (!(ADC1->SR & ADC_SR_ADONS)) {} + ADC1->CR2 &= ~ADC_CR2_ADON; + /* power off and unlock device again */ done();