1 /**
2   ******************************************************************************
3   * @file    stm32l0xx_hal_adc_ex.c
4   * @author  MCD Application Team
5   * @brief   This file provides firmware functions to manage the following
6   *          functionalities of the Analog to Digital Convertor (ADC)
7   *          peripheral:
8   *           + Operation functions
9   *             ++ Calibration
10   *               +++ ADC automatic self-calibration
11   *               +++ Calibration factors get or set
12   *          Other functions (generic functions) are available in file
13   *          "stm32l0xx_hal_adc.c".
14   *
15   @verbatim
16   [..]
17   (@) Sections "ADC peripheral features" and "How to use this driver" are
18       available in file of generic functions "stm32l0xx_hal_adc.c".
19   [..]
20   @endverbatim
21   ******************************************************************************
22   * @attention
23   *
24   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
25   *
26   * Redistribution and use in source and binary forms, with or without modification,
27   * are permitted provided that the following conditions are met:
28   *   1. Redistributions of source code must retain the above copyright notice,
29   *      this list of conditions and the following disclaimer.
30   *   2. Redistributions in binary form must reproduce the above copyright notice,
31   *      this list of conditions and the following disclaimer in the documentation
32   *      and/or other materials provided with the distribution.
33   *   3. Neither the name of STMicroelectronics nor the names of its contributors
34   *      may be used to endorse or promote products derived from this software
35   *      without specific prior written permission.
36   *
37   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
41   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47   *
48   ******************************************************************************
49   */
50 
51 /* Includes ------------------------------------------------------------------*/
52 #include "stm32l0xx_hal.h"
53 
54 /** @addtogroup STM32L0xx_HAL_Driver
55   * @{
56   */
57 
58 /** @defgroup ADCEx ADCEx
59   * @brief ADC Extended HAL module driver
60   * @{
61   */
62 
63 #ifdef HAL_ADC_MODULE_ENABLED
64 
65 /* Private typedef -----------------------------------------------------------*/
66 /* Private define ------------------------------------------------------------*/
67 
68 /** @defgroup ADCEx_Private_Constants ADC Extended Private Constants
69   * @{
70   */
71 
72   /* Fixed timeout values for ADC calibration, enable settling time, disable  */
73   /* settling time.                                                           */
74   /* Values defined to be higher than worst cases: low clock frequency,       */
75   /* maximum prescaler.                                                       */
76   /* Unit: ms                                                                 */
77   #define ADC_CALIBRATION_TIMEOUT      10U
78 
79 /* Delay for VREFINT stabilization time. */
80 /* Internal reference startup time max value is 3ms  (refer to device datasheet, parameter TVREFINT). */
81 /* Unit: ms */
82 #define SYSCFG_BUF_VREFINT_ENABLE_TIMEOUT       ((uint32_t) 3U)
83 
84 /* Delay for TEMPSENSOR stabilization time. */
85 /* Temperature sensor startup time max value is 10us  (refer to device datasheet, parameter tSTART). */
86 /* Unit: ms */
87 #define SYSCFG_BUF_TEMPSENSOR_ENABLE_TIMEOUT    ((uint32_t) 1U)
88 
89 /* Private macro -------------------------------------------------------------*/
90 /* Private variables ---------------------------------------------------------*/
91 /* Private function prototypes -----------------------------------------------*/
92 /* Exported functions --------------------------------------------------------*/
93 
94 /** @defgroup ADCEx_Exported_Functions ADC Extended Exported Functions
95   * @{
96   */
97 
98 /** @defgroup ADCEx_Exported_Functions_Group1 Extended Input and Output operation functions
99   * @brief    Extended IO operation functions
100   *
101 @verbatim
102  ===============================================================================
103                       ##### IO operation functions #####
104  ===============================================================================
105     [..]  This section provides functions allowing to:
106       (+) Perform the ADC calibration.
107 @endverbatim
108   * @{
109   */
110 
111 /**
112   * @brief  Perform an ADC automatic self-calibration
113   *         Calibration prerequisite: ADC must be disabled (execute this
114   *         function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
115   * @note   Calibration factor can be read after calibration, using function
116   *         HAL_ADC_GetValue() (value on 7 bits: from DR[6;0]).
117   * @param  hadc       ADC handle
118   * @param  SingleDiff: Selection of single-ended or differential input
119   *          This parameter can be only of the following values:
120   *            @arg ADC_SINGLE_ENDED: Channel in mode input single ended
121   * @retval HAL status
122   */
HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef * hadc,uint32_t SingleDiff)123 HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
124 {
125   HAL_StatusTypeDef tmp_hal_status = HAL_OK;
126   uint32_t tickstart = 0U;
127   uint32_t backup_setting_adc_dma_transfer = 0U; /* Note: Variable not declared as volatile because register read is already declared as volatile */
128 
129   /* Check the parameters */
130   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
131 
132   /* Process locked */
133   __HAL_LOCK(hadc);
134 
135   /* Calibration prerequisite: ADC must be disabled. */
136   if (ADC_IS_ENABLE(hadc) == RESET)
137   {
138     /* Set ADC state */
139     ADC_STATE_CLR_SET(hadc->State,
140                       HAL_ADC_STATE_REG_BUSY,
141                       HAL_ADC_STATE_BUSY_INTERNAL);
142 
143     /* Disable ADC DMA transfer request during calibration */
144     /* Note: Specificity of this STM32 serie: Calibration factor is           */
145     /*       available in data register and also transfered by DMA.           */
146     /*       To not insert ADC calibration factor among ADC conversion data   */
147     /*       in array variable, DMA transfer must be disabled during          */
148     /*       calibration.                                                     */
149     backup_setting_adc_dma_transfer = READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
150     CLEAR_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
151 
152     /* Start ADC calibration */
153     hadc->Instance->CR |= ADC_CR_ADCAL;
154 
155     tickstart = HAL_GetTick();
156 
157     /* Wait for calibration completion */
158     while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL))
159     {
160       if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
161       {
162         /* Update ADC state machine to error */
163         ADC_STATE_CLR_SET(hadc->State,
164                           HAL_ADC_STATE_BUSY_INTERNAL,
165                           HAL_ADC_STATE_ERROR_INTERNAL);
166 
167         /* Process unlocked */
168         __HAL_UNLOCK(hadc);
169 
170         return HAL_ERROR;
171       }
172     }
173 
174     /* Restore ADC DMA transfer request after calibration */
175     SET_BIT(hadc->Instance->CFGR1, backup_setting_adc_dma_transfer);
176 
177     /* Set ADC state */
178     ADC_STATE_CLR_SET(hadc->State,
179                       HAL_ADC_STATE_BUSY_INTERNAL,
180                       HAL_ADC_STATE_READY);
181   }
182   else
183   {
184     /* Update ADC state machine to error */
185     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
186 
187     tmp_hal_status = HAL_ERROR;
188   }
189 
190   /* Process unlocked */
191   __HAL_UNLOCK(hadc);
192 
193   /* Return function status */
194   return tmp_hal_status;
195 }
196 
197 /**
198   * @brief  Get the calibration factor.
199   * @param  hadc: ADC handle.
200   * @param  SingleDiff: This parameter can be only:
201   *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
202   * @retval Calibration value.
203   */
HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef * hadc,uint32_t SingleDiff)204 uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
205 {
206   /* Check the parameters */
207   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
208   assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
209 
210   /* Return the ADC calibration value */
211   return ((hadc->Instance->CALFACT) & 0x0000007FU);
212 }
213 
214 /**
215   * @brief  Set the calibration factor to overwrite automatic conversion result.
216   *         ADC must be enabled and no conversion is ongoing.
217   * @param  hadc: ADC handle
218   * @param  SingleDiff: This parameter can be only:
219   *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
220   * @param  CalibrationFactor: Calibration factor (coded on 7 bits maximum)
221   * @retval HAL state
222   */
HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef * hadc,uint32_t SingleDiff,uint32_t CalibrationFactor)223 HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff, uint32_t CalibrationFactor)
224 {
225   HAL_StatusTypeDef tmp_hal_status = HAL_OK;
226 
227   /* Check the parameters */
228   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
229   assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
230   assert_param(IS_ADC_CALFACT(CalibrationFactor));
231 
232   /* Process locked */
233   __HAL_LOCK(hadc);
234 
235   /* Verification of hardware constraints before modifying the calibration    */
236   /* factors register: ADC must be enabled, no conversion on going.           */
237   if ( (ADC_IS_ENABLE(hadc) != RESET)                            &&
238        (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)  )
239   {
240     /* Set the selected ADC calibration value */
241     hadc->Instance->CALFACT &= ~ADC_CALFACT_CALFACT;
242     hadc->Instance->CALFACT |= CalibrationFactor;
243   }
244   else
245   {
246     /* Update ADC state machine to error */
247     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
248     /* Update ADC state machine to error */
249     SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
250 
251     /* Update ADC state machine to error */
252     tmp_hal_status = HAL_ERROR;
253   }
254 
255   /* Process unlocked */
256   __HAL_UNLOCK(hadc);
257 
258   /* Return function status */
259   return tmp_hal_status;
260 }
261 
262 /**
263   * @brief  Enables the buffer of Vrefint for the ADC, required when device is in mode low-power (low-power run, low-power sleep or stop mode)
264   *         This function must be called before function HAL_ADC_Init()
265   *         (in case of previous ADC operations: function HAL_ADC_DeInit() must be called first)
266   *         For more details on procedure and buffer current consumption, refer to device reference manual.
267   * @note   This is functional only if the LOCK is not set.
268   * @retval None
269 */
HAL_ADCEx_EnableVREFINT(void)270 HAL_StatusTypeDef HAL_ADCEx_EnableVREFINT(void)
271 {
272   uint32_t tickstart = 0U;
273 
274   /* Enable the Buffer for the ADC by setting ENBUF_SENSOR_ADC bit in the CFGR3 register */
275   SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_VREFINT_ADC);
276 
277   /* Wait for Vrefint buffer effectively enabled */
278   /* Get tick count */
279   tickstart = HAL_GetTick();
280 
281   while(HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
282   {
283     if((HAL_GetTick() - tickstart) > SYSCFG_BUF_VREFINT_ENABLE_TIMEOUT)
284     {
285       return HAL_ERROR;
286     }
287   }
288 
289   return HAL_OK;
290 }
291 
292 /**
293   * @brief Disables the Buffer Vrefint for the ADC.
294   * @note This is functional only if the LOCK is not set.
295   * @retval None
296   */
HAL_ADCEx_DisableVREFINT(void)297 void HAL_ADCEx_DisableVREFINT(void)
298 {
299   /* Disable the Vrefint by resetting ENBUF_SENSOR_ADC bit in the CFGR3 register */
300   CLEAR_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_VREFINT_ADC);
301 }
302 
303 /**
304 * @brief  Enables the buffer of temperature sensor for the ADC, required when device is in mode low-power (low-power run, low-power sleep or stop mode)
305 *         This function must be called before function HAL_ADC_Init()
306 *         (in case of previous ADC operations: function HAL_ADC_DeInit() must be called first)
307 *         For more details on procedure and buffer current consumption, refer to device reference manual.
308 * @note   This is functional only if the LOCK is not set.
309 * @retval None
310 */
HAL_ADCEx_EnableVREFINTTempSensor(void)311 HAL_StatusTypeDef HAL_ADCEx_EnableVREFINTTempSensor(void)
312 {
313   uint32_t tickstart = 0U;
314 
315   /* Enable the Buffer for the ADC by setting ENBUF_SENSOR_ADC bit in the CFGR3 register */
316   SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_SENSOR_ADC);
317 
318   /* Wait for Vrefint buffer effectively enabled */
319   /* Get tick count */
320   tickstart = HAL_GetTick();
321 
322   while(HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
323   {
324     if((HAL_GetTick() - tickstart) > SYSCFG_BUF_TEMPSENSOR_ENABLE_TIMEOUT)
325     {
326       return HAL_ERROR;
327     }
328   }
329 
330   return HAL_OK;
331 }
332 
333 /**
334   * @brief Disables the VREFINT and Sensor for the ADC.
335   * @note This is functional only if the LOCK is not set.
336   * @retval None
337   */
HAL_ADCEx_DisableVREFINTTempSensor(void)338 void HAL_ADCEx_DisableVREFINTTempSensor(void)
339 {
340   /* Disable the Vrefint by resetting ENBUF_SENSOR_ADC bit in the CFGR3 register */
341   CLEAR_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_SENSOR_ADC);
342 }
343 
344 /**
345   * @}
346   */
347 
348 /**
349   * @}
350   */
351 
352 #endif /* HAL_ADC_MODULE_ENABLED */
353 /**
354   * @}
355   */
356 
357 /**
358   * @}
359   */
360 
361 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
362