2 ******************************************************************************
3 * @file stm32f3xx_hal_opamp_ex.c
4 * @author MCD Application Team
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 "stm32f3xx_hal.h"
48 /** @addtogroup STM32F3xx_HAL_Driver
52 /** @defgroup OPAMPEx OPAMP Extended HAL module driver
53 * @brief OPAMP Extended HAL module driver.
57 #ifdef HAL_OPAMP_MODULE_ENABLED
59 /* Private typedef -----------------------------------------------------------*/
60 /* Private define ------------------------------------------------------------*/
61 /* Private macro -------------------------------------------------------------*/
62 /* Private variables ---------------------------------------------------------*/
63 /* Private function prototypes -----------------------------------------------*/
64 /* Exported functions ---------------------------------------------------------*/
66 /** @defgroup OPAMPEx_Exported_Functions OPAMP Extended Exported Functions
71 /** @defgroup OPAMPEx_Exported_Functions_Group1 Extended Input and Output operation functions
72 * @brief Extended Self calibration functions
75 ===============================================================================
76 ##### Extended IO operation functions #####
77 ===============================================================================
84 #if defined(STM32F302xE) || \
86 /* 2 OPAMPS available */
87 /* 2 OPAMPS can be calibrated in parallel */
90 * @brief Run the self calibration of 2 OPAMPs in parallel.
91 * @param hopamp1 handle
92 * @param hopamp2 handle
94 * @note Updated offset trimming values (PMOS & NMOS), user trimming is enabled
95 * @note Calibration runs about 25 ms.
98 HAL_StatusTypeDef
HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef
*hopamp1
, OPAMP_HandleTypeDef
*hopamp2
)
100 HAL_StatusTypeDef status
= HAL_OK
;
102 uint32_t trimmingvaluen1
= 0;
103 uint32_t trimmingvaluep1
= 0;
104 uint32_t trimmingvaluen2
= 0;
105 uint32_t trimmingvaluep2
= 0;
109 if((hopamp1
== HAL_NULL
) || (hopamp1
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) || \
110 (hopamp2
== HAL_NULL
) || (hopamp2
->State
== HAL_OPAMP_STATE_BUSYLOCKED
))
117 /* Check if OPAMP in calibration mode and calibration not yet enable */
118 if((hopamp1
->State
== HAL_OPAMP_STATE_READY
) && (hopamp2
->State
== HAL_OPAMP_STATE_READY
))
120 /* Check the parameter */
121 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1
->Instance
));
122 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2
->Instance
));
124 /* Set Calibration mode */
125 /* Non-inverting input connected to calibration reference voltage. */
126 SET_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
127 SET_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
129 /* user trimming values are used for offset calibration */
130 SET_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
131 SET_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
133 /* Enable calibration */
134 SET_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_CALON
);
135 SET_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_CALON
);
137 /* 1st calibration - N */
138 /* Select 90% VREF */
139 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
140 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
142 /* Enable the opamps */
143 SET_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
144 SET_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
146 /* Init trimming counter */
148 trimmingvaluen1
= 16;
149 trimmingvaluen2
= 16;
154 // Set candidate trimming */
155 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
156 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
158 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
159 /* Offset trim time: during calibration, minimum time needed between */
160 /* two steps to have 1 mV accuracy */
163 if (hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
165 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
166 trimmingvaluen1
+= delta
;
170 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
171 trimmingvaluen1
-= delta
;
174 if (hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
176 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
177 trimmingvaluen2
+= delta
;
181 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
182 trimmingvaluen2
-= delta
;
188 // Still need to check if righ calibration is current value or un step below
189 // Indeed the first value that causes the OUTCAL bit to change from 1 to 0
190 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
191 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
193 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
194 /* Offset trim time: during calibration, minimum time needed between */
195 /* two steps to have 1 mV accuracy */
198 if (hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
200 /* OPAMP_CSR_OUTCAL is actually one value more */
202 /* Set right trimming */
203 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
206 if (hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
208 /* OPAMP_CSR_OUTCAL is actually one value more */
210 /* Set right trimming */
211 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
215 /* 2nd calibration - P */
216 /* Select 10% VREF */
217 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
218 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
220 /* Init trimming counter */
222 trimmingvaluep1
= 16;
223 trimmingvaluep2
= 16;
228 // Set candidate trimming */
229 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
230 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
232 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
233 /* Offset trim time: during calibration, minimum time needed between */
234 /* two steps to have 1 mV accuracy */
237 if (hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
239 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
240 trimmingvaluep1
+= delta
;
244 trimmingvaluep1
-= delta
;
247 if (hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
249 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
250 trimmingvaluep2
+= delta
;
254 trimmingvaluep2
-= delta
;
260 // Still need to check if righ calibration is current value or un step below
261 // Indeed the first value that causes the OUTCAL bit to change from 1 to 0
262 // Set candidate trimming */
263 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
264 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
266 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
267 /* Offset trim time: during calibration, minimum time needed between */
268 /* two steps to have 1 mV accuracy */
271 if (hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
273 /* OPAMP_CSR_OUTCAL is actually one value more */
275 /* Set right trimming */
276 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
279 if (hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
)
281 /* OPAMP_CSR_OUTCAL is actually one value more */
283 /* Set right trimming */
284 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
287 /* Disable calibration */
288 CLEAR_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_CALON
);
289 CLEAR_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_CALON
);
291 /* Disable the OPAMPs */
292 CLEAR_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
293 CLEAR_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
295 /* Set normale operating mode back */
296 CLEAR_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
297 CLEAR_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
299 /* Self calibration is successful */
300 /* Store calibration(user timming) results in init structure. */
301 /* Select user timming mode */
303 /* Write calibration result N */
304 hopamp1
->Init
.TrimmingValueN
= trimmingvaluen1
;
305 hopamp2
->Init
.TrimmingValueN
= trimmingvaluen2
;
307 /* Write calibration result P */
308 hopamp1
->Init
.TrimmingValueP
= trimmingvaluep1
;
309 hopamp2
->Init
.TrimmingValueP
= trimmingvaluep2
;
312 hopamp1
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
313 hopamp2
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
315 /* Select user timming mode */
316 /* And updated with calibrated settings */
317 hopamp1
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
318 hopamp2
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
320 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
321 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
323 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
324 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
330 /* At least one OPAMP can not be calibrated */
337 #endif /* STM32F302xE || */
340 #if defined(STM32F303xE) || defined(STM32F398xx) || \
341 defined(STM32F303xC) || defined(STM32F358xx)
342 /* 4 OPAMPS available */
343 /* 4 OPAMPS can be calibrated in parallel */
346 * @brief Run the self calibration of 4 OPAMPs in parallel.
347 * @param hopamp1 handle
348 * @param hopamp2 handle
349 * @param hopamp3 handle
350 * @param hopamp4 handle
352 * @note Updated offset trimming values (PMOS & NMOS), user trimming is enabled
353 * @note Calibration runs about 25 ms.
356 HAL_StatusTypeDef
HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef
*hopamp1
, OPAMP_HandleTypeDef
*hopamp2
, OPAMP_HandleTypeDef
*hopamp3
, OPAMP_HandleTypeDef
*hopamp4
)
358 HAL_StatusTypeDef status
= HAL_OK
;
360 uint32_t trimmingvaluen1
= 0;
361 uint32_t trimmingvaluep1
= 0;
362 uint32_t trimmingvaluen2
= 0;
363 uint32_t trimmingvaluep2
= 0;
364 uint32_t trimmingvaluen3
= 0;
365 uint32_t trimmingvaluep3
= 0;
366 uint32_t trimmingvaluen4
= 0;
367 uint32_t trimmingvaluep4
= 0;
371 if((hopamp1
== HAL_NULL
) || (hopamp1
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) || \
372 (hopamp2
== HAL_NULL
) || (hopamp2
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) || \
373 (hopamp3
== HAL_NULL
) || (hopamp3
->State
== HAL_OPAMP_STATE_BUSYLOCKED
) || \
374 (hopamp4
== HAL_NULL
) || (hopamp4
->State
== HAL_OPAMP_STATE_BUSYLOCKED
))
381 /* Check if OPAMP in calibration mode and calibration not yet enable */
382 if((hopamp1
->State
== HAL_OPAMP_STATE_READY
) && (hopamp2
->State
== HAL_OPAMP_STATE_READY
) && \
383 (hopamp3
->State
== HAL_OPAMP_STATE_READY
) && (hopamp4
->State
== HAL_OPAMP_STATE_READY
))
385 /* Check the parameter */
386 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1
->Instance
));
387 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2
->Instance
));
388 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp3
->Instance
));
389 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp4
->Instance
));
391 /* Set Calibration mode */
392 /* Non-inverting input connected to calibration reference voltage. */
393 SET_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
394 SET_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
395 SET_BIT(hopamp3
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
396 SET_BIT(hopamp4
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
398 /* user trimming values are used for offset calibration */
399 SET_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
400 SET_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
401 SET_BIT(hopamp3
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
402 SET_BIT(hopamp4
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
404 /* Enable calibration */
405 SET_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_CALON
);
406 SET_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_CALON
);
407 SET_BIT (hopamp3
->Instance
->CSR
, OPAMP_CSR_CALON
);
408 SET_BIT (hopamp4
->Instance
->CSR
, OPAMP_CSR_CALON
);
410 /* 1st calibration - N */
411 /* Select 90% VREF */
412 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
413 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
414 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
415 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
417 /* Enable the opamps */
418 SET_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
419 SET_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
420 SET_BIT (hopamp3
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
421 SET_BIT (hopamp4
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
423 /* Init trimming counter */
425 trimmingvaluen1
= 16;
426 trimmingvaluen2
= 16;
427 trimmingvaluen3
= 16;
428 trimmingvaluen4
= 16;
433 /* Set candidate trimming */
434 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
435 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
436 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen3
<<OPAMP_INPUT_INVERTING
);
437 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen4
<<OPAMP_INPUT_INVERTING
);
439 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
440 /* Offset trim time: during calibration, minimum time needed between */
441 /* two steps to have 1 mV accuracy */
444 if ((hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
446 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
447 trimmingvaluen1
+= delta
;
451 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
452 trimmingvaluen1
-= delta
;
455 if ((hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
457 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
458 trimmingvaluen2
+= delta
;
462 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
463 trimmingvaluen2
-= delta
;
466 if ((hopamp3
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
468 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
469 trimmingvaluen3
+= delta
;
473 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
474 trimmingvaluen3
-= delta
;
477 if ((hopamp4
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
479 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
480 trimmingvaluen4
+= delta
;
484 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
485 trimmingvaluen4
-= delta
;
491 /* Still need to check if righ calibration is current value or un step below */
492 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
493 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
494 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
495 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen3
<<OPAMP_INPUT_INVERTING
);
496 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen4
<<OPAMP_INPUT_INVERTING
);
498 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
499 /* Offset trim time: during calibration, minimum time needed between */
500 /* two steps to have 1 mV accuracy */
503 if ((hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
505 /* OPAMP_CSR_OUTCAL is actually one value more */
507 /* Set right trimming */
508 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
511 if ((hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
513 /* OPAMP_CSR_OUTCAL is actually one value more */
515 /* Set right trimming */
516 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
519 if ((hopamp3
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
521 /* OPAMP_CSR_OUTCAL is actually one value more */
523 /* Set right trimming */
524 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen3
<<OPAMP_INPUT_INVERTING
);
527 if ((hopamp4
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
529 /* OPAMP_CSR_OUTCAL is actually one value more */
531 /* Set right trimming */
532 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen4
<<OPAMP_INPUT_INVERTING
);
535 /* 2nd calibration - P */
536 /* Select 10% VREF */
537 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
538 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
539 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
540 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
542 /* Init trimming counter */
544 trimmingvaluep1
= 16;
545 trimmingvaluep2
= 16;
546 trimmingvaluep3
= 16;
547 trimmingvaluep4
= 16;
553 /* Set candidate trimming */
554 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
555 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
556 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep3
<<OPAMP_INPUT_NONINVERTING
);
557 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep4
<<OPAMP_INPUT_NONINVERTING
);
559 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
560 /* Offset trim time: during calibration, minimum time needed between */
561 /* two steps to have 1 mV accuracy */
564 if ((hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
566 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
567 trimmingvaluep1
+= delta
;
571 trimmingvaluep1
-= delta
;
574 if ((hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
576 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
577 trimmingvaluep2
+= delta
;
581 trimmingvaluep2
-= delta
;
584 if ((hopamp3
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
586 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
587 trimmingvaluep3
+= delta
;
591 trimmingvaluep3
-= delta
;
594 if ((hopamp4
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
596 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
597 trimmingvaluep4
+= delta
;
601 trimmingvaluep4
-= delta
;
607 /* Still need to check if righ calibration is current value or un step below */
608 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
609 /* Set candidate trimming */
610 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
611 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
612 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep3
<<OPAMP_INPUT_NONINVERTING
);
613 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep4
<<OPAMP_INPUT_NONINVERTING
);
615 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
616 /* Offset trim time: during calibration, minimum time needed between */
617 /* two steps to have 1 mV accuracy */
620 if ((hopamp1
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
622 /* OPAMP_CSR_OUTCAL is actually one value more */
624 /* Set right trimming */
625 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
628 if ((hopamp2
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
630 /* OPAMP_CSR_OUTCAL is actually one value more */
632 /* Set right trimming */
633 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
636 if ((hopamp3
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
638 /* OPAMP_CSR_OUTCAL is actually one value more */
640 /* Set right trimming */
641 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep3
<<OPAMP_INPUT_NONINVERTING
);
644 if ((hopamp4
->Instance
->CSR
& OPAMP_CSR_OUTCAL
) != RESET
)
646 /* OPAMP_CSR_OUTCAL is actually one value more */
648 /* Set right trimming */
649 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep4
<<OPAMP_INPUT_NONINVERTING
);
652 /* Disable calibration */
653 CLEAR_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_CALON
);
654 CLEAR_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_CALON
);
655 CLEAR_BIT (hopamp3
->Instance
->CSR
, OPAMP_CSR_CALON
);
656 CLEAR_BIT (hopamp4
->Instance
->CSR
, OPAMP_CSR_CALON
);
658 /* Disable the OPAMPs */
659 CLEAR_BIT (hopamp1
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
660 CLEAR_BIT (hopamp2
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
661 CLEAR_BIT (hopamp3
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
662 CLEAR_BIT (hopamp4
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
664 /* Set normal operating mode back */
665 CLEAR_BIT(hopamp1
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
666 CLEAR_BIT(hopamp2
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
667 CLEAR_BIT(hopamp3
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
668 CLEAR_BIT(hopamp4
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
670 /* Self calibration is successful */
671 /* Store calibration(user timming) results in init structure. */
672 /* Select user timming mode */
674 /* Write calibration result N */
675 hopamp1
->Init
.TrimmingValueN
= trimmingvaluen1
;
676 hopamp2
->Init
.TrimmingValueN
= trimmingvaluen2
;
677 hopamp3
->Init
.TrimmingValueN
= trimmingvaluen3
;
678 hopamp4
->Init
.TrimmingValueN
= trimmingvaluen4
;
680 /* Write calibration result P */
681 hopamp1
->Init
.TrimmingValueP
= trimmingvaluep1
;
682 hopamp2
->Init
.TrimmingValueP
= trimmingvaluep2
;
683 hopamp3
->Init
.TrimmingValueP
= trimmingvaluep3
;
684 hopamp4
->Init
.TrimmingValueP
= trimmingvaluep4
;
686 /* Select user timming mode */
687 /* And updated with calibrated settings */
688 hopamp1
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
689 hopamp2
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
690 hopamp3
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
691 hopamp4
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
693 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen1
<<OPAMP_INPUT_INVERTING
);
694 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen2
<<OPAMP_INPUT_INVERTING
);
695 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen3
<<OPAMP_INPUT_INVERTING
);
696 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETN
, trimmingvaluen4
<<OPAMP_INPUT_INVERTING
);
698 MODIFY_REG(hopamp1
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep1
<<OPAMP_INPUT_NONINVERTING
);
699 MODIFY_REG(hopamp2
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep2
<<OPAMP_INPUT_NONINVERTING
);
700 MODIFY_REG(hopamp3
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep3
<<OPAMP_INPUT_NONINVERTING
);
701 MODIFY_REG(hopamp4
->Instance
->CSR
, OPAMP_CSR_TRIMOFFSETP
, trimmingvaluep4
<<OPAMP_INPUT_NONINVERTING
);
707 /* At least one OPAMP can not be calibrated */
714 #endif /* STM32F303xE || STM32F398xx || */
715 /* STM32F303xC || STM32F358xx */
725 #endif /* HAL_OPAMP_MODULE_ENABLED */
734 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/