2 * Copyright © 2020 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_adc_stm32l0.h>
25 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN);
28 stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) | /* analog watchdog channel 0 */
29 (0 << STM_ADC_CFGR1_AWDEN) | /* Disable analog watchdog */
30 (0 << STM_ADC_CFGR1_AWDSGL) | /* analog watchdog on all channels */
31 (0 << STM_ADC_CFGR1_DISCEN) | /* Not discontinuous mode. All channels converted with one trigger */
32 (0 << STM_ADC_CFGR1_AUTOOFF) | /* Leave ADC running */
33 (1 << STM_ADC_CFGR1_WAIT) | /* Wait for data to be read before next conversion */
34 (0 << STM_ADC_CFGR1_CONT) | /* only one set of conversions per trigger */
35 (1 << STM_ADC_CFGR1_OVRMOD) | /* overwrite on overrun */
36 (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) | /* SW trigger */
37 (0 << STM_ADC_CFGR1_ALIGN) | /* Align to LSB */
38 (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | /* 12 bit resolution */
39 (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) | /* scan 0 .. n */
40 (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */
41 (0 << STM_ADC_CFGR1_DMAEN)); /* disable DMA */
44 stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE;
46 /* Shortest sample time */
47 stm_adc.smpr = STM_ADC_SMPR_SMP_71_5 << STM_ADC_SMPR_SMP;
49 #define AO_ADC_LFMEN (AO_SYSCLK < 3500000)
51 stm_adc.ccr = ((AO_ADC_LFMEN << STM_ADC_CCR_LFMEN) |
52 (0 << STM_ADC_CCR_VLCDEN) |
53 (0 << STM_ADC_CCR_TSEN) |
54 (0 << STM_ADC_CCR_VREFEN));
56 /* Calibrate. This also enables the ADC vreg */
57 stm_adc.cr |= (1UL << STM_ADC_CR_ADCAL);
58 while ((stm_adc.cr & (1UL << STM_ADC_CR_ADCAL)) != 0)
62 stm_adc.isr = (1 << STM_ADC_ISR_ADRDY); /* Clear ADRDY bit */
63 stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
64 while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)
72 stm_adc.cr |= (1 << STM_ADC_CR_ADDIS);
73 while ((stm_adc.cr & (1 << STM_ADC_CR_ADEN)) != 0)
77 stm_adc.isr = (1 << STM_ADC_ISR_ADRDY);
79 /* Disable ADC vreg */
80 stm_adc.cr &= ~(1UL << STM_ADC_CR_ADVREGEN);
82 /* Disable ADC clocks */
83 stm_rcc.apb2enr &= ~(1UL << STM_RCC_APB2ENR_ADCEN);
87 ao_adc_read_vref(void)
93 /* Turn on voltage reference */
94 stm_adc.ccr |= (1 << STM_ADC_CCR_VREFEN);
97 stm_adc.chselr = (1 << STM_ADC_CHSEL_VREF);
99 /* Start conversion */
100 stm_adc.cr |= (1 << STM_ADC_CR_ADSTART);
102 /* Wait for conversion complete */
103 while ((stm_adc.isr & (1 << STM_ADC_ISR_EOC)) == 0)
107 value = (uint16_t) stm_adc.dr;