libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
dac_common_all.c
Go to the documentation of this file.
1/** @addtogroup dac_file DAC peripheral API
2 * @ingroup peripheral_apis
3 * @brief Digital to Analog Converter
4
5@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
6@author @htmlonly &copy; @endhtmlonly 2020 Ben Brewer <ben.brewer@codethink.co.uk>
7
8This library supports the Digital to Analog Conversion System in the
9STM32 series of ARM Cortex Microcontrollers by ST Microelectronics.
10
11The DAC peripheral found on many of the devices in the STM32 lineup,
12sometimes with only one channel, but normally with two channels.
13
14Two DAC channels are available, however unlike the ADC channels these
15are separate DAC devices controlled by the same register block.
16
17The DAC is on APB1. Its clock must be enabled in RCC and depending on
18specific family, the GPIO
19ports set to alternate function output before it can be used.
20On most families, the GPIO pins should be configured to Analog IN to
21avoid parasitic consumption.
22The digital output driver is disabled so the output driver mode
23(push-pull/open drain) is arbitrary.
24
25The DAC has a holding (buffer) register and an output register from
26which the analog output is derived. The holding register must be
27loaded first. If triggering is enabled the output register is loaded
28from the holding register after a trigger occurs. If triggering is
29not enabled the holding register contents are transferred directly
30to the output register.
31
32@note To avoid nonlinearities, do not allow outputs to range close
33to zero or V_analog.
34
35@section dac_api_dual Dual Channel Conversion
36
37There are dual modes in which both DACs are used to output data
38simultaneously or independently on both channels. The data must be
39presented according to the formats described in the datasheets. A
40convenience function @ref dac_load_data_buffer_dual is provided
41for software controlled use.
42
43A variety of modes are available depending on whether independent
44or simultaneous output is desired, and whether waveforms are to be
45superimposed. Refer to the datasheets.
46
47If DMA is used, only enable it for one of the channels. The DMA
48requests will then serve data in dual format to the data register
49dedicated to dual mode. The data will then be split and loaded to the
50appropriate DAC following the next trigger. There are three registers
51available, one for each of the formats: 12 bit right-aligned, 12 bit
52left-aligned and 8 bit right-aligned. The desired format is determined
53by specifying the appropriate register to the DMA controller.
54
55@section dac_api_basic_ex Basic DAC handling API.
56
57Set the DAC's GPIO port to Analog IN. Enable the
58DAC clock. Enable the DAC, set a trigger source and load the buffer
59with the first value. After the DAC is triggered, load the buffer with
60the next value. This example uses software triggering and added noise.
61The trigger and further buffer load calls are made when data is to be
62sent out.
63
64@code
65 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
66 GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4);
67 rcc_periph_clock_enable(RCC_DAC);
68 dac_disable(DAC1, DAC_CHANNEL1);
69 dac_set_waveform_characteristics(DAC1, DAC_CHANNEL1, DAC_CR_MAMP1_8);
70 dac_set_waveform_generation(DAC1, DAC_CHANNEL1, DAC_CR_WAVE1_NOISE);
71 dac_enable(DAC1, DAC_CHANNEL1);
72 dac_set_trigger_source(DAC1, DAC_CR_TSEL1_SW);
73 dac_load_data_buffer_single(DAC1, 0, DAC_ALIGN_RIGHT12, DAC_CHANNEL1);
74 ....
75 dac_software_trigger(DAC1, DAC_CHANNEL1);
76 dac_load_data_buffer_single(DAC1, value,
77 DAC_ALIGN_RIGHT12, DAC_CHANNEL1);
78@endcode
79
80@section dac_api_dma_ex Simultaneous Dual DAC with DMA.
81
82This example in part sets up the DAC channel 1 DMA (DMA2 channel 3) to read
8316 bit data from memory into the right-aligned 8 bit dual register DAC_DHR8RD.
84Both DAC channels are enabled, and both triggers are set to the same timer
852 input as required for simultaneous operation. DMA is enabled for DAC channel
861 only to ensure that only one DMA request is generated.
87
88@code
89 dma_set_memory_size(DMA2, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
90 dma_set_peripheral_size(DMA2, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
91 dma_set_read_from_memory(DMA2, DMA_CHANNEL3);
92 dma_set_peripheral_address(DMA2, DMA_CHANNEL3,(uint32_t) &DAC_DHR8RD);
93 dma_enable_channel(DMA2, DMA_CHANNEL3);
94 ...
95 dac_trigger_enable(DAC1, DAC_CHANNEL_BOTH);
96 dac_set_trigger_source(DAC1, DAC_CR_TSEL1_T2 | DAC_CR_TSEL2_T2);
97 dac_dma_enable(DAC1, DAC_CHANNEL1);
98 dac_enable(DAC1, DAC_CHANNEL_BOTH);
99@endcode
100
101LGPL License Terms @ref lgpl_license
102 */
103
104/*
105 * This file is part of the libopencm3 project.
106 *
107 * Copyright (C) 2012 Ken Sarkies
108 * Copyright (C) 2020 Ben Brewer
109 *
110 * This library is free software: you can redistribute it and/or modify
111 * it under the terms of the GNU Lesser General Public License as published by
112 * the Free Software Foundation, either version 3 of the License, or
113 * (at your option) any later version.
114 *
115 * This library is distributed in the hope that it will be useful,
116 * but WITHOUT ANY WARRANTY; without even the implied warranty of
117 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118 * GNU Lesser General Public License for more details.
119 *
120 * You should have received a copy of the GNU Lesser General Public License
121 * along with this library. If not, see <http://www.gnu.org/licenses/>.
122 */
123
124/**@{*/
125
126#include <libopencm3/stm32/dac.h>
127
128/** @brief DAC Channel Enable.
129
130Enable a digital to analog converter channel. After setting this enable, the
131DAC requires a t<sub>wakeup</sub> time typically around 10 microseconds before
132it actually wakes up.
133
134@param[in] dac the base address of the DAC @ref dac_reg_base
135@param[in] channel with DAC mask. @ref dac_channel_id
136*/
137void dac_enable(uint32_t dac, int channel)
138{
139 switch (channel) {
140 case DAC_CHANNEL1:
141 DAC_CR(dac) |= DAC_CR_EN1;
142 break;
143 case DAC_CHANNEL2:
144 DAC_CR(dac) |= DAC_CR_EN2;
145 break;
146 case DAC_CHANNEL_BOTH:
147 DAC_CR(dac) |= (DAC_CR_EN1 | DAC_CR_EN2);
148 break;
149 }
150}
151
152/** @brief DAC Channel Disable.
153
154Disable a digital to analog converter channel.
155
156@param[in] dac the base address of the DAC @ref dac_reg_base
157@param[in] channel with DAC mask @ref dac_channel_id
158*/
159void dac_disable(uint32_t dac, int channel)
160{
161 switch (channel) {
162 case DAC_CHANNEL1:
163 DAC_CR(dac) &= ~DAC_CR_EN1;
164 break;
165 case DAC_CHANNEL2:
166 DAC_CR(dac) &= ~DAC_CR_EN2;
167 break;
168 case DAC_CHANNEL_BOTH:
169 DAC_CR(dac) &= ~(DAC_CR_EN1 | DAC_CR_EN2);
170 break;
171 default:
172 break;
173 }
174}
175
176/** @brief DAC Channel DMA Enable.
177
178Enable a digital to analog converter channel DMA mode (connected to DMA2 channel
1793 for DAC channel 1 and DMA2 channel 4 for DAC channel 2). A DMA request is
180generated following an external trigger.
181
182@param[in] dac the base address of the DAC. @ref dac_reg_base
183@param[in] channel with DAC mask. @ref dac_channel_id
184*/
185void dac_dma_enable(uint32_t dac, int channel)
186{
187 switch (channel) {
188 case DAC_CHANNEL1:
189 DAC_CR(dac) |= DAC_CR_DMAEN1;
190 break;
191 case DAC_CHANNEL2:
192 DAC_CR(dac) |= DAC_CR_DMAEN2;
193 break;
194 case DAC_CHANNEL_BOTH:
196 break;
197 default:
198 break;
199 }
200}
201
202/** @brief DAC Channel DMA Disable.
203
204Disable a digital to analog converter channel DMA mode.
205
206@param[in] dac the base address of the DAC. @ref dac_reg_base
207@param[in] channel with DAC mask. @ref dac_channel_id
208*/
209void dac_dma_disable(uint32_t dac, int channel)
210{
211 switch (channel) {
212 case DAC_CHANNEL1:
213 DAC_CR(dac) &= ~DAC_CR_DMAEN1;
214 break;
215 case DAC_CHANNEL2:
216 DAC_CR(dac) &= ~DAC_CR_DMAEN2;
217 break;
218 case DAC_CHANNEL_BOTH:
220 break;
221 default:
222 break;
223 }
224}
225
226/** @brief DAC Channel Trigger Enable.
227
228Enable a digital to analog converter channel external trigger mode. This allows
229an external trigger to initiate register transfers from the buffer register to
230the DAC output register, followed by a DMA transfer to the buffer register if
231DMA is enabled. The trigger source must also be selected.
232
233@param[in] dac the base address of the DAC. @ref dac_reg_base
234@param[in] channel with DAC mask. @ref dac_channel_id
235*/
236void dac_trigger_enable(uint32_t dac, int channel)
237{
238 switch (channel) {
239 case DAC_CHANNEL1:
240 DAC_CR(dac) |= DAC_CR_TEN1;
241 break;
242 case DAC_CHANNEL2:
243 DAC_CR(dac) |= DAC_CR_TEN2;
244 break;
245 case DAC_CHANNEL_BOTH:
246 DAC_CR(dac) |= (DAC_CR_TEN1 | DAC_CR_TEN2);
247 break;
248 default:
249 break;
250 }
251}
252
253/** @brief DAC Channel Trigger Disable.
254
255Disable a digital to analog converter channel external trigger.
256
257@param[in] dac the base address of the DAC. @ref dac_reg_base
258@param[in] channel with DAC mask. @ref dac_channel_id
259*/
260void dac_trigger_disable(uint32_t dac, int channel)
261{
262 switch (channel) {
263 case DAC_CHANNEL1:
264 DAC_CR(dac) &= ~DAC_CR_TEN1;
265 break;
266 case DAC_CHANNEL2:
267 DAC_CR(dac) &= ~DAC_CR_TEN2;
268 break;
269 case DAC_CHANNEL_BOTH:
270 DAC_CR(dac) &= ~(DAC_CR_TEN1 | DAC_CR_TEN2);
271 break;
272 default:
273 break;
274 }
275}
276
277/** @brief Set DAC Channel Trigger Source.
278
279Sets the digital to analog converter trigger source, which can be taken from
280various timers, an external trigger or a software trigger.
281
282@param[in] dac the base address of the DAC. @ref dac_reg_base
283@param[in] source Taken from @ref dac_trig2_sel or @ref
284dac_trig1_sel or a logical OR of one of each of these to set both channels
285simultaneously.
286*/
287void dac_set_trigger_source(uint32_t dac, uint32_t source)
288{
289 DAC_CR(dac) |= source;
290}
291
292/**
293 * Set DAC Channel Waveform Generation mode for one or both channels.
294 * These signals are superimposed on existing output values in the
295 * DAC output registers. Waveform can be disabled, noise, triangular,
296 * or sawtooth, depending on family.
297 * @note The DAC trigger must be enabled for this to work.
298 * @param[in] dac the base address of the DAC. @ref dac_reg_base
299 * @param[in] channel one or both, @ref dac_channel_id
300 * @param[in] wave enum ::dac_wave. mode for channel
301 */
302void dac_set_waveform_generation(uint32_t dac, int channel, enum dac_wave wave)
303{
304 uint32_t reg = DAC_CR(dac);
305 switch(channel) {
306 case DAC_CHANNEL1:
308 reg |= wave << DAC_CR_WAVE1_SHIFT;
309 break;
310 case DAC_CHANNEL2:
312 reg |= wave << DAC_CR_WAVE2_SHIFT;
313 break;
314 case DAC_CHANNEL_BOTH:
317 reg |= wave << DAC_CR_WAVE1_SHIFT;
318 reg |= wave << DAC_CR_WAVE2_SHIFT;
319 break;
320 default:
321 break;
322 }
323 DAC_CR(dac) = reg;
324}
325
326/**
327 * Disable DAC Channel Waveform Generation.
328 * @note this is equivalent to @ref dac_set_waveform_generation (dac, channel, DAC_WAVE_DISABLE)
329 * @param[in] dac the base address of the DAC. @ref dac_reg_base
330 * @param[in] channel with DAC mask. @ref dac_channel_id
331 */
332void dac_disable_waveform_generation(uint32_t dac, int channel)
333{
335}
336
337/** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
338
339Sets the digital to analog converter superimposed waveform generation
340characteristics. @li If the noise generation mode is set, this sets the length
341of the PRBS sequence and hence the amplitude of the output noise signal.
342Default setting is length 1. @li If the triangle wave generation mode is set,
343this sets the amplitude of the output signal as 2^(n)-1 where n is the
344parameter value. Default setting is 1.
345
346@note High amplitude levels of these waveforms can overload the DAC and distort
347the signal output.
348@note This must be called before enabling the DAC as the settings will then
349become read-only.
350@note The DAC trigger must be enabled for this to work.
351
352@param[in] dac the base address of the DAC. @ref dac_reg_base
353@param[in] channel one or both, select from @ref dac_channel_id
354@param[in] mamp amplitude of mixed waveform, bit width @ref DAC_CR_MAMPx_MASK
355*/
356void dac_set_waveform_characteristics(uint32_t dac, int channel, int mamp)
357{
358 uint32_t reg = DAC_CR(dac);
359 switch(channel) {
360 case DAC_CHANNEL1:
362 reg |= mamp << DAC_CR_MAMP1_SHIFT;
363 break;
364 case DAC_CHANNEL2:
366 reg |= mamp << DAC_CR_MAMP2_SHIFT;
367 break;
368 case DAC_CHANNEL_BOTH:
371 reg |= mamp << DAC_CR_MAMP1_SHIFT;
372 reg |= mamp << DAC_CR_MAMP2_SHIFT;
373 break;
374 default:
375 break;
376 }
377 DAC_CR(dac) = reg;
378}
379
380/** @brief Load DAC Data Register.
381
382Loads the appropriate digital to analog converter data register with 12 or 8 bit
383data to be converted on a channel. The data can be aligned as follows:
384@li right-aligned 8 bit data in bits 0-7
385@li right-aligned 12 bit data in bits 0-11
386@li left aligned 12 bit data in bits 4-15
387
388@param[in] dac the base address of the DAC. @ref dac_reg_base
389@param[in] data uint16_t with appropriate alignment.
390@param[in] align enum ::dac_align. Alignment and size.
391@param[in] channel uint8_t with DAC mask.
392*/
393void dac_load_data_buffer_single(uint32_t dac, uint16_t data,
394 enum dac_align align,
395 int channel)
396{
397 if (channel == DAC_CHANNEL1) {
398 switch (align) {
399 case DAC_ALIGN_RIGHT8:
400 DAC_DHR8R1(dac) = data;
401 break;
403 DAC_DHR12R1(dac) = data;
404 break;
405 case DAC_ALIGN_LEFT12:
406 DAC_DHR12L1(dac) = data;
407 break;
408 default:
409 break;
410 }
411 } else if (channel == DAC_CHANNEL2) {
412 switch (align) {
413 case DAC_ALIGN_RIGHT8:
414 DAC_DHR8R2(dac) = data;
415 break;
417 DAC_DHR12R2(dac) = data;
418 break;
419 case DAC_ALIGN_LEFT12:
420 DAC_DHR12L2(dac) = data;
421 break;
422 default:
423 break;
424 }
425 }
426}
427
428/** @brief Load DAC Dual Data Register.
429
430Loads the appropriate digital to analog converter dual data register with 12 or
4318 bit data to be converted for both channels. This allows high bandwidth
432simultaneous or independent analog output. The data in both channels are aligned
433identically.
434
435@param[in] dac the base address of the DAC. @ref dac_reg_base
436@param[in] data1 uint16_t for channel 1 with appropriate alignment.
437@param[in] data2 uint16_t for channel 2 with appropriate alignment.
438@param[in] align enum ::dac_align. Right or left aligned, and 8 or
43912 bit.
440*/
442 uint16_t data1, uint16_t data2,
443 enum dac_align align)
444{
445 switch (align) {
446 case DAC_ALIGN_RIGHT8:
447 DAC_DHR8RD(dac) = ((data1 & 0xFF) | ((data2 & 0xFF) << 8));
448 break;
450 DAC_DHR12RD(dac) = ((data1 & 0xFFF) |
451 ((data2 & 0xFFF) << 16));
452 break;
453 case DAC_ALIGN_LEFT12:
454 DAC_DHR12LD(dac) = ((data1 & 0xFFF) |
455 ((data2 & 0xFFF) << 16));
456 break;
457 default:
458 break;
459 }
460}
461
462/** @brief Trigger the DAC by a Software Trigger.
463
464If the trigger source is set to be a software trigger, cause a trigger to occur.
465The trigger is cleared by hardware after conversion.
466
467@param[in] dac the base address of the DAC. @ref dac_reg_base
468@param[in] channel with DAC mask. @ref dac_channel_id
469*/
470void dac_software_trigger(uint32_t dac, int channel)
471{
472 switch (channel) {
473 case DAC_CHANNEL1:
475 break;
476 case DAC_CHANNEL2:
478 break;
479 case DAC_CHANNEL_BOTH:
481 break;
482 default:
483 break;
484 }
485}
486/**@}*/
487
#define DAC_CHANNEL1
#define DAC_CHANNEL_BOTH
#define DAC_CHANNEL2
#define DAC_CR_WAVEx_MASK
Wave generation mode mask size.
#define DAC_CR_WAVE1_SHIFT
WAVE1[1:0]: DAC channel1 wave generation mode.
#define DAC_CR_MAMP2_SHIFT
MAMP2[3:0]: DAC channel2 mask/amplitude selector field position.
#define DAC_CR_MAMP1_SHIFT
MAMP1[3:0]: DAC channel1 mask/amplitude selector field position.
#define DAC_CR_DMAEN2
DMAEN2: DAC channel2 DMA enable.
#define DAC_CR_WAVE2_SHIFT
WAVE2[1:0]: DAC channel2 wave generation mode.
#define DAC_CR_MAMPx_MASK
MAMP Mask/Amplitude selector field size.
#define DAC_CR_DMAEN1
DMAEN1: DAC channel1 DMA enable.
#define DAC_CR_TEN1
#define DAC_CR_EN2
EN2: DAC channel2 enable.
#define DAC_CR_TEN2
Definition: dac_common_v1.h:79
#define DAC_CR_EN1
EN1: DAC channel1 enable.
dac_align
DAC data size (8/12 bits), alignment (right/left)
dac_wave
DAC waveform generation options.
@ DAC_ALIGN_LEFT12
@ DAC_ALIGN_RIGHT12
@ DAC_ALIGN_RIGHT8
@ DAC_WAVE_DISABLE
void dac_disable_waveform_generation(uint32_t dac, int channel)
Disable DAC Channel Waveform Generation.
void dac_set_waveform_characteristics(uint32_t dac, int channel, int mamp)
Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
void dac_set_trigger_source(uint32_t dac, uint32_t source)
Set DAC Channel Trigger Source.
void dac_set_waveform_generation(uint32_t dac, int channel, enum dac_wave wave)
Set DAC Channel Waveform Generation mode for one or both channels.
void dac_trigger_enable(uint32_t dac, int channel)
DAC Channel Trigger Enable.
void dac_load_data_buffer_single(uint32_t dac, uint16_t data, enum dac_align align, int channel)
Load DAC Data Register.
void dac_software_trigger(uint32_t dac, int channel)
Trigger the DAC by a Software Trigger.
void dac_disable(uint32_t dac, int channel)
DAC Channel Disable.
void dac_dma_enable(uint32_t dac, int channel)
DAC Channel DMA Enable.
void dac_load_data_buffer_dual(uint32_t dac, uint16_t data1, uint16_t data2, enum dac_align align)
Load DAC Dual Data Register.
void dac_enable(uint32_t dac, int channel)
DAC Channel Enable.
void dac_trigger_disable(uint32_t dac, int channel)
DAC Channel Trigger Disable.
void dac_dma_disable(uint32_t dac, int channel)
DAC Channel DMA Disable.
#define DAC_CR(dac)
DAC control register (DAC_CR)
#define DAC_DHR12R1(dac)
DAC channel1 12-bit right-aligned data holding register (DAC_DHR12R1)
#define DAC_DHR12RD(dac)
Dual DAC 12-bit right-aligned data holding register (DAC_DHR12RD)
#define DAC_DHR12R2(dac)
DAC channel2 12-bit right aligned data holding register (DAC_DHR12R2)
#define DAC_DHR12L2(dac)
DAC channel2 12-bit left aligned data holding register (DAC_DHR12L2)
#define DAC_DHR8RD(dac)
DUAL DAC 8-bit right aligned data holding register (DAC_DHR8RD)
#define DAC_SWTRIGR(dac)
DAC software trigger register (DAC_SWTRIGR)
#define DAC_DHR8R2(dac)
DAC channel2 8-bit right-aligned data holding register (DAC_DHR8R2)
#define DAC_DHR12L1(dac)
DAC channel1 12-bit left aligned data holding register (DAC_DHR12L1)
#define DAC_DHR8R1(dac)
DAC channel1 8-bit right aligned data holding register (DAC_DHR8R1)
#define DAC_DHR12LD(dac)
DUAL DAC 12-bit left aligned data holding register (DAC_DHR12LD)
#define DAC_SWTRIGR_SWTRIG1
SWTRIG1: DAC channel1 software trigger.
#define DAC_SWTRIGR_SWTRIG2
SWTRIG2: DAC channel2 software trigger.