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