2 ******************************************************************************
3 * @file stm32h7xx_hal_opamp.c
4 * @author MCD Application Team
5 * @brief OPAMP HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the operational amplifier(s) peripheral:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
13 ******************************************************************************
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
23 ******************************************************************************
25 ================================================================================
26 ##### OPAMP Peripheral Features #####
27 ================================================================================
29 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
31 (#) The OPAMP(s) provides several exclusive running modes.
33 (++) Programmable Gain Amplifier (PGA) modes
36 (#) Each OPAMP(s) can be configured in normal and high speed mode.
38 (#) The OPAMP(s) provide(s) calibration capabilities.
39 (++) Calibration aims at correcting some offset for running mode.
40 (++) The OPAMP uses either factory calibration settings OR user defined
41 calibration (trimming) settings (i.e. trimming mode).
42 (++) The user defined settings can be figured out using self calibration
43 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
44 (++) HAL_OPAMP_SelfCalibrate:
45 (+++) Runs automatically the calibration in 2 steps.
46 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
47 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
48 appropriate and enough in most cases).
49 (+++) Runs automatically the calibration.
50 (+++) Enables the user trimming mode
51 (+++) Updates the init structure with trimming values with fresh calibration
53 The user may store the calibration results for larger
54 (ex monitoring the trimming as a function of temperature
56 (+++) HAL_OPAMPEx_SelfCalibrateAll
57 runs calibration of all OPAMPs in parallel to save search time.
59 (#) Running mode: Standalone mode
60 (++) Gain is set externally (gain depends on external loads).
61 (++) Follower mode also possible externally by connecting the inverting input to
64 (#) Running mode: Follower mode
65 (++) No Inverting Input is connected.
67 (#) Running mode: Programmable Gain Amplifier (PGA) mode
68 (Resistor feedback output)
69 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
71 (#) OPAMP gain can be selected as :
73 (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
74 (+++) VREF- referenced.
75 (+++) Filtering on VINM0, VREF- referenced.
76 (+++) VINM0 node for bias voltage and VINP0 for input signal.
77 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
79 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
80 (+++) VINM0 node for input signal and VINP0 for bias.
81 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
83 (#) The OPAMPs inverting input can be selected according to the Reference Manual
84 "OPAMP functional description" chapter.
86 (#) The OPAMPs non inverting input can be selected according to the Reference Manual
87 "OPAMP functional description" chapter.
90 ##### How to use this driver #####
91 ================================================================================
94 *** High speed / normal power mode ***
95 ============================================
96 [..] To run in high speed mode:
98 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
99 (++) Select OPAMP_POWERMODE_HIGHSPEED
100 (++) Otherwise select OPAMP_POWERMODE_NORMAL
103 ============================================
104 [..] To run the OPAMP calibration self calibration:
106 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
107 Store the calibration results.
110 ============================================
112 [..] To use the OPAMP, perform the following steps:
114 (#) Fill in the HAL_OPAMP_MspInit() to
115 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
116 (++) Configure the OPAMP input AND output in analog mode using
117 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
119 (#) Registrate Callbacks
120 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
121 allows the user to configure dynamically the driver callbacks.
123 (++) Use Functions HAL_OPAMP_RegisterCallback() to register a user callback,
124 it allows to register following callbacks:
125 (+++) MspInitCallback : OPAMP MspInit.
126 (+++) MspDeInitCallback : OPAMP MspDeInit.
127 This function takes as parameters the HAL peripheral handle, the Callback ID
128 and a pointer to the user callback function.
130 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
131 weak (overridden) function. It allows to reset following callbacks:
132 (+++) MspInitCallback : OPAMP MspInit.
133 (+++) MspDeInitCallback : OPAMP MspDeInit.
135 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
137 (++) Select the inverting input
138 (++) Select the non-inverting input
139 (++) If PGA mode is enabled, Select if inverting input is connected.
140 (++) Select either factory or user defined trimming mode.
141 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
142 (typically values set by HAL_OPAMP_SelfCalibrate function).
144 (#) Enable the OPAMP using HAL_OPAMP_Start() function.
146 (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
148 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
149 Caution: On STM32H7, HAL OPAMP lock is software lock only (not
150 hardware lock as on some other STM32 devices)
152 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
154 *** Running mode: change of configuration while OPAMP ON ***
155 ============================================
156 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
157 (#) If needed, fill in the HAL_OPAMP_MspInit()
158 (++) This is the case for instance if you wish to use new OPAMP I/O
160 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
161 (++) As in configure case, select first the parameters you wish to modify.
163 (#) Change from high speed mode to normal power mode (& vice versa) requires
164 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
165 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
169 ******************************************************************************
170 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
172 +------------------------------------------------------------------------|
173 | | | OPAMP1 | OPAMP2 |
174 |-----------------|---------|----------------------|---------------------|
175 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
176 | | | VINM1-> PA7 | VINM1-> PG1 |
177 | | | Internal: | Internal: |
178 | | | ADC1_IN9 | OPAMP2_OUT |
179 | | | ADC2_IN9 | PGA mode |
182 |-----------------|---------|----------------------|---------------------|
183 | Non Inverting | VP_SEL | | |
184 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
185 | | | Internal: | Internal: |
186 | Input | | DAC1_CH1_int | DAC1_CH2_int |
187 | | | ADC1_IN8 | DAC2_CH1_int |
188 | | | ADC2_IN8 | COMP2_INP |
190 +------------------------------------------------------------------------|
193 [..] Table 2. OPAMPs outputs for the STM32H7 devices:
195 +-------------------------------------------------------------------------
196 | | | OPAMP1 | OPAMP2 |
197 |-----------------|--------|-----------------------|---------------------|
198 | Output | VOUT | PC4 | PE7 |
199 | | | & ADC1_IN4| | & COMP2_INN7 if |
200 | | | ADC2_IN4 |connected internally |
201 | | | COMP1_INN7 if | |
202 | | | connected internally | |
203 |-----------------|--------|-----------------------|---------------------|
206 /* Includes ------------------------------------------------------------------*/
207 #include "stm32h7xx_hal.h"
209 /** @addtogroup STM32H7xx_HAL_Driver
213 /** @defgroup OPAMP OPAMP
214 * @brief OPAMP module driver
218 #ifdef HAL_OPAMP_MODULE_ENABLED
220 /* Private types -------------------------------------------------------------*/
221 /* Private variables ---------------------------------------------------------*/
222 /* Private constants ---------------------------------------------------------*/
223 /** @addtogroup OPAMP_Private_Constants
227 /* CSR register reset value */
228 #define OPAMP_CSR_RESET_VALUE 0x00000000U
232 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
233 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
236 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
237 | OPAMP_CSR_USERTRIM)
240 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
241 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
246 /* Private macros ------------------------------------------------------------*/
247 /* Private functions ---------------------------------------------------------*/
248 /* Exported functions --------------------------------------------------------*/
250 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
254 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
255 * @brief Initialization and Configuration functions
258 ==============================================================================
259 ##### Initialization and de-initialization functions #####
260 ==============================================================================
267 * @brief Initialize the OPAMP according to the specified
268 * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
269 * @note If the selected opamp is locked, initialization can't be performed.
270 * To unlock the configuration, perform a system reset.
271 * @param hopamp OPAMP handle
274 HAL_StatusTypeDef
HAL_OPAMP_Init(OPAMP_HandleTypeDef
*hopamp
)
276 HAL_StatusTypeDef status
= HAL_OK
;
277 uint32_t updateotrlpotr
;
279 /* Check the OPAMP handle allocation and lock status */
280 /* Init not allowed if calibration is ongoing */
285 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
289 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
295 /* Check the parameter */
296 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
298 /* Set OPAMP parameters */
299 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
300 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp
->Init
.Mode
));
301 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp
->Init
.NonInvertingInput
));
303 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
304 if(hopamp
->State
== HAL_OPAMP_STATE_RESET
)
306 if(hopamp
->MspInitCallback
== NULL
)
308 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
311 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
312 if ((hopamp
->Init
.Mode
) == OPAMP_STANDALONE_MODE
)
314 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp
->Init
.InvertingInput
));
317 if ((hopamp
->Init
.Mode
) == OPAMP_PGA_MODE
)
319 assert_param(IS_OPAMP_PGA_GAIN(hopamp
->Init
.PgaGain
));
320 assert_param(IS_OPAMP_PGACONNECT(hopamp
->Init
.PgaConnect
));
324 assert_param(IS_OPAMP_TRIMMING(hopamp
->Init
.UserTrimming
));
326 if ((hopamp
->Init
.UserTrimming
) == OPAMP_TRIMMING_USER
)
328 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
330 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueP
));
331 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueN
));
335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValuePHighSpeed
));
336 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueNHighSpeed
));
340 if(hopamp
->State
== HAL_OPAMP_STATE_RESET
)
342 /* Allocate lock resource and initialize it */
343 hopamp
->Lock
= HAL_UNLOCKED
;
346 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
347 hopamp
->MspInitCallback(hopamp
);
349 /* Call MSP init function */
350 HAL_OPAMP_MspInit(hopamp
);
351 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
353 /* Set operating mode */
354 CLEAR_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
355 /* In PGA mode InvertingInput is Not Applicable */
356 if (hopamp
->Init
.Mode
== OPAMP_PGA_MODE
)
358 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_PGA
, \
359 hopamp
->Init
.PowerMode
| \
360 hopamp
->Init
.Mode
| \
361 hopamp
->Init
.PgaGain
| \
362 hopamp
->Init
.PgaConnect
| \
363 hopamp
->Init
.NonInvertingInput
| \
364 hopamp
->Init
.UserTrimming
);
367 if (hopamp
->Init
.Mode
== OPAMP_FOLLOWER_MODE
)
369 /* In Follower mode InvertingInput is Not Applicable */
370 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_FOLLOWER
, \
371 hopamp
->Init
.PowerMode
| \
372 hopamp
->Init
.Mode
| \
373 hopamp
->Init
.NonInvertingInput
| \
374 hopamp
->Init
.UserTrimming
);
377 if (hopamp
->Init
.Mode
== OPAMP_STANDALONE_MODE
)
379 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_STANDALONE
, \
380 hopamp
->Init
.PowerMode
| \
381 hopamp
->Init
.Mode
| \
382 hopamp
->Init
.InvertingInput
| \
383 hopamp
->Init
.NonInvertingInput
| \
384 hopamp
->Init
.UserTrimming
);
387 if (hopamp
->Init
.UserTrimming
== OPAMP_TRIMMING_USER
)
389 /* Set power mode and associated calibration parameters */
390 if (hopamp
->Init
.PowerMode
!= OPAMP_POWERMODE_HIGHSPEED
)
392 /* OPAMP_POWERMODE_NORMAL */
393 /* Set calibration mode (factory or user) and values for */
394 /* transistors differential pair high (PMOS) and low (NMOS) for */
396 updateotrlpotr
= (((hopamp
->Init
.TrimmingValueP
) << (OPAMP_INPUT_NONINVERTING
)) \
397 | (hopamp
->Init
.TrimmingValueN
));
398 MODIFY_REG(hopamp
->Instance
->OTR
, OPAMP_OTR_TRIMOFFSETN
| OPAMP_OTR_TRIMOFFSETP
, updateotrlpotr
);
402 /* OPAMP_POWERMODE_HIGHSPEED*/
403 /* transistors differential pair high (PMOS) and low (NMOS) for */
404 /* high speed mode. */
405 updateotrlpotr
= (((hopamp
->Init
.TrimmingValuePHighSpeed
) << (OPAMP_INPUT_NONINVERTING
)) \
406 | (hopamp
->Init
.TrimmingValueNHighSpeed
));
407 MODIFY_REG(hopamp
->Instance
->HSOTR
, OPAMP_OTR_TRIMOFFSETN
| OPAMP_OTR_TRIMOFFSETP
, updateotrlpotr
);
411 /* Update the OPAMP state*/
412 if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
414 /* From RESET state to READY State */
415 hopamp
->State
= HAL_OPAMP_STATE_READY
;
417 /* else: remain in READY or BUSY state (no update) */
423 * @brief DeInitialize the OPAMP peripheral
424 * @note Deinitialization can be performed if the OPAMP configuration is locked.
425 * (the lock is SW in H7)
426 * @param hopamp OPAMP handle
429 HAL_StatusTypeDef
HAL_OPAMP_DeInit(OPAMP_HandleTypeDef
*hopamp
)
431 HAL_StatusTypeDef status
= HAL_OK
;
433 /* Check the OPAMP handle allocation */
434 /* DeInit not allowed if calibration is on going */
439 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
445 /* Check the parameter */
446 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
448 /* Set OPAMP_CSR register to reset value */
449 WRITE_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_RESET_VALUE
);
451 /* DeInit the low level hardware */
452 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
453 if(hopamp
->MspDeInitCallback
== NULL
)
455 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
457 /* DeInit the low level hardware */
458 hopamp
->MspDeInitCallback(hopamp
);
460 HAL_OPAMP_MspDeInit(hopamp
);
461 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
463 /* Update the OPAMP state*/
464 hopamp
->State
= HAL_OPAMP_STATE_RESET
;
465 /* Process unlocked */
466 __HAL_UNLOCK(hopamp
);
475 * @brief Initialize the OPAMP MSP.
476 * @param hopamp OPAMP handle
479 __weak
void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef
*hopamp
)
481 /* Prevent unused argument(s) compilation warning */
484 /* NOTE : This function should not be modified, when the callback is needed,
485 the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
490 * @brief DeInitialize OPAMP MSP.
491 * @param hopamp OPAMP handle
494 __weak
void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef
*hopamp
)
496 /* Prevent unused argument(s) compilation warning */
498 /* NOTE : This function should not be modified, when the callback is needed,
499 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
508 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
509 * @brief IO operation functions
512 ===============================================================================
513 ##### IO operation functions #####
514 ===============================================================================
516 This subsection provides a set of functions allowing to manage the OPAMP
517 start, stop and calibration actions.
524 * @brief Start the OPAMP.
525 * @param hopamp OPAMP handle
528 HAL_StatusTypeDef
HAL_OPAMP_Start(OPAMP_HandleTypeDef
*hopamp
)
530 HAL_StatusTypeDef status
= HAL_OK
;
532 /* Check the OPAMP handle allocation */
533 /* Check if OPAMP locked */
538 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
544 /* Check the parameter */
545 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
547 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
549 /* Enable the selected opamp */
550 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
552 /* Update the OPAMP state*/
553 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
554 hopamp
->State
= HAL_OPAMP_STATE_BUSY
;
566 * @brief Stop the OPAMP.
567 * @param hopamp OPAMP handle
570 HAL_StatusTypeDef
HAL_OPAMP_Stop(OPAMP_HandleTypeDef
*hopamp
)
572 HAL_StatusTypeDef status
= HAL_OK
;
574 /* Check the OPAMP handle allocation */
575 /* Check if OPAMP locked */
576 /* Check if OPAMP calibration ongoing */
581 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
585 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
591 /* Check the parameter */
592 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
594 if(hopamp
->State
== HAL_OPAMP_STATE_BUSY
)
596 /* Disable the selected opamp */
597 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
599 /* Update the OPAMP state*/
600 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
601 hopamp
->State
= HAL_OPAMP_STATE_READY
;
612 * @brief Run the self calibration of one OPAMP.
613 * @note Calibration is performed in the mode specified in OPAMP init
614 * structure (mode normal or high-speed). To perform calibration for
615 * both modes, repeat this function twice after OPAMP init structure
616 * accordingly updated.
617 * @param hopamp handle
618 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
621 HAL_StatusTypeDef
HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef
*hopamp
)
624 HAL_StatusTypeDef status
= HAL_OK
;
626 uint32_t trimmingvaluen
;
627 uint32_t trimmingvaluep
;
631 __IO
uint32_t* tmp_opamp_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
633 /* Check the OPAMP handle allocation */
634 /* Check if OPAMP locked */
639 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
646 /* Check if OPAMP in calibration mode and calibration not yet enable */
647 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
649 /* Check the parameter */
650 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
651 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
653 opampmode
= READ_BIT(hopamp
->Instance
->CSR
,OPAMP_CSR_VMSEL
);
655 /* Use of standalone mode */
656 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_VMSEL
, OPAMP_STANDALONE_MODE
);
657 /* user trimming values are used for offset calibration */
658 SET_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
660 /* Select trimming settings depending on power mode */
661 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
663 tmp_opamp_reg_trimming
= &hopamp
->Instance
->OTR
;
668 /* high speed Mode */
669 tmp_opamp_reg_trimming
= &hopamp
->Instance
->HSOTR
;
673 /* Enable calibration */
674 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
676 /* Force internal reference on VP */
677 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
679 /* 1st calibration - N */
680 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
682 /* Enable the selected opamp */
683 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
685 /* Init trimming counter */
687 trimmingvaluen
= 16U;
692 /* Set candidate trimming */
693 /* OPAMP_POWERMODE_NORMAL */
694 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
696 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
697 /* Offset trim time: during calibration, minimum time needed between */
698 /* two steps to have 1 mV accuracy */
699 HAL_Delay(OPAMP_TRIMMING_DELAY
);
701 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
) != 0U)
703 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
704 trimmingvaluen
+= delta
;
708 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
709 trimmingvaluen
-= delta
;
711 /* Divide range by 2 to continue dichotomy sweep */
715 /* Still need to check if right calibration is current value or one step below */
716 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
718 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
720 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
721 /* Offset trim time: during calibration, minimum time needed between */
722 /* two steps to have 1 mV accuracy */
723 HAL_Delay(OPAMP_TRIMMING_DELAY
);
725 if ((READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
)) != 0U)
727 /* Trimming value is actually one value more */
729 /* Set right trimming */
730 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
733 /* 2nd calibration - P */
734 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
736 /* Init trimming counter */
738 trimmingvaluep
= 16U;
743 /* Set candidate trimming */
744 /* OPAMP_POWERMODE_NORMAL */
745 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
747 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
748 /* Offset trim time: during calibration, minimum time needed between */
749 /* two steps to have 1 mV accuracy */
750 HAL_Delay(OPAMP_TRIMMING_DELAY
);
752 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
)!= 0U)
754 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
755 trimmingvaluep
+= delta
;
759 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
760 trimmingvaluep
-= delta
;
763 /* Divide range by 2 to continue dichotomy sweep */
767 /* Still need to check if right calibration is current value or one step below */
768 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
769 /* Set candidate trimming */
770 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
772 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
773 /* Offset trim time: during calibration, minimum time needed between */
774 /* two steps to have 1 mV accuracy */
775 HAL_Delay(OPAMP_TRIMMING_DELAY
);
777 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
) != 0U)
779 /* Trimming value is actually one value more */
781 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
784 /* Disable calibration & set normal mode (operating mode) */
785 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
787 /* Disable the OPAMP */
788 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
790 /* Set operating mode back */
791 CLEAR_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
793 /* Self calibration is successful */
794 /* Store calibration(user trimming) results in init structure. */
796 /* Set user trimming mode */
797 hopamp
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
799 /* Affect calibration parameters depending on mode normal/high speed */
800 if (hopamp
->Init
.PowerMode
!= OPAMP_POWERMODE_HIGHSPEED
)
802 /* Write calibration result N */
803 hopamp
->Init
.TrimmingValueN
= trimmingvaluen
;
804 /* Write calibration result P */
805 hopamp
->Init
.TrimmingValueP
= trimmingvaluep
;
809 /* Write calibration result N */
810 hopamp
->Init
.TrimmingValueNHighSpeed
= trimmingvaluen
;
811 /* Write calibration result P */
812 hopamp
->Init
.TrimmingValuePHighSpeed
= trimmingvaluep
;
814 /* Restore OPAMP mode after calibration */
815 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_VMSEL
, opampmode
);
820 /* OPAMP can not be calibrated from this mode */
831 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
832 * @brief Peripheral Control functions
835 ===============================================================================
836 ##### Peripheral Control functions #####
837 ===============================================================================
839 This subsection provides a set of functions allowing to control the OPAMP data
849 * @brief Lock the selected OPAMP configuration.
850 * @note On STM32H7, HAL OPAMP lock is software lock only (in
851 * contrast of hardware lock available on some other STM32
853 * @param hopamp OPAMP handle
856 HAL_StatusTypeDef
HAL_OPAMP_Lock(OPAMP_HandleTypeDef
*hopamp
)
858 HAL_StatusTypeDef status
= HAL_OK
;
860 /* Check the OPAMP handle allocation */
861 /* Check if OPAMP locked */
862 /* OPAMP can be locked when enabled and running in normal mode */
863 /* It is meaningless otherwise */
869 else if(hopamp
->State
!= HAL_OPAMP_STATE_BUSY
)
875 /* Check the parameter */
876 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
878 /* OPAMP state changed to locked */
879 hopamp
->State
= HAL_OPAMP_STATE_BUSYLOCKED
;
885 * @brief Return the OPAMP factory trimming value.
886 * @note On STM32H7 OPAMP, user can retrieve factory trimming if
887 * OPAMP has never been set to user trimming before.
888 * Therefore, this function must be called when OPAMP init
889 * parameter "UserTrimming" is set to trimming factory,
890 * and before OPAMP calibration (function
891 * "HAL_OPAMP_SelfCalibrate()").
892 * Otherwise, factory trimming value cannot be retrieved and
893 * error status is returned.
894 * @param hopamp OPAMP handle
895 * @param trimmingoffset Trimming offset (P or N)
896 * This parameter must be a value of @ref OPAMP_FactoryTrimming
897 * @note Calibration parameter retrieved is corresponding to the mode
898 * specified in OPAMP init structure (mode normal or high-speed).
899 * To retrieve calibration parameters for both modes, repeat this
900 * function after OPAMP init structure accordingly updated.
901 * @retval Trimming value (P or N): range: 0->31
902 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
905 HAL_OPAMP_TrimmingValueTypeDef
HAL_OPAMP_GetTrimOffset (const OPAMP_HandleTypeDef
*hopamp
, uint32_t trimmingoffset
)
907 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue
;
908 __IO
const uint32_t* tmp_opamp_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
910 /* Check the OPAMP handle allocation */
911 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
914 return OPAMP_FACTORYTRIMMING_DUMMY
;
917 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
919 /* Check the parameter */
920 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
921 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset
));
922 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
924 /* Check the trimming mode */
925 if (READ_BIT(hopamp
->Instance
->CSR
,OPAMP_CSR_USERTRIM
)!= 0U)
927 /* This function must called when OPAMP init parameter "UserTrimming" */
928 /* is set to trimming factory, and before OPAMP calibration (function */
929 /* "HAL_OPAMP_SelfCalibrate()"). */
930 /* Otherwise, factory trimming value cannot be retrieved and error */
931 /* status is returned. */
932 trimmingvalue
= OPAMP_FACTORYTRIMMING_DUMMY
;
936 /* Select trimming settings depending on power mode */
937 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
939 tmp_opamp_reg_trimming
= &hopamp
->Instance
->OTR
;
943 tmp_opamp_reg_trimming
= &hopamp
->Instance
->HSOTR
;
946 /* Get factory trimming */
947 if (trimmingoffset
== OPAMP_FACTORYTRIMMING_P
)
949 /* OPAMP_FACTORYTRIMMING_P */
950 trimmingvalue
= ((*tmp_opamp_reg_trimming
) & OPAMP_OTR_TRIMOFFSETP
) >> OPAMP_INPUT_NONINVERTING
;
954 /* OPAMP_FACTORYTRIMMING_N */
955 trimmingvalue
= (*tmp_opamp_reg_trimming
) & OPAMP_OTR_TRIMOFFSETN
;
961 return OPAMP_FACTORYTRIMMING_DUMMY
;
964 return trimmingvalue
;
967 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
969 * @brief Register a User OPAMP Callback
970 * To be used instead of the weak (overridden) predefined callback
971 * @param hopamp OPAMP handle
972 * @param CallbackId ID of the callback to be registered
973 * This parameter can be one of the following values:
974 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
975 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
976 * @param pCallback pointer to the Callback function
979 HAL_StatusTypeDef
HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef
*hopamp
, HAL_OPAMP_CallbackIDTypeDef CallbackId
, pOPAMP_CallbackTypeDef pCallback
)
981 HAL_StatusTypeDef status
= HAL_OK
;
983 if(pCallback
== NULL
)
991 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
995 case HAL_OPAMP_MSPINIT_CB_ID
:
996 hopamp
->MspInitCallback
= pCallback
;
998 case HAL_OPAMP_MSPDEINIT_CB_ID
:
999 hopamp
->MspDeInitCallback
= pCallback
;
1002 /* update return status */
1007 else if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
1011 case HAL_OPAMP_MSPINIT_CB_ID
:
1012 hopamp
->MspInitCallback
= pCallback
;
1014 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1015 hopamp
->MspDeInitCallback
= pCallback
;
1018 /* update return status */
1025 /* update return status */
1030 __HAL_UNLOCK(hopamp
);
1035 * @brief Unregister a User OPAMP Callback
1036 * OPAMP Callback is redirected to the weak (overridden) predefined callback
1037 * @param hopamp OPAMP handle
1038 * @param CallbackId ID of the callback to be unregistered
1039 * This parameter can be one of the following values:
1040 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
1041 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
1042 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
1045 HAL_StatusTypeDef
HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef
*hopamp
, HAL_OPAMP_CallbackIDTypeDef CallbackId
)
1047 HAL_StatusTypeDef status
= HAL_OK
;
1049 /* Process locked */
1052 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
1056 case HAL_OPAMP_MSPINIT_CB_ID
:
1057 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1059 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1060 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1062 case HAL_OPAMP_ALL_CB_ID
:
1063 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1064 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1067 /* update return status */
1072 else if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
1076 case HAL_OPAMP_MSPINIT_CB_ID
:
1077 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1079 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1080 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1083 /* update return status */
1090 /* update return status */
1095 __HAL_UNLOCK(hopamp
);
1099 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1106 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
1107 * @brief Peripheral State functions
1110 ===============================================================================
1111 ##### Peripheral State functions #####
1112 ===============================================================================
1114 This subsection permits to get in run-time the status of the peripheral.
1121 * @brief Return the OPAMP handle state.
1122 * @param hopamp OPAMP handle
1125 HAL_OPAMP_StateTypeDef
HAL_OPAMP_GetState(const OPAMP_HandleTypeDef
*hopamp
)
1127 /* Check the OPAMP handle allocation */
1130 return HAL_OPAMP_STATE_RESET
;
1133 /* Check the parameter */
1134 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
1136 /* Return OPAMP handle state */
1137 return hopamp
->State
;
1147 #endif /* HAL_OPAMP_MODULE_ENABLED */