STM32L4xx_HAL_Driver  1.14.0
stm32l4xx_hal_opamp_ex.c File Reference

Extended OPAMP HAL module driver. This file provides firmware functions to manage the following functionalities of the operational amplifier(s)(OPAMP1, OPAMP2 etc) peripheral: More...

Go to the source code of this file.

Functions

HAL_StatusTypeDef HAL_OPAMPEx_Unlock (OPAMP_HandleTypeDef *hopamp)
 Unlock the selected OPAMP configuration. More...
 
HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll (OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2)
 Run the self calibration of the 2 OPAMPs in parallel. More...
 

Detailed Description

Extended OPAMP HAL module driver. This file provides firmware functions to manage the following functionalities of the operational amplifier(s)(OPAMP1, OPAMP2 etc) peripheral:

Author
MCD Application Team
  • Extended Initialization and de-initialization functions
  • Extended Peripheral Control functions
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"

/** @addtogroup STM32L4xx_HAL_Driver
  * @{
  */

/** @defgroup OPAMPEx OPAMPEx
  * @brief OPAMP Extended HAL module driver
  * @{
  */

#ifdef HAL_OPAMP_MODULE_ENABLED

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

/** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
  * @{
  */

#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
    defined (STM32L496xx) || defined (STM32L4A6xx) || \
    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)

