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