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 * + OPAMP configuration
11 * + Initialization and de-initialization functions
12 * + IO operation functions
13 * + Peripheral Control functions
14 * + Peripheral State functions
17 ================================================================================
18 ##### OPAMP Peripheral Features #####
19 ================================================================================
21 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
23 (#) The OPAMP(s) provides several exclusive running modes.
25 (++) Programmable Gain Amplifier (PGA) modes
28 (#) Each OPAMP(s) can be configured in normal and high speed mode.
30 (#) The OPAMP(s) provide(s) calibration capabilities.
31 (++) Calibration aims at correcting some offset for running mode.
32 (++) The OPAMP uses either factory calibration settings OR user defined
33 calibration (trimming) settings (i.e. trimming mode).
34 (++) The user defined settings can be figured out using self calibration
35 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
36 (++) HAL_OPAMP_SelfCalibrate:
37 (+++) Runs automatically the calibration in 2 steps.
38 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
39 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
40 appropriate and enough in most cases).
41 (+++) Runs automatically the calibration.
42 (+++) Enables the user trimming mode
43 (+++) Updates the init structure with trimming values with fresh calibration
45 The user may store the calibration results for larger
46 (ex monitoring the trimming as a function of temperature
48 (+++) HAL_OPAMPEx_SelfCalibrateAll
49 runs calibration of all OPAMPs in parallel to save search time.
51 (#) Running mode: Standalone mode
52 (++) Gain is set externally (gain depends on external loads).
53 (++) Follower mode also possible externally by connecting the inverting input to
56 (#) Running mode: Follower mode
57 (++) No Inverting Input is connected.
59 (#) Running mode: Programmable Gain Amplifier (PGA) mode
60 (Resistor feedback output)
61 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
63 (#) OPAMP gain can be selected as :
65 (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
66 (+++) VREF- referenced.
67 (+++) Filtering on VINM0, VREF- referenced.
68 (+++) VINM0 node for bias voltage and VINP0 for input signal.
69 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
71 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
72 (+++) VINM0 node for input signal and VINP0 for bias.
73 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
75 (#) The OPAMPs inverting input can be selected according to the Reference Manual
76 "OPAMP functional description" chapter.
78 (#) The OPAMPs non inverting input can be selected according to the Reference Manual
79 "OPAMP functional description" chapter.
82 ##### How to use this driver #####
83 ================================================================================
86 *** High speed / normal power mode ***
87 ============================================
88 [..] To run in high speed mode:
90 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
91 (++) Select OPAMP_POWERMODE_HIGHSPEED
92 (++) Otherwise select OPAMP_POWERMODE_NORMAL
95 ============================================
96 [..] To run the OPAMP calibration self calibration:
98 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
99 Store the calibration results.
102 ============================================
104 [..] To use the OPAMP, perform the following steps:
106 (#) Fill in the HAL_OPAMP_MspInit() to
107 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
108 (++) Configure the OPAMP input AND output in analog mode using
109 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
111 (#) Registrate Callbacks
112 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
113 allows the user to configure dynamically the driver callbacks.
115 (++) Use Functions @ref HAL_OPAMP_RegisterCallback() to register a user callback,
116 it allows to register following callbacks:
117 (+++) MspInitCallback : OPAMP MspInit.
118 (+++) MspDeInitCallback : OPAMP MspDeInit.
119 This function takes as parameters the HAL peripheral handle, the Callback ID
120 and a pointer to the user callback function.
122 (++) Use function @ref HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
123 weak (surcharged) function. It allows to reset following callbacks:
124 (+++) MspInitCallback : OPAMP MspInit.
125 (+++) MspDeInitCallback : OPAMP MspDeInit.
127 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
129 (++) Select the inverting input
130 (++) Select the non-inverting input
131 (++) If PGA mode is enabled, Select if inverting input is connected.
132 (++) Select either factory or user defined trimming mode.
133 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
134 (typically values set by HAL_OPAMP_SelfCalibrate function).
136 (#) Enable the OPAMP using HAL_OPAMP_Start() function.
138 (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
140 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
141 Caution: On STM32H7, HAL OPAMP lock is software lock only (not
142 hardware lock as on some other STM32 devices)
144 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
146 *** Running mode: change of configuration while OPAMP ON ***
147 ============================================
148 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
149 (#) If needed, fill in the HAL_OPAMP_MspInit()
150 (++) This is the case for instance if you wish to use new OPAMP I/O
152 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
153 (++) As in configure case, select first the parameters you wish to modify.
155 (#) Change from high speed mode to normal power mode (& vice versa) requires
156 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
157 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
161 ******************************************************************************
162 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
164 +------------------------------------------------------------------------|
165 | | | OPAMP1 | OPAMP2 |
166 |-----------------|---------|----------------------|---------------------|
167 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
168 | | | VINM1-> PA7 | VINM1-> PG1 |
169 | | | Internal: | Internal: |
170 | | | ADC1_IN9 | OPAMP2_OUT |
171 | | | ADC2_IN9 | PGA mode |
174 |-----------------|---------|----------------------|---------------------|
175 | Non Inverting | VP_SEL | | |
176 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
177 | | | Internal: | Internal: |
178 | Input | | DAC1_CH1_int | DAC1_CH2_int |
179 | | | ADC1_IN8 | DAC2_CH1_int |
180 | | | ADC2_IN8 | COMP2_INP |
182 +------------------------------------------------------------------------|
185 [..] Table 2. OPAMPs outputs for the STM32H7 devices:
187 +-------------------------------------------------------------------------
188 | | | OPAMP1 | OPAMP2 |
189 |-----------------|--------|-----------------------|---------------------|
190 | Output | VOUT | PC4 | PE7 |
191 | | | & ADC1_IN4| | & COMP2_INN7 if |
192 | | | ADC2_IN4 |connected internally |
193 | | | COMP1_INN7 if | |
194 | | | connected internally | |
195 |-----------------|--------|-----------------------|---------------------|
196 ******************************************************************************
199 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
200 * All rights reserved.</center></h2>
202 * This software component is licensed by ST under BSD 3-Clause license,
203 * the "License"; You may not use this file except in compliance with the
204 * License. You may obtain a copy of the License at:
205 * opensource.org/licenses/BSD-3-Clause
207 ******************************************************************************
210 /* Includes ------------------------------------------------------------------*/
211 #include "stm32h7xx_hal.h"
213 /** @addtogroup STM32H7xx_HAL_Driver
217 /** @defgroup OPAMP OPAMP
218 * @brief OPAMP module driver
222 #ifdef HAL_OPAMP_MODULE_ENABLED
224 /* Private types -------------------------------------------------------------*/
225 /* Private variables ---------------------------------------------------------*/
226 /* Private constants ---------------------------------------------------------*/
227 /** @addtogroup OPAMP_Private_Constants
231 /* CSR register reset value */
232 #define OPAMP_CSR_RESET_VALUE 0x00000000U
236 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
237 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
240 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
241 | OPAMP_CSR_USERTRIM)
244 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
245 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
250 /* Private macros ------------------------------------------------------------*/
251 /* Private functions ---------------------------------------------------------*/
252 /* Exported functions --------------------------------------------------------*/
254 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
258 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
259 * @brief Initialization and Configuration functions
262 ==============================================================================
263 ##### Initialization and de-initialization functions #####
264 ==============================================================================
271 * @brief Initialize the OPAMP according to the specified
272 * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
273 * @note If the selected opamp is locked, initialization can't be performed.
274 * To unlock the configuration, perform a system reset.
275 * @param hopamp OPAMP handle
278 HAL_StatusTypeDef
HAL_OPAMP_Init(OPAMP_HandleTypeDef
*hopamp
)
280 HAL_StatusTypeDef status
= HAL_OK
;
281 uint32_t updateotrlpotr
;
283 /* Check the OPAMP handle allocation and lock status */
284 /* Init not allowed if calibration is ongoing */
289 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
293 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
299 /* Check the parameter */
300 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
302 /* Set OPAMP parameters */
303 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
304 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp
->Init
.Mode
));
305 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp
->Init
.NonInvertingInput
));
307 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
308 if(hopamp
->State
== HAL_OPAMP_STATE_RESET
)
310 if(hopamp
->MspInitCallback
== NULL
)
312 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
315 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
316 if ((hopamp
->Init
.Mode
) == OPAMP_STANDALONE_MODE
)
318 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp
->Init
.InvertingInput
));
321 if ((hopamp
->Init
.Mode
) == OPAMP_PGA_MODE
)
323 assert_param(IS_OPAMP_PGA_GAIN(hopamp
->Init
.PgaGain
));
324 assert_param(IS_OPAMP_PGACONNECT(hopamp
->Init
.PgaConnect
));
328 assert_param(IS_OPAMP_TRIMMING(hopamp
->Init
.UserTrimming
));
330 if ((hopamp
->Init
.UserTrimming
) == OPAMP_TRIMMING_USER
)
332 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
334 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueP
));
335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueN
));
339 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValuePHighSpeed
));
340 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp
->Init
.TrimmingValueNHighSpeed
));
344 if(hopamp
->State
== HAL_OPAMP_STATE_RESET
)
346 /* Allocate lock resource and initialize it */
347 hopamp
->Lock
= HAL_UNLOCKED
;
350 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
351 hopamp
->MspInitCallback(hopamp
);
353 /* Call MSP init function */
354 HAL_OPAMP_MspInit(hopamp
);
355 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
357 /* Set operating mode */
358 CLEAR_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
359 /* In PGA mode InvertingInput is Not Applicable */
360 if (hopamp
->Init
.Mode
== OPAMP_PGA_MODE
)
362 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_PGA
, \
363 hopamp
->Init
.PowerMode
| \
364 hopamp
->Init
.Mode
| \
365 hopamp
->Init
.PgaGain
| \
366 hopamp
->Init
.PgaConnect
| \
367 hopamp
->Init
.NonInvertingInput
| \
368 hopamp
->Init
.UserTrimming
);
371 if (hopamp
->Init
.Mode
== OPAMP_FOLLOWER_MODE
)
373 /* In Follower mode InvertingInput is Not Applicable */
374 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_FOLLOWER
, \
375 hopamp
->Init
.PowerMode
| \
376 hopamp
->Init
.Mode
| \
377 hopamp
->Init
.NonInvertingInput
| \
378 hopamp
->Init
.UserTrimming
);
381 if (hopamp
->Init
.Mode
== OPAMP_STANDALONE_MODE
)
383 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_INIT_MASK_STANDALONE
, \
384 hopamp
->Init
.PowerMode
| \
385 hopamp
->Init
.Mode
| \
386 hopamp
->Init
.InvertingInput
| \
387 hopamp
->Init
.NonInvertingInput
| \
388 hopamp
->Init
.UserTrimming
);
391 if (hopamp
->Init
.UserTrimming
== OPAMP_TRIMMING_USER
)
393 /* Set power mode and associated calibration parameters */
394 if (hopamp
->Init
.PowerMode
!= OPAMP_POWERMODE_HIGHSPEED
)
396 /* OPAMP_POWERMODE_NORMAL */
397 /* Set calibration mode (factory or user) and values for */
398 /* transistors differential pair high (PMOS) and low (NMOS) for */
400 updateotrlpotr
= (((hopamp
->Init
.TrimmingValueP
) << (OPAMP_INPUT_NONINVERTING
)) \
401 | (hopamp
->Init
.TrimmingValueN
));
402 MODIFY_REG(hopamp
->Instance
->OTR
, OPAMP_OTR_TRIMOFFSETN
| OPAMP_OTR_TRIMOFFSETP
, updateotrlpotr
);
406 /* OPAMP_POWERMODE_HIGHSPEED*/
407 /* transistors differential pair high (PMOS) and low (NMOS) for */
408 /* high speed mode. */
409 updateotrlpotr
= (((hopamp
->Init
.TrimmingValuePHighSpeed
) << (OPAMP_INPUT_NONINVERTING
)) \
410 | (hopamp
->Init
.TrimmingValueNHighSpeed
));
411 MODIFY_REG(hopamp
->Instance
->HSOTR
, OPAMP_OTR_TRIMOFFSETN
| OPAMP_OTR_TRIMOFFSETP
, updateotrlpotr
);
415 /* Update the OPAMP state*/
416 if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
418 /* From RESET state to READY State */
419 hopamp
->State
= HAL_OPAMP_STATE_READY
;
421 /* else: remain in READY or BUSY state (no update) */
427 * @brief DeInitialize the OPAMP peripheral
428 * @note Deinitialization can be performed if the OPAMP configuration is locked.
429 * (the lock is SW in H7)
430 * @param hopamp OPAMP handle
433 HAL_StatusTypeDef
HAL_OPAMP_DeInit(OPAMP_HandleTypeDef
*hopamp
)
435 HAL_StatusTypeDef status
= HAL_OK
;
437 /* Check the OPAMP handle allocation */
438 /* DeInit not allowed if calibration is on going */
443 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
449 /* Check the parameter */
450 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
452 /* Set OPAMP_CSR register to reset value */
453 WRITE_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_RESET_VALUE
);
455 /* DeInit the low level hardware */
456 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
457 if(hopamp
->MspDeInitCallback
== NULL
)
459 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
461 /* DeInit the low level hardware */
462 hopamp
->MspDeInitCallback(hopamp
);
464 HAL_OPAMP_MspDeInit(hopamp
);
465 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
467 /* Update the OPAMP state*/
468 hopamp
->State
= HAL_OPAMP_STATE_RESET
;
469 /* Process unlocked */
470 __HAL_UNLOCK(hopamp
);
479 * @brief Initialize the OPAMP MSP.
480 * @param hopamp OPAMP handle
483 __weak
void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef
*hopamp
)
485 /* Prevent unused argument(s) compilation warning */
488 /* NOTE : This function should not be modified, when the callback is needed,
489 the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
494 * @brief DeInitialize OPAMP MSP.
495 * @param hopamp OPAMP handle
498 __weak
void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef
*hopamp
)
500 /* Prevent unused argument(s) compilation warning */
502 /* NOTE : This function should not be modified, when the callback is needed,
503 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
512 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
513 * @brief IO operation functions
516 ===============================================================================
517 ##### IO operation functions #####
518 ===============================================================================
520 This subsection provides a set of functions allowing to manage the OPAMP
521 start, stop and calibration actions.
528 * @brief Start the OPAMP.
529 * @param hopamp OPAMP handle
532 HAL_StatusTypeDef
HAL_OPAMP_Start(OPAMP_HandleTypeDef
*hopamp
)
534 HAL_StatusTypeDef status
= HAL_OK
;
536 /* Check the OPAMP handle allocation */
537 /* Check if OPAMP locked */
542 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
548 /* Check the parameter */
549 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
551 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
553 /* Enable the selected opamp */
554 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
556 /* Update the OPAMP state*/
557 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
558 hopamp
->State
= HAL_OPAMP_STATE_BUSY
;
570 * @brief Stop the OPAMP.
571 * @param hopamp OPAMP handle
574 HAL_StatusTypeDef
HAL_OPAMP_Stop(OPAMP_HandleTypeDef
*hopamp
)
576 HAL_StatusTypeDef status
= HAL_OK
;
578 /* Check the OPAMP handle allocation */
579 /* Check if OPAMP locked */
580 /* Check if OPAMP calibration ongoing */
585 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
589 else if(hopamp
->State
== HAL_OPAMP_STATE_CALIBBUSY
)
595 /* Check the parameter */
596 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
598 if(hopamp
->State
== HAL_OPAMP_STATE_BUSY
)
600 /* Disable the selected opamp */
601 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
603 /* Update the OPAMP state*/
604 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
605 hopamp
->State
= HAL_OPAMP_STATE_READY
;
616 * @brief Run the self calibration of one OPAMP.
617 * @note Calibration is performed in the mode specified in OPAMP init
618 * structure (mode normal or high-speed). To perform calibration for
619 * both modes, repeat this function twice after OPAMP init structure
620 * accordingly updated.
621 * @param hopamp handle
622 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
625 HAL_StatusTypeDef
HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef
*hopamp
)
628 HAL_StatusTypeDef status
= HAL_OK
;
630 uint32_t trimmingvaluen
;
631 uint32_t trimmingvaluep
;
635 __IO
uint32_t* tmp_opamp_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
637 /* Check the OPAMP handle allocation */
638 /* Check if OPAMP locked */
643 else if(hopamp
->State
== HAL_OPAMP_STATE_BUSYLOCKED
)
650 /* Check if OPAMP in calibration mode and calibration not yet enable */
651 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
653 /* Check the parameter */
654 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
655 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
657 opampmode
= READ_BIT(hopamp
->Instance
->CSR
,OPAMP_CSR_VMSEL
);
659 /* Use of standalone mode */
660 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_VMSEL
, OPAMP_STANDALONE_MODE
);
661 /* user trimming values are used for offset calibration */
662 SET_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_USERTRIM
);
664 /* Select trimming settings depending on power mode */
665 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
667 tmp_opamp_reg_trimming
= &hopamp
->Instance
->OTR
;
672 /* high speed Mode */
673 tmp_opamp_reg_trimming
= &hopamp
->Instance
->HSOTR
;
677 /* Enable calibration */
678 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
680 /* Force internal reference on VP */
681 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
683 /* 1st calibration - N */
684 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_90VDDA
);
686 /* Enable the selected opamp */
687 SET_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
689 /* Init trimming counter */
691 trimmingvaluen
= 16U;
696 /* Set candidate trimming */
697 /* OPAMP_POWERMODE_NORMAL */
698 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
700 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
701 /* Offset trim time: during calibration, minimum time needed between */
702 /* two steps to have 1 mV accuracy */
703 HAL_Delay(OPAMP_TRIMMING_DELAY
);
705 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
) != 0U)
707 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
708 trimmingvaluen
+= delta
;
712 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
713 trimmingvaluen
-= delta
;
715 /* Divide range by 2 to continue dichotomy sweep */
719 /* Still need to check if right calibration is current value or one step below */
720 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
722 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
724 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
725 /* Offset trim time: during calibration, minimum time needed between */
726 /* two steps to have 1 mV accuracy */
727 HAL_Delay(OPAMP_TRIMMING_DELAY
);
729 if ((READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
)) != 0U)
731 /* Trimming value is actually one value more */
733 /* Set right trimming */
734 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETN
, trimmingvaluen
);
737 /* 2nd calibration - P */
738 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_CALSEL
, OPAMP_VREF_10VDDA
);
740 /* Init trimming counter */
742 trimmingvaluep
= 16U;
747 /* Set candidate trimming */
748 /* OPAMP_POWERMODE_NORMAL */
749 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
751 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
752 /* Offset trim time: during calibration, minimum time needed between */
753 /* two steps to have 1 mV accuracy */
754 HAL_Delay(OPAMP_TRIMMING_DELAY
);
756 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
)!= 0U)
758 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
759 trimmingvaluep
+= delta
;
763 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
764 trimmingvaluep
-= delta
;
767 /* Divide range by 2 to continue dichotomy sweep */
771 /* Still need to check if right calibration is current value or one step below */
772 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
773 /* Set candidate trimming */
774 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
776 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
777 /* Offset trim time: during calibration, minimum time needed between */
778 /* two steps to have 1 mV accuracy */
779 HAL_Delay(OPAMP_TRIMMING_DELAY
);
781 if (READ_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_CALOUT
) != 0U)
783 /* Trimming value is actually one value more */
785 MODIFY_REG(*tmp_opamp_reg_trimming
, OPAMP_OTR_TRIMOFFSETP
, (trimmingvaluep
<<OPAMP_INPUT_NONINVERTING
));
788 /* Disable calibration & set normal mode (operating mode) */
789 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_CALON
);
791 /* Disable the OPAMP */
792 CLEAR_BIT (hopamp
->Instance
->CSR
, OPAMP_CSR_OPAMPxEN
);
794 /* Set operating mode back */
795 CLEAR_BIT(hopamp
->Instance
->CSR
, OPAMP_CSR_FORCEVP
);
797 /* Self calibration is successful */
798 /* Store calibration(user trimming) results in init structure. */
800 /* Set user trimming mode */
801 hopamp
->Init
.UserTrimming
= OPAMP_TRIMMING_USER
;
803 /* Affect calibration parameters depending on mode normal/high speed */
804 if (hopamp
->Init
.PowerMode
!= OPAMP_POWERMODE_HIGHSPEED
)
806 /* Write calibration result N */
807 hopamp
->Init
.TrimmingValueN
= trimmingvaluen
;
808 /* Write calibration result P */
809 hopamp
->Init
.TrimmingValueP
= trimmingvaluep
;
813 /* Write calibration result N */
814 hopamp
->Init
.TrimmingValueNHighSpeed
= trimmingvaluen
;
815 /* Write calibration result P */
816 hopamp
->Init
.TrimmingValuePHighSpeed
= trimmingvaluep
;
818 /* Restore OPAMP mode after calibration */
819 MODIFY_REG(hopamp
->Instance
->CSR
, OPAMP_CSR_VMSEL
, opampmode
);
824 /* OPAMP can not be calibrated from this mode */
835 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
836 * @brief Peripheral Control functions
839 ===============================================================================
840 ##### Peripheral Control functions #####
841 ===============================================================================
843 This subsection provides a set of functions allowing to control the OPAMP data
853 * @brief Lock the selected OPAMP configuration.
854 * @note On STM32H7, HAL OPAMP lock is software lock only (in
855 * contrast of hardware lock available on some other STM32
857 * @param hopamp OPAMP handle
860 HAL_StatusTypeDef
HAL_OPAMP_Lock(OPAMP_HandleTypeDef
*hopamp
)
862 HAL_StatusTypeDef status
= HAL_OK
;
864 /* Check the OPAMP handle allocation */
865 /* Check if OPAMP locked */
866 /* OPAMP can be locked when enabled and running in normal mode */
867 /* It is meaningless otherwise */
873 else if(hopamp
->State
!= HAL_OPAMP_STATE_BUSY
)
879 /* Check the parameter */
880 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
882 /* OPAMP state changed to locked */
883 hopamp
->State
= HAL_OPAMP_STATE_BUSYLOCKED
;
889 * @brief Return the OPAMP factory trimming value.
890 * @note On STM32H7 OPAMP, user can retrieve factory trimming if
891 * OPAMP has never been set to user trimming before.
892 * Therefore, this function must be called when OPAMP init
893 * parameter "UserTrimming" is set to trimming factory,
894 * and before OPAMP calibration (function
895 * "HAL_OPAMP_SelfCalibrate()").
896 * Otherwise, factory trimming value cannot be retrieved and
897 * error status is returned.
898 * @param hopamp OPAMP handle
899 * @param trimmingoffset Trimming offset (P or N)
900 * This parameter must be a value of @ref OPAMP_FactoryTrimming
901 * @note Calibration parameter retrieved is corresponding to the mode
902 * specified in OPAMP init structure (mode normal or high-speed).
903 * To retrieve calibration parameters for both modes, repeat this
904 * function after OPAMP init structure accordingly updated.
905 * @retval Trimming value (P or N): range: 0->31
906 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
909 HAL_OPAMP_TrimmingValueTypeDef
HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef
*hopamp
, uint32_t trimmingoffset
)
911 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue
;
912 __IO
uint32_t* tmp_opamp_reg_trimming
; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
914 /* Check the OPAMP handle allocation */
915 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
918 return OPAMP_FACTORYTRIMMING_DUMMY
;
921 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
923 /* Check the parameter */
924 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
925 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset
));
926 assert_param(IS_OPAMP_POWERMODE(hopamp
->Init
.PowerMode
));
928 /* Check the trimming mode */
929 if (READ_BIT(hopamp
->Instance
->CSR
,OPAMP_CSR_USERTRIM
)!= 0U)
931 /* This function must called when OPAMP init parameter "UserTrimming" */
932 /* is set to trimming factory, and before OPAMP calibration (function */
933 /* "HAL_OPAMP_SelfCalibrate()"). */
934 /* Otherwise, factory trimming value cannot be retrieved and error */
935 /* status is returned. */
936 trimmingvalue
= OPAMP_FACTORYTRIMMING_DUMMY
;
940 /* Select trimming settings depending on power mode */
941 if (hopamp
->Init
.PowerMode
== OPAMP_POWERMODE_NORMAL
)
943 tmp_opamp_reg_trimming
= &hopamp
->Instance
->OTR
;
947 tmp_opamp_reg_trimming
= &hopamp
->Instance
->HSOTR
;
950 /* Get factory trimming */
951 if (trimmingoffset
== OPAMP_FACTORYTRIMMING_P
)
953 /* OPAMP_FACTORYTRIMMING_P */
954 trimmingvalue
= ((*tmp_opamp_reg_trimming
) & OPAMP_OTR_TRIMOFFSETP
) >> OPAMP_INPUT_NONINVERTING
;
958 /* OPAMP_FACTORYTRIMMING_N */
959 trimmingvalue
= (*tmp_opamp_reg_trimming
) & OPAMP_OTR_TRIMOFFSETN
;
965 return OPAMP_FACTORYTRIMMING_DUMMY
;
968 return trimmingvalue
;
976 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
977 * @brief Peripheral State functions
980 ===============================================================================
981 ##### Peripheral State functions #####
982 ===============================================================================
984 This subsection permits to get in run-time the status of the peripheral.
991 * @brief Return the OPAMP handle state.
992 * @param hopamp OPAMP handle
995 HAL_OPAMP_StateTypeDef
HAL_OPAMP_GetState(OPAMP_HandleTypeDef
*hopamp
)
997 /* Check the OPAMP handle allocation */
1000 return HAL_OPAMP_STATE_RESET
;
1003 /* Check the parameter */
1004 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp
->Instance
));
1006 /* Return OPAMP handle state */
1007 return hopamp
->State
;
1014 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
1016 * @brief Register a User OPAMP Callback
1017 * To be used instead of the weak (surcharged) predefined callback
1018 * @param hopamp OPAMP handle
1019 * @param CallbackId ID of the callback to be registered
1020 * This parameter can be one of the following values:
1021 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
1022 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
1023 * @param pCallback pointer to the Callback function
1026 HAL_StatusTypeDef
HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef
*hopamp
, HAL_OPAMP_CallbackIDTypeDef CallbackId
, pOPAMP_CallbackTypeDef pCallback
)
1028 HAL_StatusTypeDef status
= HAL_OK
;
1030 if(pCallback
== NULL
)
1035 /* Process locked */
1038 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
1042 case HAL_OPAMP_MSPINIT_CB_ID
:
1043 hopamp
->MspInitCallback
= pCallback
;
1045 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1046 hopamp
->MspDeInitCallback
= pCallback
;
1049 /* update return status */
1054 else if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
1058 case HAL_OPAMP_MSPINIT_CB_ID
:
1059 hopamp
->MspInitCallback
= pCallback
;
1061 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1062 hopamp
->MspDeInitCallback
= pCallback
;
1065 /* update return status */
1072 /* update return status */
1077 __HAL_UNLOCK(hopamp
);
1082 * @brief Unregister a User OPAMP Callback
1083 * OPAMP Callback is redirected to the weak (surcharged) predefined callback
1084 * @param hopamp OPAMP handle
1085 * @param CallbackId ID of the callback to be unregistered
1086 * This parameter can be one of the following values:
1087 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
1088 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
1089 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
1092 HAL_StatusTypeDef
HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef
*hopamp
, HAL_OPAMP_CallbackIDTypeDef CallbackId
)
1094 HAL_StatusTypeDef status
= HAL_OK
;
1096 /* Process locked */
1099 if(hopamp
->State
== HAL_OPAMP_STATE_READY
)
1103 case HAL_OPAMP_MSPINIT_CB_ID
:
1104 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1106 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1107 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1109 case HAL_OPAMP_ALL_CB_ID
:
1110 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1111 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1114 /* update return status */
1119 else if (hopamp
->State
== HAL_OPAMP_STATE_RESET
)
1123 case HAL_OPAMP_MSPINIT_CB_ID
:
1124 hopamp
->MspInitCallback
= HAL_OPAMP_MspInit
;
1126 case HAL_OPAMP_MSPDEINIT_CB_ID
:
1127 hopamp
->MspDeInitCallback
= HAL_OPAMP_MspDeInit
;
1130 /* update return status */
1137 /* update return status */
1142 __HAL_UNLOCK(hopamp
);
1146 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1154 #endif /* HAL_OPAMP_MODULE_ENABLED */
1163 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/