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****/