/** @addtogroup OPAMPEx_Exported_Functions_Group1
  * @brief    Extended operation functions
  *
@verbatim
 ===============================================================================
              ##### Extended IO operation functions #####
 ===============================================================================
  [..]
      (+) OPAMP Self calibration.

Definition in file stm32l4xx_hal_opamp_ex.c.

Function Documentation

◆ HAL_OPAMPEx_SelfCalibrateAll()

HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll ( OPAMP_HandleTypeDef hopamp1,
OPAMP_HandleTypeDef hopamp2 
)

Run the self calibration of the 2 OPAMPs in parallel.

Note
Trimming values (PMOS & NMOS) are updated and user trimming is enabled is calibration is successful.
Calibration is performed in the mode specified in OPAMP init structure (mode normal or low-power). To perform calibration for both modes, repeat this function twice after OPAMP init structure accordingly updated.
Calibration runs about 10 ms (5 dichotomy steps, repeated for P and N transistors: 10 steps with 1 ms for each step).
Parameters
hopamp1handle
hopamp2handle
Return values
HALstatus

Definition at line 89 of file stm32l4xx_hal_opamp_ex.c.

90 {
91  HAL_StatusTypeDef status = HAL_OK;
92 
93  uint32_t trimmingvaluen1;
94  uint32_t trimmingvaluep1;
95  uint32_t trimmingvaluen2;
96  uint32_t trimmingvaluep2;
97 
98 /* Selection of register of trimming depending on power mode: OTR or LPOTR */
99  __IO uint32_t* tmp_opamp1_reg_trimming;
100  __IO uint32_t* tmp_opamp2_reg_trimming;
101 
102  uint32_t delta;
103  uint32_t opampmode1;
104  uint32_t opampmode2;
105 
106  if((hopamp1 == NULL) || (hopamp2 == NULL))
107  {
108  status = HAL_ERROR;
109  }
110  /* Check if OPAMP in calibration mode and calibration not yet enable */
111  else if(hopamp1->State != HAL_OPAMP_STATE_READY)
112  {
113  status = HAL_ERROR;
114  }
115  else if(hopamp2->State != HAL_OPAMP_STATE_READY)
116  {
117  status = HAL_ERROR;
118  }
119  else
120  {
121  /* Check the parameter */
122  assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
123  assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
124 
125  assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode));
126  assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode));
127 
128  /* Save OPAMP mode as in */
129  /* STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx */
130  /* the calibration is not working in PGA mode */
131  opampmode1 = READ_BIT(hopamp1->Instance->CSR,OPAMP_CSR_OPAMODE);
132  opampmode2 = READ_BIT(hopamp2->Instance->CSR,OPAMP_CSR_OPAMODE);
133 
134  /* Use of standalone mode */
135  MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE);
136  MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE);
137 
138  /* user trimming values are used for offset calibration */
139  SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM);
140  SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM);
141 
142  /* Select trimming settings depending on power mode */
143  if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
144  {
145  tmp_opamp1_reg_trimming = &OPAMP1->OTR;
146  }
147  else
148  {
149  tmp_opamp1_reg_trimming = &OPAMP1->LPOTR;
150  }
151 
152  if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
153  {
154  tmp_opamp2_reg_trimming = &OPAMP2->OTR;
155  }
156  else
157  {
158  tmp_opamp2_reg_trimming = &OPAMP2->LPOTR;
159  }
160 
161  /* Enable calibration */
162  SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
163  SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
164 
165  /* 1st calibration - N */
166  CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL);
167  CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL);
168 
169  /* Enable the selected opamp */
170  SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
171  SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
172 
173  /* Init trimming counter */
174  /* Medium value */
175  trimmingvaluen1 = 16U;
176  trimmingvaluen2 = 16U;
177  delta = 8U;
178 
179  while (delta != 0U)
180  {
181  /* Set candidate trimming */
182  /* OPAMP_POWERMODE_NORMAL */
183  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
184  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
185 
186  /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
187  /* Offset trim time: during calibration, minimum time needed between */
188  /* two steps to have 1 mV accuracy */
189  HAL_Delay(OPAMP_TRIMMING_DELAY);
190 
191  if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
192  {
193  /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
194  trimmingvaluen1 -= delta;
195  }
196  else
197  {
198  /* OPAMP_CSR_CALOUT is LOW try higher trimming */
199  trimmingvaluen1 += delta;
200  }
201 
202  if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
203  {
204  /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
205  trimmingvaluen2 -= delta;
206  }
207  else
208  {
209  /* OPAMP_CSR_CALOUT is LOW try higher trimming */
210  trimmingvaluen2 += delta;
211  }
212  /* Divide range by 2 to continue dichotomy sweep */
213  delta >>= 1U;
214  }
215 
216  /* Still need to check if right calibration is current value or one step below */
217  /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */
218  /* Set candidate trimming */
219  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
220  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
221 
222  /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
223  /* Offset trim time: during calibration, minimum time needed between */
224  /* two steps to have 1 mV accuracy */
225  HAL_Delay(OPAMP_TRIMMING_DELAY);
226 
227  if ((READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)) == 0U)
228  {
229  /* Trimming value is actually one value more */
230  trimmingvaluen1++;
231  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
232  }
233 
234  if ((READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)) == 0U)
235  {
236  /* Trimming value is actually one value more */
237  trimmingvaluen2++;
238  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
239  }
240 
241  /* 2nd calibration - P */
242  SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL);
243  SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL);
244 
245  /* Init trimming counter */
246  /* Medium value */
247  trimmingvaluep1 = 16U;
248  trimmingvaluep2 = 16U;
249  delta = 8U;
250 
251  while (delta != 0U)
252  {
253  /* Set candidate trimming */
254  /* OPAMP_POWERMODE_NORMAL */
255  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
256  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
257 
258  /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
259  /* Offset trim time: during calibration, minimum time needed between */
260  /* two steps to have 1 mV accuracy */
261  HAL_Delay(OPAMP_TRIMMING_DELAY);
262 
263  if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
264  {
265  /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
266  trimmingvaluep1 += delta;
267  }
268  else
269  {
270  /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
271  trimmingvaluep1 -= delta;
272  }
273 
274  if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
275  {
276  /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
277  trimmingvaluep2 += delta;
278  }
279  else
280  {
281  /* OPAMP_CSR_CALOUT is LOW try lower trimming */
282  trimmingvaluep2 -= delta;
283  }
284  /* Divide range by 2 to continue dichotomy sweep */
285  delta >>= 1U;
286  }
287 
288  /* Still need to check if right calibration is current value or one step below */
289  /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
290  /* Set candidate trimming */
291  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
292  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
293 
294  /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
295  /* Offset trim time: during calibration, minimum time needed between */
296  /* two steps to have 1 mV accuracy */
297  HAL_Delay(OPAMP_TRIMMING_DELAY);
298 
299  if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
300  {
301  /* Trimming value is actually one value more */
302  trimmingvaluep1++;
303  MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
304  }
305 
306  if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
307  {
308  /* Trimming value is actually one value more */
309  trimmingvaluep2++;
310  MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
311  }
312 
313  /* Disable the OPAMPs */
314  CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
315  CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
316 
317  /* Disable calibration & set normal mode (operating mode) */
318  CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
319  CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
320 
321  /* Self calibration is successful */
322  /* Store calibration (user trimming) results in init structure. */
323 
324  /* Set user trimming mode */
325  hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
326  hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
327 
328  /* Affect calibration parameters depending on mode normal/low power */
329  if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
330  {
331  /* Write calibration result N */
332  hopamp1->Init.TrimmingValueN = trimmingvaluen1;
333  /* Write calibration result P */
334  hopamp1->Init.TrimmingValueP = trimmingvaluep1;
335  }
336  else
337  {
338  /* Write calibration result N */
339  hopamp1->Init.TrimmingValueNLowPower = trimmingvaluen1;
340  /* Write calibration result P */
341  hopamp1->Init.TrimmingValuePLowPower = trimmingvaluep1;
342  }
343 
344  if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
345  {
346  /* Write calibration result N */
347  hopamp2->Init.TrimmingValueN = trimmingvaluen2;
348  /* Write calibration result P */
349  hopamp2->Init.TrimmingValueP = trimmingvaluep2;
350  }
351  else
352  {
353  /* Write calibration result N */
354  hopamp2->Init.TrimmingValueNLowPower = trimmingvaluen2;
355  /* Write calibration result P */
356  hopamp2->Init.TrimmingValuePLowPower = trimmingvaluep2;
357  }
358 
359  /* Update OPAMP state */
360  hopamp1->State = HAL_OPAMP_STATE_READY;
361  hopamp2->State = HAL_OPAMP_STATE_READY;
362 
363  /* Restore OPAMP mode after calibration */
364  MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode1);
365  MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode2);
366  }
367  return status;
368 }
void HAL_Delay(uint32_t Delay)
This function provides minimum delay (in milliseconds) based on variable incremented.
CLEAR_BIT(hrtc->Instance->CR, RTC_CR_WUTE)
return HAL_OK
MODIFY_REG(hrtc->Instance->CR, RTC_CR_WUCKSEL,(uint32_t) WakeUpClock)
assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock))