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 * based on F3 file
5 *
6 * @date 14 July 2013
7 *
8 * LGPL License Terms @ref lgpl_license
9 */
10/*
11 * This file is part of the libopencm3 project.
12 *
13 * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
14 *
15 * This library is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with this library. If not, see <http://www.gnu.org/licenses/>.
27 */
28
31
32/**@{*/
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36/**
37 * @defgroup adc_api_opmode ADC Operation mode API
38 * @ingroup adc_file
39 *
40 * @brief ADC Result API
41 *
42 *@{*/
43
44/*---------------------------------------------------------------------------*/
45/** @brief ADC Enable Discontinuous Mode for Regular Conversions
46 *
47 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
48 */
49
51{
53}
54
55/*---------------------------------------------------------------------------*/
56/** @brief ADC Disable Discontinuous Mode for Regular Conversions
57 *
58 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
59 */
60
62{
63 ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
64}
65
66/*---------------------------------------------------------------------------*/
67/** ADC Set operation mode
68 *
69 * There are some operation modes, common for entire stm32 branch. In the text
70 * the braces are describing result to single trigger event. The trigger event
71 * is described by character T in the description. The ADC is configured to
72 * convert list of inputs [0, 1, 2, 3]. In Grouped modes, there is used group
73 * size of 2 conversions in the examples
74 *
75 * @li @c ADC_MODE_SEQUENTIAL: T(0) T(1) T(2) T(3)[EOSEQ] T(0) T(1) T(2) ...
76 *
77 * In this mode, after the trigger event a single channel is converted and the
78 * next channel in the list is prepared to convert on next trigger edge.
79 *
80 * @note This mode can be emulated by ADC_MODE_GROUPED with group size
81 * of 1.
82 *
83 * @li @c ADC_MODE_SCAN: T(0123)[EOSEQ] T(0123)[EOSEQ] T(0123)[EOSEQ]
84 *
85 * In this mode, after the trigger event, all channels will be converted once,
86 * storing results sequentially.
87 *
88 * @note The DMA must be configured properly for more than single channel to
89 * convert.
90 *
91 * @li @c ADC_MODE_SCAN_INFINITE: T(0123[EOSEQ]0123[EOSEQ]0123[EOSEQ]...)
92 *
93 * In this mode, after the trigger event, all channels from the list are
94 * converted. At the end of list, the conversion continues from the beginning.
95 *
96 * @note The DMA must be configured properly to operate in this mode.@par
97 *
98 * @li @c ADC_MODE_GROUPED: T(12) T(34)[EOSEQ] T(12) T(34)[EOSEQ] T(12)
99 *
100 * In this mode, after the trigger event, a specified group size of channels
101 * are converted. If the end of channel list occurs, the EOSEQ is generated
102 * and on the next trigger it wraps to the beginning.
103 *
104 * @note The DMA must be configured properly to operate on more than single
105 * channel conversion groups.
106 *
107 * @warning not all families supports all modes of operation of ADC.
108 *
109 */
110
111/*---------------------------------------------------------------------------*/
112/** @brief ADC Set conversion operation mode
113 *
114 * @note on SEQUENTIAL mode, the trigger event is necessary to start conversion.
115 *
116 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
117 * @param[in] opmode ADC operation mode
118 */
119
120void adc_set_operation_mode(uint32_t adc, enum adc_opmode opmode)
121{
122 switch (opmode) {
124 ADC_CFGR1(adc) &= ~ADC_CFGR1_CONT;
126 break;
127
128 case ADC_MODE_SCAN:
130 break;
131
133 ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
135 break;
136 }
137}
138
139/**@}*/
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143/**
144 * @defgroup adc_api_trigger ADC Trigger API
145 * @ingroup adc_file
146 *
147 * @brief ADC Trigger API
148 *
149 *@{*/
150
151/*---------------------------------------------------------------------------*/
152/** @brief ADC Enable an External Trigger for Regular Channels
153 *
154 * This enables an external trigger for set of defined regular channels, and
155 * sets the polarity of the trigger event: rising or falling edge or both. Note
156 * that if the trigger polarity is zero, triggering is disabled.
157 *
158 * @param[in] adc peripheral of choice (@ref adc_reg_base)
159 * @param[in] trigger external trigger @ref adc_cfgr1_extsel
160 * @param[in] polarity Trigger polarity @ref adc_cfgr1_exten
161 */
162void adc_enable_external_trigger_regular(uint32_t adc, uint32_t trigger,
163 uint32_t polarity)
164{
165 uint32_t reg = ADC_CFGR1(adc);
167 reg &= ~(ADC_CFGR1_EXTEN_MASK);
168 reg |= polarity | (trigger << ADC_CFGR1_EXTSEL_SHIFT);
169 ADC_CFGR1(adc) = reg;
170}
171
172/*---------------------------------------------------------------------------*/
173/** @brief ADC Disable an External Trigger for Regular Channels
174 *
175 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
176 */
177
179{
180 ADC_CFGR1(adc) &= ~ADC_CFGR1_EXTEN_MASK;
181}
182
183/**@}*/
184
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188/**
189 * @defgroup adc_api_interrupts ADC Interrupt configuration API
190 * @ingroup adc_file
191 *
192 * @brief ADC Interrupt configuration API
193 *
194 *@{*/
195
196/*---------------------------------------------------------------------------*/
197/** @brief ADC Enable Analog Watchdog Interrupt
198 *
199 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
200 */
201
203{
204 ADC_IER(adc) |= ADC_IER_AWD1IE;
205}
206
207/*---------------------------------------------------------------------------*/
208/** @brief ADC Disable Regular End-Of-Conversion Interrupt
209 *
210 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
211 */
212
214{
215 ADC_IER(adc) &= ~ADC_IER_AWD1IE;
216}
217
218/*---------------------------------------------------------------------------*/
219/** @brief ADC Read the Analog Watchdog Flag
220 *
221 * This flag is set when the converted voltage crosses the high or low
222 * thresholds.
223 *
224 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
225 * @returns bool true, if the signal is out of defined analog range.
226 */
227
228bool adc_get_watchdog_flag(uint32_t adc)
229{
230 return ADC_ISR(adc) & ADC_ISR_AWD1;
231}
232
233/*---------------------------------------------------------------------------*/
234/** @brief ADC Clear Analog Watchdog Flag
235 *
236 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
237 */
238
239void adc_clear_watchdog_flag(uint32_t adc)
240{
241 ADC_ISR(adc) = ADC_ISR_AWD1;
242}
243
244/*---------------------------------------------------------------------------*/
245/** @brief ADC Enable Regular End-Of-Conversion Sequence Interrupt
246 *
247 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
248 */
249
251{
252 ADC_IER(adc) |= ADC_IER_EOSEQIE;
253}
254
255/*---------------------------------------------------------------------------*/
256/** @brief ADC Disable Regular End-Of-Conversion Sequence Interrupt
257 *
258 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
259 */
260
262{
263 ADC_IER(adc) &= ~ADC_IER_EOSEQIE;
264}
265
266/*---------------------------------------------------------------------------*/
267/** @brief ADC Read the Regular End-Of-Conversion Sequence Flag
268 *
269 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
270 */
271
273{
274 return ADC_ISR(adc) & ADC_ISR_EOSEQ;
275}
276
277/*---------------------------------------------------------------------------*/
278/** @brief ADC Clear Regular End-Of-Conversion Sequence Flag
279 *
280 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
281 */
282
284{
285 ADC_ISR(adc) = ADC_ISR_EOSEQ;
286}
287
288/**@}*/
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292/**
293 * @defgroup adc_api_config ADC Basic configuration API
294 * @ingroup adc_file
295 *
296 * @brief ADC Basic configuration API
297 *
298 *@{*/
299
300/*---------------------------------------------------------------------------*/
301/** @brief ADC Set Clock Source
302 *
303 * The ADC clock taken from the many sources.
304 *
305 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
306 * @param[in] source Unsigned int32. Source (@ref adc_api_clksource)
307 */
308
309void adc_set_clk_source(uint32_t adc, uint32_t source)
310{
311 ADC_CFGR2(adc) = ((ADC_CFGR2(adc) & ~ADC_CFGR2_CKMODE) | source);
312}
313
314/*---------------------------------------------------------------------------*/
315/** @brief ADC Set a Regular Channel Conversion Sequence
316 *
317 * Define a sequence of channels to be converted as a regular group with a
318 * length from 1 to 18 channels. If this is called during conversion, the
319 * current conversion is reset and conversion begins again with the newly
320 * defined group.
321 *
322 * @warning This core doesn't support the random order of ADC conversions.
323 * The channel list must be ordered by channel number.
324 *
325 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
326 * @param[in] length Unsigned int8. Number of channels in the group.
327 * @param[in] channel Unsigned int8[]. Set of channels to convert, integers
328 * 0..18.
329 */
330
331void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
332{
333 uint32_t reg32 = 0;
334 uint8_t i = 0;
335 bool stepup = false, stepdn = false;
336
337 if (length == 0) {
338 ADC_CHSELR(adc) = 0;
339 return;
340 }
341
342 reg32 |= (1 << channel[0]);
343
344 for (i = 1; i < length; i++) {
345 reg32 |= (1 << channel[i]);
346 stepup |= channel[i-1] < channel[i];
347 stepdn |= channel[i-1] > channel[i];
348 }
349
350 /* Check, if the channel list is in order */
351 if (stepup && stepdn) {
353 }
354
355 /* Update the scan direction flag */
356 if (stepdn) {
358 } else {
359 ADC_CFGR1(adc) &= ~ADC_CFGR1_SCANDIR;
360 }
361
362 ADC_CHSELR(adc) = reg32;
363}
364
365/*---------------------------------------------------------------------------*/
366/** @brief ADC Set the Sample Time for All Channels
367 *
368 * The sampling time can be selected in ADC clock cycles from 1.5 to 239.5,
369 * same for all channels.
370 *
371 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
372 * @param[in] time Unsigned int8. Sampling time selection (@ref adc_api_smptime)
373 */
374
375void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time)
376{
377 ADC_SMPR(adc) = time & ADC_SMPR_SMP;
378}
379
380/*---------------------------------------------------------------------------*/
381/** @brief ADC Enable The VBat Sensor
382 *
383 * This enables the battery voltage measurements on channel 17.
384 */
385
387{
389}
390
391/*---------------------------------------------------------------------------*/
392/** @brief ADC Disable The VBat Sensor
393 *
394 * Disabling this will reduce power consumption from the battery voltage
395 * measurement.
396 */
397
399{
400 ADC_CCR(ADC1) &= ~ADC_CCR_VBATEN;
401}
402
403/*---------------------------------------------------------------------------*/
404/** @brief ADC Start the calibration procedure
405 * @deprecated Replaced by adc_calibrate/_async/is_calibrating
406 *
407 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
408 */
409
410void adc_calibrate_start(uint32_t adc)
411{
412 ADC_CR(adc) = ADC_CR_ADCAL;
413}
414
415/*---------------------------------------------------------------------------*/
416/** @brief ADC Wait to finish the ADC calibration procedure
417 * @deprecated Replaced by adc_calibrate/_async/is_calibrating
418 *
419 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
420 */
421
423{
424 while (ADC_CR(adc) & ADC_CR_ADCAL);
425}
426
427/**@}*/
428
429/*---------------------------------------------------------------------------*/
430/*---------------------------------------------------------------------------*/
431/**
432 * @defgroup adc_api_wdg ADC Analog watchdog API
433 * @ingroup adc_file
434 *
435 * @brief ADC analog watchdog API definitions.
436 *
437 * The analog watchdog allows the monitoring of an analog signal between two
438 * threshold levels. The thresholds must be preset. Analog watchdog is disabled
439 * by default.
440 *
441 * @warning Comparison is done before data alignment takes place, so the
442 * thresholds are left-aligned.
443 *
444 * Example 1: Enable watchdog checking on all channels
445 *
446 * @code
447 * // in configuration
448 * adc_enable_analog_watchdog_on_all_channels(ADC1);
449 * adc_set_watchdog_high_threshold(ADC1, 0xE00);
450 * adc_set_watchdog_low_threshold(ADC1, 0x200);
451 *
452 * // in the main application thread
453 * if (adc_get_watchdog_flag(ADC1)) {
454 * // the converted signal is out of AWD ranges
455 * adc_clear_watchdog_flag(ADC1);
456 * }
457 * @endcode
458 *
459 * Example 2: Enable watchdog checking on channel 5
460 *
461 * @code
462 * // in configuration
463 * adc_enable_analog_watchdog_on_selected_channel(ADC1,5);
464 * adc_set_watchdog_high_threshold(ADC1, 0xE00);
465 * adc_set_watchdog_low_threshold(ADC1, 0x200);
466 *
467 * // in the main application thread
468 * if (adc_get_watchdog_flag(ADC1)) {
469 * // the converted signal is out of AWD ranges
470 * adc_clear_watchdog_flag(ADC1);
471 * }
472 * @endcode
473 *@{*/
474
475/*---------------------------------------------------------------------------*/
476/** @brief ADC Enable Analog Watchdog for All Channels
477 *
478 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
479 */
480
482{
484 ADC_CFGR1(adc) &= ~ADC_CFGR1_AWD1SGL;
485}
486
487/*---------------------------------------------------------------------------*/
488/** @brief ADC Enable Analog Watchdog for a Selected Channel
489 *
490 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
491 * @param[in] chan Unsigned int8. ADC channel number @ref adc_api_channel
492 */
493
495{
496 ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_AWD1CH) |
498
500}
501
502/*---------------------------------------------------------------------------*/
503/** @brief ADC Disable Analog Watchdog
504 *
505 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
506 */
508{
509 ADC_CFGR1(adc) &= ~ADC_CFGR1_AWD1EN;
510}
511
512/*---------------------------------------------------------------------------*/
513/** @brief ADC Set Analog Watchdog Upper Threshold
514 *
515 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
516 * @param[in] threshold Upper threshold value
517 */
518
519void adc_set_watchdog_high_threshold(uint32_t adc, uint16_t threshold)
520{
521 ADC_TR1(adc) = (ADC_TR1(adc) & ~ADC_TR1_HT) | ADC_TR1_HT_VAL(threshold);
522}
523
524/*---------------------------------------------------------------------------*/
525/** @brief ADC Set Analog Watchdog Lower Threshold
526 *
527 * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
528 * @param[in] threshold Lower threshold value
529 */
530
531void adc_set_watchdog_low_threshold(uint32_t adc, uint16_t threshold)
532{
533 ADC_TR1(adc) = (ADC_TR1(adc) & ~ADC_TR1_LT) | ADC_TR1_LT_VAL(threshold);
534}
535
536/**@}*/
537
538/*---------------------------------------------------------------------------*/
539
540/**@}*/
#define ADC_SMPR(adc)
Definition: f0/adc.h:61
#define ADC_SMPR_SMP
Definition: f0/adc.h:102
#define ADC_CFGR1_EXTSEL_MASK
Definition: f0/adc.h:81
#define ADC_CFGR1_EXTSEL_SHIFT
Definition: f0/adc.h:80
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:375
void adc_disable_vbat_sensor(void)
ADC Disable The VBat Sensor.
Definition: adc.c:398
void adc_calibrate_wait_finish(uint32_t adc)
ADC Wait to finish the ADC calibration procedure.
Definition: adc.c:422
void adc_calibrate_start(uint32_t adc)
ADC Start the calibration procedure.
Definition: adc.c:410
void adc_enable_vbat_sensor(void)
ADC Enable The VBat Sensor.
Definition: adc.c:386
void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
ADC Set a Regular Channel Conversion Sequence.
Definition: adc.c:331
void adc_set_clk_source(uint32_t adc, uint32_t source)
ADC Set Clock Source.
Definition: adc.c:309
void adc_clear_watchdog_flag(uint32_t adc)
ADC Clear Analog Watchdog Flag.
Definition: adc.c:239
void adc_disable_eoc_sequence_interrupt(uint32_t adc)
ADC Disable Regular End-Of-Conversion Sequence Interrupt.
Definition: adc.c:261
void adc_disable_watchdog_interrupt(uint32_t adc)
ADC Disable Regular End-Of-Conversion Interrupt.
Definition: adc.c:213
void adc_clear_eoc_sequence_flag(uint32_t adc)
ADC Clear Regular End-Of-Conversion Sequence Flag.
Definition: adc.c:283
void adc_enable_watchdog_interrupt(uint32_t adc)
ADC Enable Analog Watchdog Interrupt.
Definition: adc.c:202
bool adc_get_eoc_sequence_flag(uint32_t adc)
ADC Read the Regular End-Of-Conversion Sequence Flag.
Definition: adc.c:272
bool adc_get_watchdog_flag(uint32_t adc)
ADC Read the Analog Watchdog Flag.
Definition: adc.c:228
void adc_enable_eoc_sequence_interrupt(uint32_t adc)
ADC Enable Regular End-Of-Conversion Sequence Interrupt.
Definition: adc.c:250
void adc_set_operation_mode(uint32_t adc, enum adc_opmode opmode)
ADC Set operation mode.
Definition: adc.c:120
void adc_disable_discontinuous_mode(uint32_t adc)
ADC Disable Discontinuous Mode for Regular Conversions.
Definition: adc.c:61
adc_opmode
Definition: f0/adc.h:163
void adc_enable_discontinuous_mode(uint32_t adc)
ADC Enable Discontinuous Mode for Regular Conversions.
Definition: adc.c:50
@ ADC_MODE_SCAN
Definition: f0/adc.h:165
@ ADC_MODE_SCAN_INFINITE
Definition: f0/adc.h:166
@ ADC_MODE_SEQUENTIAL
Definition: f0/adc.h:164
void adc_enable_external_trigger_regular(uint32_t adc, uint32_t trigger, uint32_t polarity)
ADC Enable an External Trigger for Regular Channels.
Definition: adc.c:162
void adc_disable_external_trigger_regular(uint32_t adc)
ADC Disable an External Trigger for Regular Channels.
Definition: adc.c:178
void adc_set_watchdog_high_threshold(uint32_t adc, uint16_t threshold)
ADC Set Analog Watchdog Upper Threshold.
Definition: adc.c:519
void adc_enable_analog_watchdog_on_all_channels(uint32_t adc)
ADC Enable Analog Watchdog for All Channels.
Definition: adc.c:481
void adc_enable_analog_watchdog_on_selected_channel(uint32_t adc, uint8_t chan)
ADC Enable Analog Watchdog for a Selected Channel.
Definition: adc.c:494
void adc_disable_analog_watchdog(uint32_t adc)
ADC Disable Analog Watchdog.
Definition: adc.c:507
void adc_set_watchdog_low_threshold(uint32_t adc, uint16_t threshold)
ADC Set Analog Watchdog Lower Threshold.
Definition: adc.c:531
#define ADC_CCR_VBATEN
VBATEN: Enable VBAT Channel.
#define ADC_CFGR1_SCANDIR
SCANDIR: Scan Sequence Direction: Upwards Scan (0), Downwards(1)
#define ADC_CFGR1_AWD1CH_VAL(x)
AWD1CH: Analog watchdog 1 channel selection.
#define ADC_CFGR1_CONT
CONT: Single / continuous conversion mode for regular conversions.
#define ADC_CFGR1_AWD1SGL
AWD1SGL: Enable the watchdog 1 on a single channel or on all channels.
#define ADC_CFGR1_EXTEN_MASK
#define ADC_CFGR1_AWD1EN
AWD1EN: Analog watchdog 1 enable on regular channels.
#define ADC_CFGR1_DISCEN
DISCEN: Discontinuous mode for regular channels.
#define ADC_CR_ADCAL
ADCAL: ADC calibration.
#define ADC_IER_AWD1IE
AWD1IE: Analog watchdog 1 interrupt enable.
Definition: adc_common_v2.h:90
#define ADC_IER_EOSEQIE
Definition: adc_common_v2.h:95
#define ADC_ISR_EOSEQ
Definition: adc_common_v2.h:75
#define ADC_ISR_AWD1
AWD1: Analog watchdog 1 flag.
Definition: adc_common_v2.h:70
#define ADC1
Definition: f0/adc.h:48
#define ADC_CR(adc)
Control Register.
Definition: adc_common_v2.h:46
#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_IER(adc)
Interrupt Enable Register.
Definition: adc_common_v2.h:44
#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_TR1(adc)
Watchdog Threshold Register 1.
Definition: adc_common_v2.h:54
#define ADC_TR1_HT_VAL(x)
TR1_HT: analog watchdog 1 threshold high.
#define ADC_TR1_LT_VAL(x)
TR1_LT: analog watchdog 1 threshold low.
#define cm3_assert_not_reached()
Check if unreachable code is reached.
Definition: assert.h:102