1 /**
2 ******************************************************************************
3 * @file stm32h5xx_hal_dac_ex.c
4 * @author MCD Application Team
5 * @brief Extended DAC HAL module driver.
6 * This file provides firmware functions to manage the extended
7 * functionalities of the DAC peripheral.
8 *
9 *
10 ******************************************************************************
11 * @attention
12 *
13 * Copyright (c) 2023 STMicroelectronics.
14 * All rights reserved.
15 *
16 * This software is licensed under terms that can be found in the LICENSE file
17 * in the root directory of this software component.
18 * If no LICENSE file comes with this software, it is provided AS-IS.
19 *
20 ******************************************************************************
21 @verbatim
22 ==============================================================================
23 ##### How to use this driver #####
24 ==============================================================================
25 [..]
26 *** Dual mode IO operation ***
27 ==============================
28 [..]
29 (+) Use HAL_DACEx_DualStart() to enable both channel and start conversion
30 for dual mode operation.
31 If software trigger is selected, using HAL_DACEx_DualStart() will start
32 the conversion of the value previously set by HAL_DACEx_DualSetValue().
33 (+) Use HAL_DACEx_DualStop() to disable both channel and stop conversion
34 for dual mode operation.
35 (+) Use HAL_DACEx_DualStart_DMA() to enable both channel and start conversion
36 for dual mode operation using DMA to feed DAC converters.
37 First issued trigger will start the conversion of the value previously
38 set by HAL_DACEx_DualSetValue().
39 The same callbacks that are used in single mode are called in dual mode to notify
40 transfer completion (half complete or complete), errors or underrun.
41 (+) Use HAL_DACEx_DualStop_DMA() to disable both channel and stop conversion
42 for dual mode operation using DMA to feed DAC converters.
43 (+) When Dual mode is enabled (i.e. DAC Channel1 and Channel2 are used simultaneously) :
44 Use HAL_DACEx_DualGetValue() to get digital data to be converted and use
45 HAL_DACEx_DualSetValue() to set digital value to converted simultaneously in
46 Channel 1 and Channel 2.
47 *** Signal generation operation ***
48 ===================================
49 [..]
50 (+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
51 (+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
52
53 (+) HAL_DACEx_SelfCalibrate to calibrate one DAC channel.
54 (+) HAL_DACEx_SetUserTrimming to set user trimming value.
55 (+) HAL_DACEx_GetTrimOffset to retrieve trimming value (factory setting
56 after reset, user setting if HAL_DACEx_SetUserTrimming have been used
57 at least one time after reset).
58
59 @endverbatim
60 ******************************************************************************
61 */
62
63
64 /* Includes ------------------------------------------------------------------*/
65 #include "stm32h5xx_hal.h"
66
67 /** @addtogroup STM32H5xx_HAL_Driver
68 * @{
69 */
70
71 #ifdef HAL_DAC_MODULE_ENABLED
72
73 #if defined(DAC1)
74
75 /** @defgroup DACEx DACEx
76 * @brief DAC Extended HAL module driver
77 * @{
78 */
79
80 /* Private typedef -----------------------------------------------------------*/
81 /* Private define ------------------------------------------------------------*/
82
83 /* Delay for DAC minimum trimming time. */
84 /* Note: minimum time needed between two calibration steps */
85 /* The delay below is specified under conditions: */
86 /* - DAC channel output buffer enabled */
87 /* Literal set to maximum value (refer to device datasheet, */
88 /* electrical characteristics, parameter "tTRIM"). */
89 /* Unit: us */
90 #define DAC_DELAY_TRIM_US (50UL) /*!< Delay for DAC minimum trimming time */
91
92 /* Private macro -------------------------------------------------------------*/
93 /* Private variables ---------------------------------------------------------*/
94 /* Private function prototypes -----------------------------------------------*/
95 /* Exported functions --------------------------------------------------------*/
96
97 /** @defgroup DACEx_Exported_Functions DACEx Exported Functions
98 * @{
99 */
100
101 /** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
102 * @brief Extended IO operation functions
103 *
104 @verbatim
105 ==============================================================================
106 ##### Extended features functions #####
107 ==============================================================================
108 [..] This section provides functions allowing to:
109 (+) Start conversion.
110 (+) Stop conversion.
111 (+) Start conversion and enable DMA transfer.
112 (+) Stop conversion and disable DMA transfer.
113 (+) Get result of conversion.
114 (+) Get result of dual mode conversion.
115
116 @endverbatim
117 * @{
118 */
119
120
121 /**
122 * @brief Enables DAC and starts conversion of both channels.
123 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
124 * the configuration information for the specified DAC.
125 * @retval HAL status
126 */
HAL_DACEx_DualStart(DAC_HandleTypeDef * hdac)127 HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
128 {
129 uint32_t tmp_swtrig = 0UL;
130 __IO uint32_t wait_loop_index;
131
132 /* Check the DAC peripheral handle */
133 if (hdac == NULL)
134 {
135 return HAL_ERROR;
136 }
137
138
139 /* Process locked */
140 __HAL_LOCK(hdac);
141
142 /* Change DAC state */
143 hdac->State = HAL_DAC_STATE_BUSY;
144
145 /* Enable the Peripheral */
146 __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
147 __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
148 /* Ensure minimum wait before using peripheral after enabling it */
149 /* Wait loop initialization and execution */
150 /* Note: Variable divided by 2 to compensate partially */
151 /* CPU processing cycles, scaling in us split to not */
152 /* exceed 32 bits register capacity and handle low frequency. */
153 wait_loop_index = ((DAC_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
154 while (wait_loop_index != 0UL)
155 {
156 wait_loop_index--;
157 }
158
159 /* Check if software trigger enabled */
160 if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
161 {
162 tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
163 }
164 if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (DAC_CHANNEL_2 & 0x10UL)))
165 {
166 tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
167 }
168 /* Enable the selected DAC software conversion*/
169 SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
170
171 /* Change DAC state */
172 hdac->State = HAL_DAC_STATE_READY;
173
174 /* Process unlocked */
175 __HAL_UNLOCK(hdac);
176
177 /* Return function status */
178 return HAL_OK;
179 }
180
181 /**
182 * @brief Disables DAC and stop conversion of both channels.
183 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
184 * the configuration information for the specified DAC.
185 * @retval HAL status
186 */
HAL_DACEx_DualStop(DAC_HandleTypeDef * hdac)187 HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
188 {
189 /* Check the DAC peripheral handle */
190 if (hdac == NULL)
191 {
192 return HAL_ERROR;
193 }
194
195
196 /* Disable the Peripheral */
197 __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
198 __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
199
200 /* Change DAC state */
201 hdac->State = HAL_DAC_STATE_READY;
202
203 /* Return function status */
204 return HAL_OK;
205 }
206
207 /**
208 * @brief Enables DAC and starts conversion of both channel 1 and 2 of the same DAC.
209 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
210 * the configuration information for the specified DAC.
211 * @param Channel The DAC channel that will request data from DMA.
212 * This parameter can be one of the following values:
213 * @arg DAC_CHANNEL_1: DAC Channel1 selected
214 * @arg DAC_CHANNEL_2: DAC Channel2 selected
215 * @param pData The destination peripheral Buffer address.
216 * @param Length The length of data to be transferred from memory to DAC peripheral
217 * @param Alignment Specifies the data alignment for DAC channel.
218 * This parameter can be one of the following values:
219 * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
220 * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
221 * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
222 * @retval HAL status
223 */
HAL_DACEx_DualStart_DMA(DAC_HandleTypeDef * hdac,uint32_t Channel,const uint32_t * pData,uint32_t Length,uint32_t Alignment)224 HAL_StatusTypeDef HAL_DACEx_DualStart_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel,
225 const uint32_t *pData, uint32_t Length, uint32_t Alignment)
226 {
227 HAL_StatusTypeDef status;
228 uint32_t tmpreg = 0UL;
229 __IO uint32_t wait_loop_index;
230 uint32_t LengthInBytes;
231
232 /* Check the DAC peripheral handle */
233 if (hdac == NULL)
234 {
235 return HAL_ERROR;
236 }
237
238 /* Check the parameters */
239 assert_param(IS_DAC_CHANNEL(Channel));
240 assert_param(IS_DAC_ALIGN(Alignment));
241
242 /* Process locked */
243 __HAL_LOCK(hdac);
244
245 /* Change DAC state */
246 hdac->State = HAL_DAC_STATE_BUSY;
247
248 if (Channel == DAC_CHANNEL_1)
249 {
250 /* Set the DMA transfer complete callback for channel1 */
251 hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
252
253 /* Set the DMA half transfer complete callback for channel1 */
254 hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
255
256 /* Set the DMA error callback for channel1 */
257 hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
258
259 /* Enable the selected DAC channel1 DMA request */
260 SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
261 }
262 else
263 {
264 /* Set the DMA transfer complete callback for channel2 */
265 hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
266
267 /* Set the DMA half transfer complete callback for channel2 */
268 hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
269
270 /* Set the DMA error callback for channel2 */
271 hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
272
273 /* Enable the selected DAC channel2 DMA request */
274 SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
275 }
276
277 switch (Alignment)
278 {
279 case DAC_ALIGN_12B_R:
280 /* Get DHR12R1 address */
281 tmpreg = (uint32_t)&hdac->Instance->DHR12RD;
282 break;
283 case DAC_ALIGN_12B_L:
284 /* Get DHR12L1 address */
285 tmpreg = (uint32_t)&hdac->Instance->DHR12LD;
286 break;
287 case DAC_ALIGN_8B_R:
288 /* Get DHR8R1 address */
289 tmpreg = (uint32_t)&hdac->Instance->DHR8RD;
290 break;
291 default:
292 break;
293 }
294
295 /* Enable the DMA channel */
296 if (Channel == DAC_CHANNEL_1)
297 {
298 /* Enable the DAC DMA underrun interrupt */
299 __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
300
301 /* Length should be converted to number of bytes */
302 LengthInBytes = Length * 4U;
303
304 /* Check linkedlist mode */
305 if ((hdac->DMA_Handle1->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
306 {
307 if ((hdac->DMA_Handle1->LinkedListQueue != NULL) && (hdac->DMA_Handle1->LinkedListQueue->Head != NULL))
308 {
309 /* Set DMA data size */
310 hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = LengthInBytes;
311
312 /* Set DMA source address */
313 hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)pData;
314
315 /* Set DMA destination address */
316 hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = tmpreg;
317
318 /* Enable the DMA channel */
319 status = HAL_DMAEx_List_Start_IT(hdac->DMA_Handle1);
320 }
321 else
322 {
323 /* Return error status */
324 return HAL_ERROR;
325 }
326 }
327 else
328 {
329 /* Enable the DMA channel */
330 status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, LengthInBytes);
331 }
332 }
333 else
334 {
335 /* Enable the DAC DMA underrun interrupt */
336 __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
337
338 /* Length should be converted to number of bytes */
339 LengthInBytes = Length * 4U;
340
341 /* Check linkedlist mode */
342 if ((hdac->DMA_Handle2->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
343 {
344 if ((hdac->DMA_Handle2->LinkedListQueue != NULL) && (hdac->DMA_Handle2->LinkedListQueue->Head != NULL))
345 {
346 /* Set DMA data size */
347 hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = LengthInBytes;
348
349 /* Set DMA source address */
350 hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)pData;
351
352 /* Set DMA destination address */
353 hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = tmpreg;
354
355 /* Enable the DMA channel */
356 status = HAL_DMAEx_List_Start_IT(hdac->DMA_Handle2);
357 }
358 else
359 {
360 /* Return error status */
361 return HAL_ERROR;
362 }
363 }
364 else
365 {
366 /* Enable the DMA channel */
367 status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, LengthInBytes);
368 }
369 }
370
371 /* Process Unlocked */
372 __HAL_UNLOCK(hdac);
373
374 if (status == HAL_OK)
375 {
376 /* Enable the Peripheral */
377 __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
378 __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
379 /* Ensure minimum wait before using peripheral after enabling it */
380 /* Wait loop initialization and execution */
381 /* Note: Variable divided by 2 to compensate partially */
382 /* CPU processing cycles, scaling in us split to not */
383 /* exceed 32 bits register capacity and handle low frequency. */
384 wait_loop_index = ((DAC_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
385 while (wait_loop_index != 0UL)
386 {
387 wait_loop_index--;
388 }
389 }
390 else
391 {
392 hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
393 }
394
395 /* Return function status */
396 return status;
397 }
398
399 /**
400 * @brief Disables DAC and stop conversion both channel.
401 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
402 * the configuration information for the specified DAC.
403 * @param Channel The DAC channel that requests data from DMA.
404 * This parameter can be one of the following values:
405 * @arg DAC_CHANNEL_1: DAC Channel1 selected
406 * @arg DAC_CHANNEL_2: DAC Channel2 selected
407 * @retval HAL status
408 */
HAL_DACEx_DualStop_DMA(DAC_HandleTypeDef * hdac,uint32_t Channel)409 HAL_StatusTypeDef HAL_DACEx_DualStop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
410 {
411 HAL_StatusTypeDef status;
412
413 /* Check the DAC peripheral handle */
414 if (hdac == NULL)
415 {
416 return HAL_ERROR;
417 }
418
419
420 /* Disable the selected DAC channel DMA request */
421 CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN2 | DAC_CR_DMAEN1);
422
423 /* Disable the Peripheral */
424 __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
425 __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
426
427 /* Disable the DMA channel */
428
429 /* Channel1 is used */
430 if (Channel == DAC_CHANNEL_1)
431 {
432 /* Disable the DMA channel */
433 status = HAL_DMA_Abort(hdac->DMA_Handle1);
434
435 /* Disable the DAC DMA underrun interrupt */
436 __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
437 }
438 else
439 {
440 /* Disable the DMA channel */
441 status = HAL_DMA_Abort(hdac->DMA_Handle2);
442
443 /* Disable the DAC DMA underrun interrupt */
444 __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
445 }
446
447 /* Check if DMA Channel effectively disabled */
448 if (status != HAL_OK)
449 {
450 /* Update DAC state machine to error */
451 hdac->State = HAL_DAC_STATE_ERROR;
452 }
453 else
454 {
455 /* Change DAC state */
456 hdac->State = HAL_DAC_STATE_READY;
457 }
458
459 /* Return function status */
460 return status;
461 }
462
463
464 /**
465 * @brief Enable or disable the selected DAC channel wave generation.
466 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
467 * the configuration information for the specified DAC.
468 * @param Channel The selected DAC channel.
469 * This parameter can be one of the following values:
470 * @arg DAC_CHANNEL_1: DAC Channel1 selected
471 * @arg DAC_CHANNEL_2: DAC Channel2 selected
472 * @param Amplitude Select max triangle amplitude.
473 * This parameter can be one of the following values:
474 * @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
475 * @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
476 * @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
477 * @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
478 * @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
479 * @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
480 * @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
481 * @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
482 * @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
483 * @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
484 * @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
485 * @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
486 * @retval HAL status
487 */
HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)488 HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
489 {
490 /* Check the DAC peripheral handle */
491 if (hdac == NULL)
492 {
493 return HAL_ERROR;
494 }
495
496 /* Check the parameters */
497 assert_param(IS_DAC_CHANNEL(Channel));
498 assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
499
500 /* Process locked */
501 __HAL_LOCK(hdac);
502
503 /* Change DAC state */
504 hdac->State = HAL_DAC_STATE_BUSY;
505
506 /* Enable the triangle wave generation for the selected DAC channel */
507 MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
508 (DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
509
510 /* Change DAC state */
511 hdac->State = HAL_DAC_STATE_READY;
512
513 /* Process unlocked */
514 __HAL_UNLOCK(hdac);
515
516 /* Return function status */
517 return HAL_OK;
518 }
519
520 /**
521 * @brief Enable or disable the selected DAC channel wave generation.
522 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
523 * the configuration information for the specified DAC.
524 * @param Channel The selected DAC channel.
525 * This parameter can be one of the following values:
526 * @arg DAC_CHANNEL_1: DAC Channel1 selected
527 * @arg DAC_CHANNEL_2: DAC Channel2 selected
528 * @param Amplitude Unmask DAC channel LFSR for noise wave generation.
529 * This parameter can be one of the following values:
530 * @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
531 * @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
532 * @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
533 * @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
534 * @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
535 * @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
536 * @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
537 * @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
538 * @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
539 * @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
540 * @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
541 * @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
542 * @retval HAL status
543 */
HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)544 HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
545 {
546 /* Check the DAC peripheral handle */
547 if (hdac == NULL)
548 {
549 return HAL_ERROR;
550 }
551
552 /* Check the parameters */
553 assert_param(IS_DAC_CHANNEL(Channel));
554 assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
555
556 /* Process locked */
557 __HAL_LOCK(hdac);
558
559 /* Change DAC state */
560 hdac->State = HAL_DAC_STATE_BUSY;
561
562 /* Enable the noise wave generation for the selected DAC channel */
563 MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
564 (DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
565
566 /* Change DAC state */
567 hdac->State = HAL_DAC_STATE_READY;
568
569 /* Process unlocked */
570 __HAL_UNLOCK(hdac);
571
572 /* Return function status */
573 return HAL_OK;
574 }
575
576
577 /**
578 * @brief Set the specified data holding register value for dual DAC channel.
579 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
580 * the configuration information for the specified DAC.
581 * @param Alignment Specifies the data alignment for dual channel DAC.
582 * This parameter can be one of the following values:
583 * DAC_ALIGN_8B_R: 8bit right data alignment selected
584 * DAC_ALIGN_12B_L: 12bit left data alignment selected
585 * DAC_ALIGN_12B_R: 12bit right data alignment selected
586 * @param Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
587 * @param Data2 Data for DAC Channel2 to be loaded in the selected data holding register.
588 * @note In dual mode, a unique register access is required to write in both
589 * DAC channels at the same time.
590 * @retval HAL status
591 */
HAL_DACEx_DualSetValue(DAC_HandleTypeDef * hdac,uint32_t Alignment,uint32_t Data1,uint32_t Data2)592 HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
593 {
594 uint32_t data;
595 uint32_t tmp;
596
597 /* Check the DAC peripheral handle */
598 if (hdac == NULL)
599 {
600 return HAL_ERROR;
601 }
602
603 /* Check the parameters */
604 assert_param(IS_DAC_ALIGN(Alignment));
605 assert_param(IS_DAC_DATA(Data1));
606 assert_param(IS_DAC_DATA(Data2));
607
608 /* Calculate and set dual DAC data holding register value */
609 if (Alignment == DAC_ALIGN_8B_R)
610 {
611 data = ((uint32_t)Data2 << 8U) | Data1;
612 }
613 else
614 {
615 data = ((uint32_t)Data2 << 16U) | Data1;
616 }
617
618 tmp = (uint32_t)hdac->Instance;
619 tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
620
621 /* Set the dual DAC selected data holding register */
622 *(__IO uint32_t *)tmp = data;
623
624 /* Return function status */
625 return HAL_OK;
626 }
627
628 /**
629 * @brief Conversion complete callback in non-blocking mode for Channel2.
630 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
631 * the configuration information for the specified DAC.
632 * @retval None
633 */
HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef * hdac)634 __weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
635 {
636 /* Prevent unused argument(s) compilation warning */
637 UNUSED(hdac);
638
639 /* NOTE : This function should not be modified, when the callback is needed,
640 the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
641 */
642 }
643
644 /**
645 * @brief Conversion half DMA transfer callback in non-blocking mode for Channel2.
646 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
647 * the configuration information for the specified DAC.
648 * @retval None
649 */
HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef * hdac)650 __weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
651 {
652 /* Prevent unused argument(s) compilation warning */
653 UNUSED(hdac);
654
655 /* NOTE : This function should not be modified, when the callback is needed,
656 the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
657 */
658 }
659
660 /**
661 * @brief Error DAC callback for Channel2.
662 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
663 * the configuration information for the specified DAC.
664 * @retval None
665 */
HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef * hdac)666 __weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
667 {
668 /* Prevent unused argument(s) compilation warning */
669 UNUSED(hdac);
670
671 /* NOTE : This function should not be modified, when the callback is needed,
672 the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
673 */
674 }
675
676 /**
677 * @brief DMA underrun DAC callback for Channel2.
678 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
679 * the configuration information for the specified DAC.
680 * @retval None
681 */
HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef * hdac)682 __weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
683 {
684 /* Prevent unused argument(s) compilation warning */
685 UNUSED(hdac);
686
687 /* NOTE : This function should not be modified, when the callback is needed,
688 the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
689 */
690 }
691
692
693 /**
694 * @brief Run the self calibration of one DAC channel.
695 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
696 * the configuration information for the specified DAC.
697 * @param sConfig DAC channel configuration structure.
698 * @param Channel The selected DAC channel.
699 * This parameter can be one of the following values:
700 * @arg DAC_CHANNEL_1: DAC Channel1 selected
701 * @arg DAC_CHANNEL_2: DAC Channel2 selected
702 * @retval Updates DAC_TrimmingValue. , DAC_UserTrimming set to DAC_UserTrimming
703 * @retval HAL status
704 * @note Calibration runs about 7 ms.
705 */
HAL_DACEx_SelfCalibrate(DAC_HandleTypeDef * hdac,DAC_ChannelConfTypeDef * sConfig,uint32_t Channel)706 HAL_StatusTypeDef HAL_DACEx_SelfCalibrate(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
707 {
708 HAL_StatusTypeDef status = HAL_OK;
709
710 uint32_t trimmingvalue;
711 uint32_t delta;
712 __IO uint32_t wait_loop_index;
713
714 /* store/restore channel configuration structure purpose */
715 uint32_t oldmodeconfiguration;
716
717 /* Check the parameters */
718 assert_param(IS_DAC_CHANNEL(Channel));
719
720 /* Check the DAC handle allocation */
721 /* Check if DAC running */
722 if ((hdac == NULL) || (sConfig == NULL))
723 {
724 status = HAL_ERROR;
725 }
726 else if (hdac->State == HAL_DAC_STATE_BUSY)
727 {
728 status = HAL_ERROR;
729 }
730 else
731 {
732 /* Process locked */
733 __HAL_LOCK(hdac);
734
735 /* Store configuration */
736 oldmodeconfiguration = (hdac->Instance->MCR & (DAC_MCR_MODE1 << (Channel & 0x10UL)));
737
738 /* Disable the selected DAC channel */
739 CLEAR_BIT((hdac->Instance->CR), (DAC_CR_EN1 << (Channel & 0x10UL)));
740 /* Wait for ready bit to be de-asserted */
741 HAL_Delay(1);
742
743 /* Set mode in MCR for calibration */
744 MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), 0U);
745
746 /* Enable the selected DAC channel calibration */
747 /* i.e. set DAC_CR_CENx bit */
748 SET_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
749
750 /* Init trimming counter */
751 /* Medium value */
752 trimmingvalue = 0x10UL;
753 delta = 0x08UL;
754 while (delta != 0UL)
755 {
756 /* Set candidate trimming */
757 MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
758
759 /* Wait minimum time needed between two calibration steps (OTRIM) */
760 /* Wait loop initialization and execution */
761 /* Note: Variable divided by 2 to compensate partially CPU processing cycles, scaling in us split to not exceed */
762 /* 32 bits register capacity and handle low frequency. */
763 wait_loop_index = ((DAC_DELAY_TRIM_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
764 while (wait_loop_index != 0UL)
765 {
766 wait_loop_index--;
767 }
768
769 if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL)))
770 {
771 /* DAC_SR_CAL_FLAGx is HIGH try higher trimming */
772 trimmingvalue -= delta;
773 }
774 else
775 {
776 /* DAC_SR_CAL_FLAGx is LOW try lower trimming */
777 trimmingvalue += delta;
778 }
779 delta >>= 1UL;
780 }
781
782 /* Still need to check if right calibration is current value or one step below */
783 /* Indeed the first value that causes the DAC_SR_CAL_FLAGx bit to change from 0 to 1 */
784 /* Set candidate trimming */
785 MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
786
787 /* Wait minimum time needed between two calibration steps (OTRIM) */
788 /* Wait loop initialization and execution */
789 /* Note: Variable divided by 2 to compensate partially CPU processing cycles, scaling in us split to not exceed */
790 /* 32 bits register capacity and handle low frequency. */
791 wait_loop_index = ((DAC_DELAY_TRIM_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
792 while (wait_loop_index != 0UL)
793 {
794 wait_loop_index--;
795 }
796
797 if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == 0UL)
798 {
799 /* Check trimming value below maximum */
800 if (trimmingvalue < 0x1FU)
801 {
802 /* Trimming is actually one value more */
803 trimmingvalue++;
804 }
805 /* Set right trimming */
806 MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
807 }
808
809 /* Disable the selected DAC channel calibration */
810 /* i.e. clear DAC_CR_CENx bit */
811 CLEAR_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
812
813 sConfig->DAC_TrimmingValue = trimmingvalue;
814 sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
815
816 /* Restore configuration */
817 MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), oldmodeconfiguration);
818
819 /* Process unlocked */
820 __HAL_UNLOCK(hdac);
821 }
822
823 return status;
824 }
825
826 /**
827 * @brief Set the trimming mode and trimming value (user trimming mode applied).
828 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
829 * the configuration information for the specified DAC.
830 * @param sConfig DAC configuration structure updated with new DAC trimming value.
831 * @param Channel The selected DAC channel.
832 * This parameter can be one of the following values:
833 * @arg DAC_CHANNEL_1: DAC Channel1 selected
834 * @arg DAC_CHANNEL_2: DAC Channel2 selected
835 * @param NewTrimmingValue DAC new trimming value
836 * @retval HAL status
837 */
HAL_DACEx_SetUserTrimming(DAC_HandleTypeDef * hdac,DAC_ChannelConfTypeDef * sConfig,uint32_t Channel,uint32_t NewTrimmingValue)838 HAL_StatusTypeDef HAL_DACEx_SetUserTrimming(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel,
839 uint32_t NewTrimmingValue)
840 {
841 HAL_StatusTypeDef status = HAL_OK;
842
843 /* Check the parameters */
844 assert_param(IS_DAC_CHANNEL(Channel));
845 assert_param(IS_DAC_NEWTRIMMINGVALUE(NewTrimmingValue));
846
847 /* Check the DAC handle and channel configuration struct allocation */
848 if ((hdac == NULL) || (sConfig == NULL))
849 {
850 status = HAL_ERROR;
851 }
852 else
853 {
854 /* Process locked */
855 __HAL_LOCK(hdac);
856
857 /* Set new trimming */
858 MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (NewTrimmingValue << (Channel & 0x10UL)));
859
860 /* Update trimming mode */
861 sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
862 sConfig->DAC_TrimmingValue = NewTrimmingValue;
863
864 /* Process unlocked */
865 __HAL_UNLOCK(hdac);
866 }
867 return status;
868 }
869
870 /**
871 * @brief Return the DAC trimming value.
872 * @param hdac DAC handle
873 * @param Channel The selected DAC channel.
874 * This parameter can be one of the following values:
875 * @arg DAC_CHANNEL_1: DAC Channel1 selected
876 * @arg DAC_CHANNEL_2: DAC Channel2 selected
877 * @retval TrimmingValue Value between Min_Data=0x00 and Max_Data=0x1F
878 */
HAL_DACEx_GetTrimOffset(const DAC_HandleTypeDef * hdac,uint32_t Channel)879 uint32_t HAL_DACEx_GetTrimOffset(const DAC_HandleTypeDef *hdac, uint32_t Channel)
880 {
881 /* Check the parameter */
882 assert_param(IS_DAC_CHANNEL(Channel));
883
884 /* Retrieve trimming */
885 return ((hdac->Instance->CCR & (DAC_CCR_OTRIM1 << (Channel & 0x10UL))) >> (Channel & 0x10UL));
886 }
887
888 /**
889 * @}
890 */
891
892 /** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
893 * @brief Extended Peripheral Control functions
894 *
895 @verbatim
896 ==============================================================================
897 ##### Peripheral Control functions #####
898 ==============================================================================
899 [..] This section provides functions allowing to:
900 (+) Set the specified data holding register value for DAC channel.
901
902 @endverbatim
903 * @{
904 */
905
906
907 /**
908 * @brief Return the last data output value of the selected DAC channel.
909 * @param hdac pointer to a DAC_HandleTypeDef structure that contains
910 * the configuration information for the specified DAC.
911 * @retval The selected DAC channel data output value.
912 */
HAL_DACEx_DualGetValue(const DAC_HandleTypeDef * hdac)913 uint32_t HAL_DACEx_DualGetValue(const DAC_HandleTypeDef *hdac)
914 {
915 uint32_t tmp = 0UL;
916
917 tmp |= hdac->Instance->DOR1;
918
919 tmp |= hdac->Instance->DOR2 << 16UL;
920
921 /* Returns the DAC channel data output register value */
922 return tmp;
923 }
924
925
926 /**
927 * @}
928 */
929 /**
930 * @}
931 */
932
933 /* Private functions ---------------------------------------------------------*/
934 /** @defgroup DACEx_Private_Functions DACEx private functions
935 * @brief Extended private functions
936 * @{
937 */
938
939
940 /**
941 * @brief DMA conversion complete callback.
942 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
943 * the configuration information for the specified DMA module.
944 * @retval None
945 */
DAC_DMAConvCpltCh2(DMA_HandleTypeDef * hdma)946 void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
947 {
948 DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
949
950 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
951 hdac->ConvCpltCallbackCh2(hdac);
952 #else
953 HAL_DACEx_ConvCpltCallbackCh2(hdac);
954 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
955
956 hdac->State = HAL_DAC_STATE_READY;
957 }
958
959 /**
960 * @brief DMA half transfer complete callback.
961 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
962 * the configuration information for the specified DMA module.
963 * @retval None
964 */
DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef * hdma)965 void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
966 {
967 DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
968 /* Conversion complete callback */
969 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
970 hdac->ConvHalfCpltCallbackCh2(hdac);
971 #else
972 HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
973 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
974 }
975
976 /**
977 * @brief DMA error callback.
978 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
979 * the configuration information for the specified DMA module.
980 * @retval None
981 */
DAC_DMAErrorCh2(DMA_HandleTypeDef * hdma)982 void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
983 {
984 DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
985
986 /* Set DAC error code to DMA error */
987 hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
988
989 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
990 hdac->ErrorCallbackCh2(hdac);
991 #else
992 HAL_DACEx_ErrorCallbackCh2(hdac);
993 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
994
995 hdac->State = HAL_DAC_STATE_READY;
996 }
997
998
999 /**
1000 * @}
1001 */
1002
1003 /**
1004 * @}
1005 */
1006
1007 #endif /* DAC1 */
1008
1009 #endif /* HAL_DAC_MODULE_ENABLED */
1010
1011 /**
1012 * @}
1013 */
1014