2 ******************************************************************************
3 * @file stm32l1xx_hal_opamp_ex.c
4 * @author MCD Application Team
6 * @date 5-September-2014
7 * @brief Extended OPAMP HAL module driver.
9 * This file provides firmware functions to manage the following
10 * functionalities of the Power Controller (OPAMP) peripheral:
11 * + Extended Initialization and de-initialization functions
12 * + Extended Peripheral Control functions
15 ******************************************************************************
18 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
20 * Redistribution and use in source and binary forms, with or without modification,
21 * are permitted provided that the following conditions are met:
22 * 1. Redistributions of source code must retain the above copyright notice,
23 * this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright notice,
25 * this list of conditions and the following disclaimer in the documentation
26 * and/or other materials provided with the distribution.
27 * 3. Neither the name of STMicroelectronics nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ******************************************************************************
45 /* Includes ------------------------------------------------------------------*/
46 #include "stm32l1xx_hal.h"
48 /** @addtogroup STM32L1xx_HAL_Driver
52 /** @defgroup OPAMPEx OPAMPEx
53 * @brief OPAMP Extended HAL module driver.
57 #ifdef HAL_OPAMP_MODULE_ENABLED
59 #if defined (STM32L151xCA) || defined (STM32L151xD) || defined (STM32L152xCA) || defined (STM32L152xD) || defined (STM32L162xCA) || defined (STM32L162xD) || defined (STM32L151xE) || defined (STM32L152xE) || defined (STM32L162xE) || defined (STM32L162xC) || defined (STM32L152xC) || defined (STM32L151xC)
61 /* Private typedef -----------------------------------------------------------*/
62 /* Private define ------------------------------------------------------------*/
63 /* Private macro -------------------------------------------------------------*/
64 /* Private variables ---------------------------------------------------------*/
65 /* Private function prototypes -----------------------------------------------*/
66 /* Private functions ---------------------------------------------------------*/
68 /** @addtogroup OPAMPEx_Exported_Functions OPAMPEx Exported Functions
72 /** @addtogroup OPAMPEx_Exported_Functions_Group1
73 * @brief Extended operation functions
76 ===============================================================================
77 ##### Extended IO operation functions #####
78 ===============================================================================
80 (+) OPAMP Self calibration.
86 #if defined (STM32L151xD) || defined (STM32L152xD) || defined (STM32L162xD)
88 /* 3 OPAMPS available */
89 /* 3 OPAMPS can be calibrated in parallel */
92 * @brief Run the self calibration of the 3 OPAMPs in parallel.
93 * @note Trimming values (PMOS & NMOS) are updated and user trimming is
94 * enabled is calibration is succesful.
95 * @note Calibration is performed in the mode specified in OPAMP init
96 * structure (mode normal or low-power). To perform calibration for
97 * both modes, repeat this function twice after OPAMP init structure
98 * accordingly updated.
99 * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
100 * and N transistors: 10 steps with 1 ms for each step).
101 * @param hopamp1 handle
102 * @param hopamp2 handle
103 * @param hopamp3 handle
106 HAL_StatusTypeDef
HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef
*hopamp1
, OPAMP_HandleTypeDef
*hopamp2
, OPAMP_HandleTypeDef
*hopamp3
)
108 HAL_StatusTypeDef status
= HAL_OK
;
110 uint32_t* opamp1_trimmingvalue
= 0;
111 uint32_t opamp1_trimmingvaluen
= 0;
112 uint32_t opamp1_trimmingvaluep
= 0;
114 uint32_t* opamp2_trimmingvalue
= 0;
115 uint32_t opamp2_trimmingvaluen
= 0;
116 uint32_t opamp2_trimmingvaluep
= 0;
118 uint32_t* opamp3_trimmingvalue
= 0;
119 uint32_t opamp3_trimmingvaluen
= 0;
120 uint32_t opamp3_trimmingvaluep
= 0;
122 uint32_t trimming_diff_pair
= 0; /* Selection of differential transistors pair high or low */
124 __IO
uint32_t* tmp_opamp1_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
125 __IO
uint32_t* tmp_opamp2_reg_trimming
;
126 __IO
uint32_t* tmp_opamp3_reg_trimming
;
127 uint32_t tmp_opamp1_otr_otuser
= 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
128 uint32_t tmp_opamp2_otr_otuser
= 0;
129 uint32_t tmp_opamp3_otr_otuser
= 0;
131 uint32_t tmp_Opa1calout_DefaultSate
= 0; /* Bit OPAMP_CSR_OPA1CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
132 uint32_t tmp_Opa2calout_DefaultSate
= 0; /* Bit OPAMP_CSR_OPA2CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
133 uint32_t tmp_Opa3calout_DefaultSate
= 0; /* Bit OPAMP_CSR_OPA3CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
135 uint32_t tmp_OpaxSwitchesContextBackup
= 0;
137 uint8_t trimming_diff_pair_iteration_count
= 0;
141 /* Check the OPAMP handle allocation */
142 /* Check if OPAMP locked */
143 if((hopamp1
== HAL_NULL
) || (hopamp1
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) ||
144 (hopamp2
== HAL_NULL
) || (hopamp2
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) ||
145 (hopamp3
== HAL_NULL
) || (hopamp3
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) )
152 /* Check if OPAMP in calibration mode and calibration not yet enable */
153 if((hopamp1
->State
== HAL_OPAMP_STATE_READY
) &&
154 (hopamp2
->State
== HAL_OPAMP_STATE_READY
) &&
155 (hopamp3
->State
== HAL_OPAMP_STATE_READY
) )
157 /* Check the parameter */
158 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1
->Instance
));
159 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2
->Instance
));
160 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp3
->Instance
));
161 assert_param(IS_OPAMP_POWERMODE(hopamp1
->Init
.PowerMode
));
162 assert_param(IS_OPAMP_POWERMODE(hopamp2
->Init
.PowerMode
));
163 assert_param(IS_OPAMP_POWERMODE(hopamp3
->Init
.PowerMode
));
165 /* Update OPAMP state */
166 hopamp1
->State
= HAL_OPAMP_STATE_CALIBBUSY
;
167 hopamp2
->State
= HAL_OPAMP_STATE_CALIBBUSY
;
168 hopamp3
->State
= HAL_OPAMP_STATE_CALIBBUSY
;
170 /* Backup of switches configuration to restore it at the end of the */
172 tmp_OpaxSwitchesContextBackup
= READ_BIT(OPAMP
->CSR
, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS
);
174 /* Open all switches on non-inverting input, inverting input and output */
176 CLEAR_BIT(OPAMP
->CSR
, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS
);
178 /* Set calibration mode to user programmed trimming values */
179 SET_BIT(OPAMP
->OTR
, OPAMP_OTR_OT_USER
);
181 /* Select trimming settings depending on power mode */
182 if (hopamp1
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
184 tmp_opamp1_otr_otuser
= OPAMP_OTR_OT_USER
;
185 tmp_opamp1_reg_trimming
= &OPAMP
->OTR
;
189 tmp_opamp1_otr_otuser
= 0x00000000;
190 tmp_opamp1_reg_trimming
= &OPAMP
->LPOTR
;
193 if (hopamp2
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
195 tmp_opamp2_otr_otuser
= OPAMP_OTR_OT_USER
;
196 tmp_opamp2_reg_trimming
= &OPAMP
->OTR
;
200 tmp_opamp2_otr_otuser
= 0x00000000;
201 tmp_opamp2_reg_trimming
= &OPAMP
->LPOTR
;
204 if (hopamp3
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
206 tmp_opamp3_otr_otuser
= OPAMP_OTR_OT_USER
;
207 tmp_opamp3_reg_trimming
= &OPAMP
->OTR
;
211 tmp_opamp3_otr_otuser
= 0x00000000;
212 tmp_opamp3_reg_trimming
= &OPAMP
->LPOTR
;
215 /* Enable the selected opamp */
216 CLEAR_BIT (OPAMP
->CSR
, OPAMP_CSR_OPAXPD_ALL
);
218 /* Perform trimming for both differential transistors pair high and low */
219 for (trimming_diff_pair_iteration_count
= 0; trimming_diff_pair_iteration_count
<=1; trimming_diff_pair_iteration_count
++)
221 if (trimming_diff_pair_iteration_count
== 0)
223 /* Calibration of transistors differential pair high (NMOS) */
224 trimming_diff_pair
= OPAMP_FACTORYTRIMMING_N
;
225 opamp1_trimmingvalue
= &opamp1_trimmingvaluen
;
226 opamp2_trimmingvalue
= &opamp2_trimmingvaluen
;
227 opamp3_trimmingvalue
= &opamp3_trimmingvaluen
;
229 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
230 /* is 00000b. Used to detect the bit toggling during trimming. */
231 tmp_Opa1calout_DefaultSate
= RESET
;
232 tmp_Opa2calout_DefaultSate
= RESET
;
233 tmp_Opa3calout_DefaultSate
= RESET
;
235 /* Enable calibration for N differential pair */
236 MODIFY_REG(OPAMP
->CSR
, OPAMP_CSR_OPAXCAL_L_ALL
,
237 OPAMP_CSR_OPAXCAL_H_ALL
);
239 else /* (trimming_diff_pair_iteration_count == 1) */
241 /* Calibration of transistors differential pair low (PMOS) */
242 trimming_diff_pair
= OPAMP_FACTORYTRIMMING_P
;
243 opamp1_trimmingvalue
= &opamp1_trimmingvaluep
;
244 opamp2_trimmingvalue
= &opamp2_trimmingvaluep
;
245 opamp3_trimmingvalue
= &opamp3_trimmingvaluep
;
247 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
248 /* is 00000b. Used to detect the bit toggling during trimming. */
249 tmp_Opa1calout_DefaultSate
= __OPAMP_CSR_OPAXCALOUT(hopamp1
);
250 tmp_Opa2calout_DefaultSate
= __OPAMP_CSR_OPAXCALOUT(hopamp2
);
251 tmp_Opa3calout_DefaultSate
= __OPAMP_CSR_OPAXCALOUT(hopamp3
);
253 /* Enable calibration for P differential pair */
254 MODIFY_REG(OPAMP
->CSR
, OPAMP_CSR_OPAXCAL_H_ALL
,
255 OPAMP_CSR_OPAXCAL_L_ALL
);
259 /* Perform calibration parameter search by dichotomy sweep */
260 /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
261 /* initial range, then successive delta sweeps (8, 4, 2, 1). */
262 /* can extend the search range to +/- 15 units. */
263 /* - Trimming initial value 15: search range will go from 0 to 30 */
264 /* (Trimming value 31 is forbidden). */
265 *opamp1_trimmingvalue
= 15;
266 *opamp2_trimmingvalue
= 15;
267 *opamp3_trimmingvalue
= 15;
272 /* Set candidate trimming */
274 MODIFY_REG(*tmp_opamp1_reg_trimming
, __OPAMP_OFFSET_TRIM_SET(hopamp1
, trimming_diff_pair
, OPAMP_TRIM_VALUE_MASK
) ,
275 __OPAMP_OFFSET_TRIM_SET(hopamp1
, trimming_diff_pair
, *opamp1_trimmingvalue
) | tmp_opamp1_otr_otuser
);
277 MODIFY_REG(*tmp_opamp2_reg_trimming
, __OPAMP_OFFSET_TRIM_SET(hopamp2
, trimming_diff_pair
, OPAMP_TRIM_VALUE_MASK
) ,
278 __OPAMP_OFFSET_TRIM_SET(hopamp2
, trimming_diff_pair
, *opamp2_trimmingvalue
) | tmp_opamp2_otr_otuser
);
280 MODIFY_REG(*tmp_opamp3_reg_trimming
, __OPAMP_OFFSET_TRIM_SET(hopamp3
, trimming_diff_pair
, OPAMP_TRIM_VALUE_MASK
) ,
281 __OPAMP_OFFSET_TRIM_SET(hopamp3
, trimming_diff_pair
, *opamp3_trimmingvalue
) | tmp_opamp3_otr_otuser
);
284 /* Offset trimming time: during calibration, minimum time needed */
285 /* between two steps to have 1 mV accuracy. */
286 HAL_Delay(OPAMP_TRIMMING_DELAY
);
288 /* Divide range by 2 to continue dichotomy sweep */
291 /* Set trimming values for next iteration in function of trimming */
292 /* result toggle (versus initial state). */
293 /* Trimming values update with dichotomy delta of previous */
295 if (READ_BIT(OPAMP
->CSR
, __OPAMP_CSR_OPAXCALOUT(hopamp1
)) != tmp_Opa1calout_DefaultSate
)
297 /* If calibration output is has toggled, try lower trimming */
298 *opamp1_trimmingvalue
-= delta
;
302 /* If calibration output is has not toggled, try higher trimming */
303 *opamp1_trimmingvalue
+= delta
;
306 /* Set trimming values for next iteration in function of trimming */
307 /* result toggle (versus initial state). */
308 /* Trimming values update with dichotomy delta of previous */
310 if (READ_BIT(OPAMP
->CSR
, __OPAMP_CSR_OPAXCALOUT(hopamp2
)) != tmp_Opa2calout_DefaultSate
)
312 /* If calibration output is has toggled, try lower trimming */
313 *opamp2_trimmingvalue
-= delta
;
317 /* If calibration output is has not toggled, try higher trimming */
318 *opamp2_trimmingvalue
+= delta
;
321 /* Set trimming values for next iteration in function of trimming */
322 /* result toggle (versus initial state). */
323 /* Trimming values update with dichotomy delta of previous */
325 if (READ_BIT(OPAMP
->CSR
, __OPAMP_CSR_OPAXCALOUT(hopamp3
)) != tmp_Opa3calout_DefaultSate
)
327 /* If calibration output is has toggled, try lower trimming */
328 *opamp3_trimmingvalue
-= delta
;
332 /* If calibration output is has not toggled, try higher trimming */
333 *opamp3_trimmingvalue
+= delta
;
340 /* Disable calibration for P and N differential pairs */
341 /* Disable the selected opamp */
342 CLEAR_BIT (OPAMP
->CSR
, (OPAMP_CSR_OPAXCAL_H_ALL
|
343 OPAMP_CSR_OPAXCAL_L_ALL
|
344 OPAMP_CSR_OPAXPD_ALL
));
346 /* Backup of switches configuration to restore it at the end of the */
348 SET_BIT(OPAMP
->CSR
, tmp_OpaxSwitchesContextBackup
);
350 /* Self calibration is successful */
351 /* Store calibration (user trimming) results in init structure. */
353 /* Set user trimming mode */
354 hopamp1
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
355 hopamp2
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
356 hopamp3
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
358 /* Affect calibration parameters depending on mode normal/low power */
359 if (hopamp1
->Init
.PowerMode
!= OPAMP_POWERMODE_LOWPOWER
)
361 /* Write calibration result N */
362 hopamp1
->Init
.TrimmingValueN
= opamp1_trimmingvaluen
;
363 /* Write calibration result P */
364 hopamp1
->Init
.TrimmingValueP
= opamp1_trimmingvaluep
;
368 /* Write calibration result N */
369 hopamp1
->Init
.TrimmingValueNLowPower
= opamp1_trimmingvaluen
;
370 /* Write calibration result P */
371 hopamp1
->Init
.TrimmingValuePLowPower
= opamp1_trimmingvaluep
;
374 if (hopamp2
->Init
.PowerMode
!= OPAMP_POWERMODE_LOWPOWER
)
376 /* Write calibration result N */
377 hopamp2
->Init
.TrimmingValueN
= opamp2_trimmingvaluen
;
378 /* Write calibration result P */
379 hopamp2
->Init
.TrimmingValueP
= opamp2_trimmingvaluep
;
383 /* Write calibration result N */
384 hopamp2
->Init
.TrimmingValueNLowPower
= opamp2_trimmingvaluen
;
385 /* Write calibration result P */
386 hopamp2
->Init
.TrimmingValuePLowPower
= opamp2_trimmingvaluep
;
389 if (hopamp3
->Init
.PowerMode
!= OPAMP_POWERMODE_LOWPOWER
)
391 /* Write calibration result N */
392 hopamp3
->Init
.TrimmingValueN
= opamp3_trimmingvaluen
;
393 /* Write calibration result P */
394 hopamp3
->Init
.TrimmingValueP
= opamp3_trimmingvaluep
;
398 /* Write calibration result N */
399 hopamp3
->Init
.TrimmingValueNLowPower
= opamp3_trimmingvaluen
;
400 /* Write calibration result P */
401 hopamp3
->Init
.TrimmingValuePLowPower
= opamp3_trimmingvaluep
;
404 /* Update OPAMP state */
405 hopamp1
->State
= HAL_OPAMP_STATE_READY
;
406 hopamp2
->State
= HAL_OPAMP_STATE_READY
;
407 hopamp3
->State
= HAL_OPAMP_STATE_READY
;
412 /* OPAMP can not be calibrated from this mode */
422 /* 2 OPAMPS available */
423 /* 2 OPAMPS can be calibrated in parallel */
426 * @brief Run the self calibration of the 2 OPAMPs in parallel.
427 * @note Trimming values (PMOS & NMOS) are updated and user trimming is
428 * enabled is calibration is succesful.
429 * @note Calibration is performed in the mode specified in OPAMP init
430 * structure (mode normal or low-power). To perform calibration for
431 * both modes, repeat this function twice after OPAMP init structure
432 * accordingly updated.
433 * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
434 * and N transistors: 10 steps with 1 ms for each step).
435 * @param hopamp1 handle
436 * @param hopamp2 handle
439 HAL_StatusTypeDef
HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef
*hopamp1
, OPAMP_HandleTypeDef
*hopamp2
)
441 HAL_StatusTypeDef status
= HAL_OK
;
443 uint32_t* opamp1_trimmingvalue
= 0;
444 uint32_t opamp1_trimmingvaluen
= 0;
445 uint32_t opamp1_trimmingvaluep
= 0;
447 uint32_t* opamp2_trimmingvalue
= 0;
448 uint32_t opamp2_trimmingvaluen
= 0;
449 uint32_t opamp2_trimmingvaluep
= 0;
451 uint32_t trimming_diff_pair
= 0; /* Selection of differential transistors pair high or low */
453 __IO
uint32_t* tmp_opamp1_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
454 __IO
uint32_t* tmp_opamp2_reg_trimming
;
455 uint32_t tmp_opamp1_otr_otuser
= 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
456 uint32_t tmp_opamp2_otr_otuser
= 0;
458 uint32_t tmp_Opa1calout_DefaultSate
= 0; /* Bit OPAMP_CSR_OPA1CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
459 uint32_t tmp_Opa2calout_DefaultSate
= 0; /* Bit OPAMP_CSR_OPA2CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
461 uint32_t tmp_OpaxSwitchesContextBackup
= 0;
463 uint8_t trimming_diff_pair_iteration_count
= 0;
467 /* Check the OPAMP handle allocation */
468 /* Check if OPAMP locked */
469 if((hopamp1
== HAL_NULL
) || (hopamp1
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) ||
470 (hopamp2
== HAL_NULL
) || (hopamp2
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) )
477 /* Check if OPAMP in calibration mode and calibration not yet enable */
478 if((hopamp1
->State
== HAL_OPAMP_STATE_READY
) &&
479 (hopamp2
->State
== HAL_OPAMP_STATE_READY
) )
481 /* Check the parameter */
482 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1
->Instance
));
483 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2
->Instance
));
484 assert_param(IS_OPAMP_POWERMODE(hopamp1
->Init
.PowerMode
));
485 assert_param(IS_OPAMP_POWERMODE(hopamp2
->Init
.PowerMode
));
487 /* Update OPAMP state */
488 hopamp1
->State
= HAL_OPAMP_STATE_CALIBBUSY
;
489 hopamp2
->State
= HAL_OPAMP_STATE_CALIBBUSY
;
491 /* Backup of switches configuration to restore it at the end of the */
493 tmp_OpaxSwitchesContextBackup
= READ_BIT(OPAMP
->CSR
, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS
);
495 /* Open all switches on non-inverting input, inverting input and output */
497 CLEAR_BIT(OPAMP
->CSR
, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS
);
499 /* Set calibration mode to user programmed trimming values */
500 SET_BIT(OPAMP
->OTR
, OPAMP_OTR_OT_USER
);
502 /* Select trimming settings depending on power mode */
503 if (hopamp1
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
505 tmp_opamp1_otr_otuser
= OPAMP_OTR_OT_USER
;
506 tmp_opamp1_reg_trimming
= &OPAMP
->OTR
;
510 tmp_opamp1_otr_otuser
= 0x00000000;
511 tmp_opamp1_reg_trimming
= &OPAMP
->LPOTR
;
514 if (hopamp2
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
516 tmp_opamp2_otr_otuser
= OPAMP_OTR_OT_USER
;
517 tmp_opamp2_reg_trimming
= &OPAMP
->OTR
;
521 tmp_opamp2_otr_otuser
= 0x00000000;
522 tmp_opamp2_reg_trimming
= &OPAMP
->LPOTR
;
525 /* Enable the selected opamp */
526 CLEAR_BIT (OPAMP
->CSR
, OPAMP_CSR_OPAXPD_ALL
);
528 /* Perform trimming for both differential transistors pair high and low */
529 for (trimming_diff_pair_iteration_count
= 0; trimming_diff_pair_iteration_count
<=1; trimming_diff_pair_iteration_count
++)
531 if (trimming_diff_pair_iteration_count
== 0)
533 /* Calibration of transistors differential pair high (NMOS) */
534 trimming_diff_pair
= OPAMP_FACTORYTRIMMING_N
;
535 opamp1_trimmingvalue
= &opamp1_trimmingvaluen
;
536 opamp2_trimmingvalue
= &opamp2_trimmingvaluen
;
538 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
539 /* is 00000b. Used to detect the bit toggling during trimming. */
540 tmp_Opa1calout_DefaultSate
= RESET
;
541 tmp_Opa2calout_DefaultSate
= RESET
;
543 /* Enable calibration for N differential pair */
544 MODIFY_REG(OPAMP
->CSR
, OPAMP_CSR_OPAXCAL_L_ALL
,
545 OPAMP_CSR_OPAXCAL_H_ALL
);
547 else /* (trimming_diff_pair_iteration_count == 1) */
549 /* Calibration of transistors differential pair low (PMOS) */
550 trimming_diff_pair
= OPAMP_FACTORYTRIMMING_P
;
551 opamp1_trimmingvalue
= &opamp1_trimmingvaluep
;
552 opamp2_trimmingvalue
= &opamp2_trimmingvaluep
;
554 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
555 /* is 00000b. Used to detect the bit toggling during trimming. */
556 tmp_Opa1calout_DefaultSate
= __OPAMP_CSR_OPAXCALOUT(hopamp1
);
557 tmp_Opa2calout_DefaultSate
= __OPAMP_CSR_OPAXCALOUT(hopamp2
);
559 /* Enable calibration for P differential pair */
560 MODIFY_REG(OPAMP
->CSR
, OPAMP_CSR_OPAXCAL_H_ALL
,
561 OPAMP_CSR_OPAXCAL_L_ALL
);
565 /* Perform calibration parameter search by dichotomy sweep */
566 /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
567 /* initial range, then successive delta sweeps (8, 4, 2, 1). */
568 /* can extend the search range to +/- 15 units. */
569 /* - Trimming initial value 15: search range will go from 0 to 30 */
570 /* (Trimming value 31 is forbidden). */
571 *opamp1_trimmingvalue
= 15;
572 *opamp2_trimmingvalue
= 15;
577 /* Set candidate trimming */
579 MODIFY_REG(*tmp_opamp1_reg_trimming
, __OPAMP_OFFSET_TRIM_SET(hopamp1
, trimming_diff_pair
, OPAMP_TRIM_VALUE_MASK
) ,
580 __OPAMP_OFFSET_TRIM_SET(hopamp1
, trimming_diff_pair
, *opamp1_trimmingvalue
) | tmp_opamp1_otr_otuser
);
582 MODIFY_REG(*tmp_opamp2_reg_trimming
, __OPAMP_OFFSET_TRIM_SET(hopamp2
, trimming_diff_pair
, OPAMP_TRIM_VALUE_MASK
) ,
583 __OPAMP_OFFSET_TRIM_SET(hopamp2
, trimming_diff_pair
, *opamp2_trimmingvalue
) | tmp_opamp2_otr_otuser
);
586 /* Offset trimming time: during calibration, minimum time needed */
587 /* between two steps to have 1 mV accuracy. */
588 HAL_Delay(OPAMP_TRIMMING_DELAY
);
590 /* Divide range by 2 to continue dichotomy sweep */
593 /* Set trimming values for next iteration in function of trimming */
594 /* result toggle (versus initial state). */
595 if (READ_BIT(OPAMP
->CSR
, __OPAMP_CSR_OPAXCALOUT(hopamp1
)) != tmp_Opa1calout_DefaultSate
)
597 /* If calibration output is has toggled, try lower trimming */
598 *opamp1_trimmingvalue
-= delta
;
602 /* If calibration output is has not toggled, try higher trimming */
603 *opamp1_trimmingvalue
+= delta
;
606 /* Set trimming values for next iteration in function of trimming */
607 /* result toggle (versus initial state). */
608 if (READ_BIT(OPAMP
->CSR
, __OPAMP_CSR_OPAXCALOUT(hopamp2
)) != tmp_Opa2calout_DefaultSate
)
610 /* If calibration output is has toggled, try lower trimming */
611 *opamp2_trimmingvalue
-= delta
;
615 /* If calibration output is has not toggled, try higher trimming */
616 *opamp2_trimmingvalue
+= delta
;
623 /* Disable calibration for P and N differential pairs */
624 /* Disable the selected opamp */
625 CLEAR_BIT (OPAMP
->CSR
, (OPAMP_CSR_OPAXCAL_H_ALL
|
626 OPAMP_CSR_OPAXCAL_L_ALL
|
627 OPAMP_CSR_OPAXPD_ALL
));
629 /* Backup of switches configuration to restore it at the end of the */
631 SET_BIT(OPAMP
->CSR
, tmp_OpaxSwitchesContextBackup
);
633 /* Self calibration is successful */
634 /* Store calibration (user trimming) results in init structure. */
636 /* Set user trimming mode */
637 hopamp1
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
638 hopamp2
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
640 /* Affect calibration parameters depending on mode normal/low power */
641 if (hopamp1
->Init
.PowerMode
!= OPAMP_POWERMODE_LOWPOWER
)
643 /* Write calibration result N */
644 hopamp1
->Init
.TrimmingValueN
= opamp1_trimmingvaluen
;
645 /* Write calibration result P */
646 hopamp1
->Init
.TrimmingValueP
= opamp1_trimmingvaluep
;
650 /* Write calibration result N */
651 hopamp1
->Init
.TrimmingValueNLowPower
= opamp1_trimmingvaluen
;
652 /* Write calibration result P */
653 hopamp1
->Init
.TrimmingValuePLowPower
= opamp1_trimmingvaluep
;
656 if (hopamp2
->Init
.PowerMode
!= OPAMP_POWERMODE_LOWPOWER
)
658 /* Write calibration result N */
659 hopamp2
->Init
.TrimmingValueN
= opamp2_trimmingvaluen
;
660 /* Write calibration result P */
661 hopamp2
->Init
.TrimmingValueP
= opamp2_trimmingvaluep
;
665 /* Write calibration result N */
666 hopamp2
->Init
.TrimmingValueNLowPower
= opamp2_trimmingvaluen
;
667 /* Write calibration result P */
668 hopamp2
->Init
.TrimmingValuePLowPower
= opamp2_trimmingvaluep
;
671 /* Update OPAMP state */
672 hopamp1
->State
= HAL_OPAMP_STATE_READY
;
673 hopamp2
->State
= HAL_OPAMP_STATE_READY
;
678 /* OPAMP can not be calibrated from this mode */
686 #endif /* STM32L151xD || STM32L152xD || STM32L162xD */
692 /** @defgroup OPAMPEx_Exported_Functions_Group2 Extended Peripheral Control functions
693 * @brief Extended control functions
696 ===============================================================================
697 ##### Peripheral Control functions #####
698 ===============================================================================
707 * @brief Unlock the selected opamp configuration.
708 * This function must be called only when OPAMP is in state "locked".
709 * @param hopamp: OPAMP handle
712 HAL_StatusTypeDef
HAL_OPAMPEx_Unlock(OPAMP_HandleTypeDef
* hopamp
)
714 HAL_StatusTypeDef status
= HAL_OK
;
716 /* Check the OPAMP handle allocation */
717 /* Check if OPAMP locked */
718 if((hopamp
== HAL_NULL
) || (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
719 || (hopamp
->State
== HAL_OPAMP_STATE_READY
)
720 || (hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
721 || (hopamp
->State
== HAL_OPAMP_STATE_BUSY
))
728 /* Check the parameter */
729 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
731 /* OPAMP state changed to locked */
732 hopamp
->State
= HAL_OPAMP_STATE_BUSY
;
746 #endif /* STM32L151xCA || STM32L151xD || STM32L152xCA || STM32L152xD || STM32L162xCA || STM32L162xD || STM32L151xE || STM32L152xE || STM32L162xE || STM32L162xC || STM32L152xC || STM32L151xC */
748 #endif /* HAL_OPAMP_MODULE_ENABLED */
757 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/