libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
adc.c
Go to the documentation of this file.
1/** @addtogroup adc_file ADC peripheral API
2 * @ingroup peripheral_apis
3 *
4 * @author @htmlonly &copy; @endhtmlonly 2019 Guillaume Revaillot <g.revaillot@gmail.com>
5 *
6 * @date 10 January 2019
7 *
8 * LGPL License Terms @ref lgpl_license
9 */
10
11/*
12 * This file is part of the libopencm3 project.
13 *
14 * This library is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this library. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28/**@{*/
29
32
33/** @brief ADC Set Clock Source
34 *
35 * @param[in] adc ADC base address (@ref adc_reg_base)
36 * @param[in] source Source (@ref adc_cfgr2_ckmode)
37 */
38void adc_set_clk_source(uint32_t adc, uint32_t source)
39{
40 uint32_t reg32 = ADC_CFGR2(adc);
41
43 ADC_CFGR2(adc) = (reg32 | (source << ADC_CFGR2_CKMODE_SHIFT));
44}
45
46/** @brief ADC Set Clock Prescale
47 *
48 * @param[in] adc ADC base address (@ref adc_reg_base)
49 * @param[in] prescale Prescale value for ADC Async Clock (@ref adc_ccr_presc)
50*/
51void adc_set_clk_prescale(uint32_t adc, uint32_t prescale)
52{
53 uint32_t reg32 = ADC_CCR(adc);
54
56 ADC_CCR(adc) = (reg32 | (prescale << ADC_CCR_PRESC_SHIFT));
57}
58
59/** @brief ADC Set the Sample Time for All Channels
60 *
61 * Setup all ADC channels to use a single ADC sampling time.
62 *
63 * @param[in] adc ADC base address (@ref adc_reg_base)
64 * @param[in] time ADC Sampling Time (@ref adc_api_smptime)
65 */
66void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time)
67{
68 uint32_t reg32;
69
70 reg32 = ADC_SMPR1(adc);
71 /* set all channels on ADC_SMPR_SMPSEL_SMP1 first @ref adc_smpr_smpsel sample time selection, and clear its value */
73 /* setup ADC_SMPR_SMPSEL_SMP1 sample time */
74 reg32 |= (time << ADC_SMPR_SMP1_SHIFT);
75 ADC_SMPR1(adc) = reg32;
76}
77
78/** @brief ADC Set the Sample Time Selection for a Single Channel
79 *
80 * @param[in] adc ADC base address (@ref adc_reg_base)
81 * @param[in] channel ADC Channel (0..18 or @ref adc_channel)
82 * @param[in] selection Sampling time selection (@ref adc_smpr_smpsel)
83*/
84void adc_set_channel_sample_time_selection(uint32_t adc, uint8_t channel, uint8_t selection)
85{
86 uint32_t reg32;
87
88 reg32 = ADC_SMPR1(adc);
90 reg32 |= (selection << ADC_SMPR_SMPSEL_CHANNEL_SHIFT(channel));
91 ADC_SMPR1(adc) = reg32;
92}
93
94/** @brief ADC Set the Sample Time for Given Selection.
95 *
96 * @param[in] adc ADC base address (@ref adc_reg_base)
97 * @param[in] selection Sampling Time Selection (@ref adc_smpr_smpsel)
98 * @param[in] time Sampling Time (@ref adc_smpr_smp)
99*/
100void adc_set_selection_sample_time(uint32_t adc, uint8_t selection, uint8_t time)
101{
102 uint32_t reg32;
103
104 reg32 = ADC_SMPR1(adc);
105 switch (selection) {
108 reg32 |= (time << ADC_SMPR_SMP1_SHIFT);
109 break;
112 reg32 |= (time << ADC_SMPR_SMP2_SHIFT);
113 break;
114 }
115 ADC_SMPR1(adc) = reg32;
116}
117
118/** @brief ADC Set a Regular Channel Conversion Sequence
119 *
120 * Define a simple sequence of channels to be converted.
121 * ADCSTART must be de-asserted before sequence setup.
122 *
123 * @param[in] adc ADC base address (@ref adc_reg_base)
124 * @param[in] length Number of channels in the group, range 0..18
125 * @param[in] channel Set of channels in sequence (0..18 or @ref adc_channel)
126 */
127void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
128{
129 uint32_t reg32 = 0;
130 bool stepup = false, stepdn = false;
131
132 if (length > ADC_CHSELR_MAX_CHANNELS) {
133 return;
134 }
135
136 if (length == 0) {
137 ADC_CHSELR(adc) = 0;
138 return;
139 }
140
141 reg32 |= (1 << channel[0]);
142
143 for (uint8_t i = 1; i < length; i++) {
144 reg32 |= ADC_CHSELR_CHSEL(channel[i]);
145 stepup |= channel[i-1] < channel[i];
146 stepdn |= channel[i-1] > channel[i];
147 }
148
149 /* Check if the channel list is in order */
150 if (stepup && stepdn) {
152 }
153
154 /* Each modification to ADC_CFGR1's SCANDIR or CHSELRMOD bits or
155 ADC_CHSELR register must be done after previous configuration change
156 being properly applied: We have to clear ccrdy bit before and poll for
157 it being assert back after, before going on. We also need to wait for
158 configuration applied before starting conversion, or start will be
159 ignored. */
160
161 /* Setup scandir, if needed, waiting for configuration be applied.. */
162 if (stepdn && (!(ADC_CFGR1(adc) & ADC_CFGR1_SCANDIR))) {
163 ADC_ISR(adc) = ADC_ISR_CCRDY;
165 while (!(ADC_ISR(adc) & ADC_ISR_CCRDY));
166 } else if (stepup && ((ADC_CFGR1(adc) & ADC_CFGR1_SCANDIR))) {
167 ADC_ISR(adc) = ADC_ISR_CCRDY;
168 ADC_CFGR1(adc) &= ~ADC_CFGR1_SCANDIR;
169 while (!(ADC_ISR(adc) & ADC_ISR_CCRDY));
170 }
171
172 /* Setup ADC in simple, not configurable, mode, if needed. */
173 if ((ADC_CFGR1(adc) & ADC_CFGR1_CHSELRMOD)) {
174 ADC_ISR(adc) = ADC_ISR_CCRDY;
175 ADC_CFGR1(adc) &= ~ADC_CFGR1_CHSELRMOD;
176 while (!(ADC_ISR(adc) & ADC_ISR_CCRDY));
177 }
178
179 if (ADC_CHSELR(adc) != reg32) {
180 ADC_ISR(adc) = ADC_ISR_CCRDY;
181 ADC_CHSELR(adc) = reg32;
182 while (!(ADC_ISR(adc) & ADC_ISR_CCRDY));
183 }
184}
185
186/**
187 * @brief Enable the ADC Voltage regulator
188 *
189 * @param[in] adc ADC base address (@ref adc_reg_base)
190 */
191void adc_enable_regulator(uint32_t adc)
192{
193 ADC_CR(adc) |= ADC_CR_ADVREGEN;
194}
195
196/**
197 * @brief Disable the ADC Voltage regulator
198 *
199 * @param[in] adc ADC base address (@ref adc_reg_base)
200 */
201void adc_disable_regulator(uint32_t adc)
202{
203 ADC_CR(adc) &= ~ADC_CR_ADVREGEN;
204}
205
206/**@}*/
#define ADC_CCR_PRESC_SHIFT
Definition: g0/adc.h:91
#define ADC_CCR_PRESC_MASK
Definition: g0/adc.h:90
#define ADC_CFGR1_SCANDIR
SCANDIR: Scan Sequence Direction: Upwards Scan (0), Downwards(1)
#define ADC_CFGR1_CHSELRMOD
CHSELRMOD: Mode Selection of the ADC_CHSELR register.
Definition: g0/adc.h:141
#define ADC_CFGR2_CKMODE_MASK
Definition: g0/adc.h:149
#define ADC_CFGR2_CKMODE_SHIFT
Definition: g0/adc.h:148
#define ADC_CHSELR_MAX_CHANNELS
ADC_CHSELR_MAX_CHANNELS Maximum number of channel in regular sequence.
Definition: g0/adc.h:257
#define ADC_CHSELR_CHSEL(x)
#define ADC_CR_ADVREGEN
ADVREGEN: Voltage regulator enable bit.
Definition: g0/adc.h:114
void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time)
ADC Set the Sample Time for All Channels.
Definition: adc.c:66
void adc_disable_regulator(uint32_t adc)
Disable the ADC Voltage regulator.
Definition: adc.c:201
void adc_set_clk_prescale(uint32_t adc, uint32_t prescale)
ADC Set Clock Prescale.
Definition: adc.c:51
void adc_set_selection_sample_time(uint32_t adc, uint8_t selection, uint8_t time)
ADC Set the Sample Time for Given Selection.
Definition: adc.c:100
void adc_enable_regulator(uint32_t adc)
Enable the ADC Voltage regulator.
Definition: adc.c:191
void adc_set_channel_sample_time_selection(uint32_t adc, uint8_t channel, uint8_t selection)
ADC Set the Sample Time Selection for a Single Channel.
Definition: adc.c:84
void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
ADC Set a Regular Channel Conversion Sequence.
Definition: adc.c:127
void adc_set_clk_source(uint32_t adc, uint32_t source)
ADC Set Clock Source.
Definition: adc.c:38
#define ADC_ISR_CCRDY
CCRDY: Channel Configuration Ready flag.
Definition: g0/adc.h:75
#define ADC_CR(adc)
Control Register.
Definition: adc_common_v2.h:46
#define ADC_SMPR1(adc)
Sample Time Register 1.
Definition: adc_common_v2.h:52
#define ADC_ISR(adc)
ADC interrupt and status register.
Definition: adc_common_v2.h:42
#define ADC_CCR(adc)
Common Configuration register.
Definition: adc_common_v2.h:60
#define ADC_CHSELR(adc)
Channel Select Register.
#define ADC_CFGR2(adc)
Configuration Register 2.
Definition: adc_common_v2.h:50
#define ADC_CFGR1(adc)
Configuration Register 1.
Definition: adc_common_v2.h:48
#define ADC_SMPR_SMPSEL_SMP1
Definition: g0/adc.h:200
#define ADC_SMPR_SMPSEL_SMP2
Definition: g0/adc.h:201
#define ADC_SMPR_SMPSEL_CHANNEL_SHIFT(channel)
Definition: g0/adc.h:196
#define ADC_SMPR_SMPSEL_MASK
Definition: g0/adc.h:195
#define ADC_SMPR_SMP1_MASK
Definition: g0/adc.h:206
#define ADC_SMPR_SMP1_SHIFT
SMP1 ADC Sample Time #1 selection.
Definition: g0/adc.h:205
#define ADC_SMPR_SMPSEL_CHANNEL_MASK
Definition: g0/adc.h:197
#define ADC_SMPR_SMPSEL_SHIFT
Definition: g0/adc.h:194
#define ADC_SMPR_SMP2_MASK
Definition: g0/adc.h:210
#define ADC_SMPR_SMP2_SHIFT
SMP1 ADC Sample Time #2 selection.
Definition: g0/adc.h:209
#define cm3_assert_not_reached()
Check if unreachable code is reached.
Definition: assert.h:102