STM32H735xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h7xx_hal_opamp.c 00004 * @author MCD Application Team 00005 * @brief OPAMP HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the operational amplifier(s) peripheral: 00008 * + Initialization and de-initialization functions 00009 * + IO operation functions 00010 * + Peripheral Control functions 00011 * + Peripheral State functions 00012 * 00013 ****************************************************************************** 00014 * @attention 00015 * 00016 * Copyright (c) 2017 STMicroelectronics. 00017 * All rights reserved. 00018 * 00019 * This software is licensed under terms that can be found in the LICENSE file 00020 * in the root directory of this software component. 00021 * If no LICENSE file comes with this software, it is provided AS-IS. 00022 * 00023 ****************************************************************************** 00024 @verbatim 00025 ================================================================================ 00026 ##### OPAMP Peripheral Features ##### 00027 ================================================================================ 00028 00029 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2 00030 00031 (#) The OPAMP(s) provides several exclusive running modes. 00032 (++) Standalone mode 00033 (++) Programmable Gain Amplifier (PGA) modes 00034 (++) Follower mode 00035 00036 (#) Each OPAMP(s) can be configured in normal and high speed mode. 00037 00038 (#) The OPAMP(s) provide(s) calibration capabilities. 00039 (++) Calibration aims at correcting some offset for running mode. 00040 (++) The OPAMP uses either factory calibration settings OR user defined 00041 calibration (trimming) settings (i.e. trimming mode). 00042 (++) The user defined settings can be figured out using self calibration 00043 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll 00044 (++) HAL_OPAMP_SelfCalibrate: 00045 (+++) Runs automatically the calibration in 2 steps. 00046 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors). 00047 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is 00048 appropriate and enough in most cases). 00049 (+++) Runs automatically the calibration. 00050 (+++) Enables the user trimming mode 00051 (+++) Updates the init structure with trimming values with fresh calibration 00052 results. 00053 The user may store the calibration results for larger 00054 (ex monitoring the trimming as a function of temperature 00055 for instance) 00056 (+++) HAL_OPAMPEx_SelfCalibrateAll 00057 runs calibration of all OPAMPs in parallel to save search time. 00058 00059 (#) Running mode: Standalone mode 00060 (++) Gain is set externally (gain depends on external loads). 00061 (++) Follower mode also possible externally by connecting the inverting input to 00062 the output. 00063 00064 (#) Running mode: Follower mode 00065 (++) No Inverting Input is connected. 00066 00067 (#) Running mode: Programmable Gain Amplifier (PGA) mode 00068 (Resistor feedback output) 00069 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback 00070 output. 00071 (#) OPAMP gain can be selected as : 00072 00073 (##) Gain of x2, x4, x8 or x16 for non inverting mode with: 00074 (+++) VREF- referenced. 00075 (+++) Filtering on VINM0, VREF- referenced. 00076 (+++) VINM0 node for bias voltage and VINP0 for input signal. 00077 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering. 00078 00079 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with: 00080 (+++) VINM0 node for input signal and VINP0 for bias. 00081 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering. 00082 00083 (#) The OPAMPs inverting input can be selected according to the Reference Manual 00084 "OPAMP functional description" chapter. 00085 00086 (#) The OPAMPs non inverting input can be selected according to the Reference Manual 00087 "OPAMP functional description" chapter. 00088 00089 00090 ##### How to use this driver ##### 00091 ================================================================================ 00092 [..] 00093 00094 *** High speed / normal power mode *** 00095 ============================================ 00096 [..] To run in high speed mode: 00097 00098 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00099 (++) Select OPAMP_POWERMODE_HIGHSPEED 00100 (++) Otherwise select OPAMP_POWERMODE_NORMAL 00101 00102 *** Calibration *** 00103 ============================================ 00104 [..] To run the OPAMP calibration self calibration: 00105 00106 (#) Start calibration using HAL_OPAMP_SelfCalibrate. 00107 Store the calibration results. 00108 00109 *** Running mode *** 00110 ============================================ 00111 00112 [..] To use the OPAMP, perform the following steps: 00113 00114 (#) Fill in the HAL_OPAMP_MspInit() to 00115 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE() 00116 (++) Configure the OPAMP input AND output in analog mode using 00117 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin. 00118 00119 (#) Registrate Callbacks 00120 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1 00121 allows the user to configure dynamically the driver callbacks. 00122 00123 (++) Use Functions HAL_OPAMP_RegisterCallback() to register a user callback, 00124 it allows to register following callbacks: 00125 (+++) MspInitCallback : OPAMP MspInit. 00126 (+++) MspDeInitCallback : OPAMP MspDeInit. 00127 This function takes as parameters the HAL peripheral handle, the Callback ID 00128 and a pointer to the user callback function. 00129 00130 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default 00131 weak (surcharged) function. It allows to reset following callbacks: 00132 (+++) MspInitCallback : OPAMP MspInit. 00133 (+++) MspDeInitCallback : OPAMP MspDeInit. 00134 (+++) All Callbacks 00135 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00136 (++) Select the mode 00137 (++) Select the inverting input 00138 (++) Select the non-inverting input 00139 (++) If PGA mode is enabled, Select if inverting input is connected. 00140 (++) Select either factory or user defined trimming mode. 00141 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values 00142 (typically values set by HAL_OPAMP_SelfCalibrate function). 00143 00144 (#) Enable the OPAMP using HAL_OPAMP_Start() function. 00145 00146 (#) Disable the OPAMP using HAL_OPAMP_Stop() function. 00147 00148 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function. 00149 Caution: On STM32H7, HAL OPAMP lock is software lock only (not 00150 hardware lock as on some other STM32 devices) 00151 00152 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function. 00153 00154 *** Running mode: change of configuration while OPAMP ON *** 00155 ============================================ 00156 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly) 00157 (#) If needed, fill in the HAL_OPAMP_MspInit() 00158 (++) This is the case for instance if you wish to use new OPAMP I/O 00159 00160 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00161 (++) As in configure case, select first the parameters you wish to modify. 00162 00163 (#) Change from high speed mode to normal power mode (& vice versa) requires 00164 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init(). 00165 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode 00166 alone. 00167 00168 @endverbatim 00169 ****************************************************************************** 00170 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices: 00171 00172 +------------------------------------------------------------------------| 00173 | | | OPAMP1 | OPAMP2 | 00174 |-----------------|---------|----------------------|---------------------| 00175 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 | 00176 | | | VINM1-> PA7 | VINM1-> PG1 | 00177 | | | Internal: | Internal: | 00178 | | | ADC1_IN9 | OPAMP2_OUT | 00179 | | | ADC2_IN9 | PGA mode | 00180 | | | OPAMP1_OUT | | 00181 | | | PGA mode | | 00182 |-----------------|---------|----------------------|---------------------| 00183 | Non Inverting | VP_SEL | | | 00184 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) | 00185 | | | Internal: | Internal: | 00186 | Input | | DAC1_CH1_int | DAC1_CH2_int | 00187 | | | ADC1_IN8 | DAC2_CH1_int | 00188 | | | ADC2_IN8 | COMP2_INP | 00189 | | | COMP1_INP | | 00190 +------------------------------------------------------------------------| 00191 00192 00193 [..] Table 2. OPAMPs outputs for the STM32H7 devices: 00194 00195 +------------------------------------------------------------------------- 00196 | | | OPAMP1 | OPAMP2 | 00197 |-----------------|--------|-----------------------|---------------------| 00198 | Output | VOUT | PC4 | PE7 | 00199 | | | & ADC1_IN4| | & COMP2_INN7 if | 00200 | | | ADC2_IN4 |connected internally | 00201 | | | COMP1_INN7 if | | 00202 | | | connected internally | | 00203 |-----------------|--------|-----------------------|---------------------| 00204 */ 00205 00206 /* Includes ------------------------------------------------------------------*/ 00207 #include "stm32h7xx_hal.h" 00208 00209 /** @addtogroup STM32H7xx_HAL_Driver 00210 * @{ 00211 */ 00212 00213 /** @defgroup OPAMP OPAMP 00214 * @brief OPAMP module driver 00215 * @{ 00216 */ 00217 00218 #ifdef HAL_OPAMP_MODULE_ENABLED 00219 00220 /* Private types -------------------------------------------------------------*/ 00221 /* Private variables ---------------------------------------------------------*/ 00222 /* Private constants ---------------------------------------------------------*/ 00223 /** @addtogroup OPAMP_Private_Constants 00224 * @{ 00225 */ 00226 00227 /* CSR register reset value */ 00228 #define OPAMP_CSR_RESET_VALUE 0x00000000U 00229 00230 /* CSR Init masks */ 00231 00232 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \ 00233 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM) 00234 00235 00236 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \ 00237 | OPAMP_CSR_USERTRIM) 00238 00239 00240 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \ 00241 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM) 00242 /** 00243 * @} 00244 */ 00245 00246 /* Private macros ------------------------------------------------------------*/ 00247 /* Private functions ---------------------------------------------------------*/ 00248 /* Exported functions --------------------------------------------------------*/ 00249 00250 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions 00251 * @{ 00252 */ 00253 00254 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions 00255 * @brief Initialization and Configuration functions 00256 * 00257 @verbatim 00258 ============================================================================== 00259 ##### Initialization and de-initialization functions ##### 00260 ============================================================================== 00261 00262 @endverbatim 00263 * @{ 00264 */ 00265 00266 /** 00267 * @brief Initialize the OPAMP according to the specified 00268 * parameters in the OPAMP_InitTypeDef and initialize the associated handle. 00269 * @note If the selected opamp is locked, initialization can't be performed. 00270 * To unlock the configuration, perform a system reset. 00271 * @param hopamp OPAMP handle 00272 * @retval HAL status 00273 */ 00274 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp) 00275 { 00276 HAL_StatusTypeDef status = HAL_OK; 00277 uint32_t updateotrlpotr; 00278 00279 /* Check the OPAMP handle allocation and lock status */ 00280 /* Init not allowed if calibration is ongoing */ 00281 if(hopamp == NULL) 00282 { 00283 return HAL_ERROR; 00284 } 00285 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 00286 { 00287 return HAL_ERROR; 00288 } 00289 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 00290 { 00291 return HAL_ERROR; 00292 } 00293 else 00294 { 00295 /* Check the parameter */ 00296 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00297 00298 /* Set OPAMP parameters */ 00299 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00300 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode)); 00301 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput)); 00302 00303 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 00304 if(hopamp->State == HAL_OPAMP_STATE_RESET) 00305 { 00306 if(hopamp->MspInitCallback == NULL) 00307 { 00308 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 00309 } 00310 } 00311 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 00312 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE) 00313 { 00314 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput)); 00315 } 00316 00317 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE) 00318 { 00319 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain)); 00320 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect)); 00321 } 00322 00323 00324 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming)); 00325 00326 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER) 00327 { 00328 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00329 { 00330 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP)); 00331 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN)); 00332 } 00333 else 00334 { 00335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed)); 00336 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed)); 00337 } 00338 } 00339 00340 if(hopamp->State == HAL_OPAMP_STATE_RESET) 00341 { 00342 /* Allocate lock resource and initialize it */ 00343 hopamp->Lock = HAL_UNLOCKED; 00344 } 00345 00346 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 00347 hopamp->MspInitCallback(hopamp); 00348 #else 00349 /* Call MSP init function */ 00350 HAL_OPAMP_MspInit(hopamp); 00351 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 00352 00353 /* Set operating mode */ 00354 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON); 00355 /* In PGA mode InvertingInput is Not Applicable */ 00356 if (hopamp->Init.Mode == OPAMP_PGA_MODE) 00357 { 00358 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \ 00359 hopamp->Init.PowerMode | \ 00360 hopamp->Init.Mode | \ 00361 hopamp->Init.PgaGain | \ 00362 hopamp->Init.PgaConnect | \ 00363 hopamp->Init.NonInvertingInput | \ 00364 hopamp->Init.UserTrimming); 00365 } 00366 00367 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE) 00368 { 00369 /* In Follower mode InvertingInput is Not Applicable */ 00370 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \ 00371 hopamp->Init.PowerMode | \ 00372 hopamp->Init.Mode | \ 00373 hopamp->Init.NonInvertingInput | \ 00374 hopamp->Init.UserTrimming); 00375 } 00376 00377 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE) 00378 { 00379 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \ 00380 hopamp->Init.PowerMode | \ 00381 hopamp->Init.Mode | \ 00382 hopamp->Init.InvertingInput | \ 00383 hopamp->Init.NonInvertingInput | \ 00384 hopamp->Init.UserTrimming); 00385 } 00386 00387 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER) 00388 { 00389 /* Set power mode and associated calibration parameters */ 00390 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED) 00391 { 00392 /* OPAMP_POWERMODE_NORMAL */ 00393 /* Set calibration mode (factory or user) and values for */ 00394 /* transistors differential pair high (PMOS) and low (NMOS) for */ 00395 /* normal mode. */ 00396 updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \ 00397 | (hopamp->Init.TrimmingValueN)); 00398 MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 00399 } 00400 else 00401 { 00402 /* OPAMP_POWERMODE_HIGHSPEED*/ 00403 /* transistors differential pair high (PMOS) and low (NMOS) for */ 00404 /* high speed mode. */ 00405 updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \ 00406 | (hopamp->Init.TrimmingValueNHighSpeed)); 00407 MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 00408 } 00409 } 00410 00411 /* Update the OPAMP state*/ 00412 if (hopamp->State == HAL_OPAMP_STATE_RESET) 00413 { 00414 /* From RESET state to READY State */ 00415 hopamp->State = HAL_OPAMP_STATE_READY; 00416 } 00417 /* else: remain in READY or BUSY state (no update) */ 00418 return status; 00419 } 00420 } 00421 00422 /** 00423 * @brief DeInitialize the OPAMP peripheral 00424 * @note Deinitialization can be performed if the OPAMP configuration is locked. 00425 * (the lock is SW in H7) 00426 * @param hopamp OPAMP handle 00427 * @retval HAL status 00428 */ 00429 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp) 00430 { 00431 HAL_StatusTypeDef status = HAL_OK; 00432 00433 /* Check the OPAMP handle allocation */ 00434 /* DeInit not allowed if calibration is on going */ 00435 if(hopamp == NULL) 00436 { 00437 status = HAL_ERROR; 00438 } 00439 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 00440 { 00441 status = HAL_ERROR; 00442 } 00443 else 00444 { 00445 /* Check the parameter */ 00446 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00447 00448 /* Set OPAMP_CSR register to reset value */ 00449 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE); 00450 00451 /* DeInit the low level hardware */ 00452 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 00453 if(hopamp->MspDeInitCallback == NULL) 00454 { 00455 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 00456 } 00457 /* DeInit the low level hardware */ 00458 hopamp->MspDeInitCallback(hopamp); 00459 #else 00460 HAL_OPAMP_MspDeInit(hopamp); 00461 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 00462 00463 /* Update the OPAMP state*/ 00464 hopamp->State = HAL_OPAMP_STATE_RESET; 00465 /* Process unlocked */ 00466 __HAL_UNLOCK(hopamp); 00467 00468 } 00469 00470 return status; 00471 } 00472 00473 00474 /** 00475 * @brief Initialize the OPAMP MSP. 00476 * @param hopamp OPAMP handle 00477 * @retval None 00478 */ 00479 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp) 00480 { 00481 /* Prevent unused argument(s) compilation warning */ 00482 UNUSED(hopamp); 00483 00484 /* NOTE : This function should not be modified, when the callback is needed, 00485 the function "HAL_OPAMP_MspInit()" must be implemented in the user file. 00486 */ 00487 } 00488 00489 /** 00490 * @brief DeInitialize OPAMP MSP. 00491 * @param hopamp OPAMP handle 00492 * @retval None 00493 */ 00494 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp) 00495 { 00496 /* Prevent unused argument(s) compilation warning */ 00497 UNUSED(hopamp); 00498 /* NOTE : This function should not be modified, when the callback is needed, 00499 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file. 00500 */ 00501 } 00502 00503 /** 00504 * @} 00505 */ 00506 00507 00508 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions 00509 * @brief IO operation functions 00510 * 00511 @verbatim 00512 =============================================================================== 00513 ##### IO operation functions ##### 00514 =============================================================================== 00515 [..] 00516 This subsection provides a set of functions allowing to manage the OPAMP 00517 start, stop and calibration actions. 00518 00519 @endverbatim 00520 * @{ 00521 */ 00522 00523 /** 00524 * @brief Start the OPAMP. 00525 * @param hopamp OPAMP handle 00526 * @retval HAL status 00527 */ 00528 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp) 00529 { 00530 HAL_StatusTypeDef status = HAL_OK; 00531 00532 /* Check the OPAMP handle allocation */ 00533 /* Check if OPAMP locked */ 00534 if(hopamp == NULL) 00535 { 00536 status = HAL_ERROR; 00537 } 00538 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 00539 { 00540 status = HAL_ERROR; 00541 } 00542 else 00543 { 00544 /* Check the parameter */ 00545 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00546 00547 if(hopamp->State == HAL_OPAMP_STATE_READY) 00548 { 00549 /* Enable the selected opamp */ 00550 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00551 00552 /* Update the OPAMP state*/ 00553 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */ 00554 hopamp->State = HAL_OPAMP_STATE_BUSY; 00555 } 00556 else 00557 { 00558 status = HAL_ERROR; 00559 } 00560 00561 } 00562 return status; 00563 } 00564 00565 /** 00566 * @brief Stop the OPAMP. 00567 * @param hopamp OPAMP handle 00568 * @retval HAL status 00569 */ 00570 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp) 00571 { 00572 HAL_StatusTypeDef status = HAL_OK; 00573 00574 /* Check the OPAMP handle allocation */ 00575 /* Check if OPAMP locked */ 00576 /* Check if OPAMP calibration ongoing */ 00577 if(hopamp == NULL) 00578 { 00579 status = HAL_ERROR; 00580 } 00581 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 00582 { 00583 status = HAL_ERROR; 00584 } 00585 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 00586 { 00587 status = HAL_ERROR; 00588 } 00589 else 00590 { 00591 /* Check the parameter */ 00592 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00593 00594 if(hopamp->State == HAL_OPAMP_STATE_BUSY) 00595 { 00596 /* Disable the selected opamp */ 00597 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00598 00599 /* Update the OPAMP state*/ 00600 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/ 00601 hopamp->State = HAL_OPAMP_STATE_READY; 00602 } 00603 else 00604 { 00605 status = HAL_ERROR; 00606 } 00607 } 00608 return status; 00609 } 00610 00611 /** 00612 * @brief Run the self calibration of one OPAMP. 00613 * @note Calibration is performed in the mode specified in OPAMP init 00614 * structure (mode normal or high-speed). To perform calibration for 00615 * both modes, repeat this function twice after OPAMP init structure 00616 * accordingly updated. 00617 * @param hopamp handle 00618 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled 00619 * @retval HAL status 00620 */ 00621 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp) 00622 { 00623 00624 HAL_StatusTypeDef status = HAL_OK; 00625 00626 uint32_t trimmingvaluen; 00627 uint32_t trimmingvaluep; 00628 uint32_t delta; 00629 uint32_t opampmode; 00630 00631 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */ 00632 00633 /* Check the OPAMP handle allocation */ 00634 /* Check if OPAMP locked */ 00635 if(hopamp == NULL) 00636 { 00637 status = HAL_ERROR; 00638 } 00639 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 00640 { 00641 status = HAL_ERROR; 00642 } 00643 else 00644 { 00645 00646 /* Check if OPAMP in calibration mode and calibration not yet enable */ 00647 if(hopamp->State == HAL_OPAMP_STATE_READY) 00648 { 00649 /* Check the parameter */ 00650 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00651 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00652 00653 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL); 00654 00655 /* Use of standalone mode */ 00656 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE); 00657 /* user trimming values are used for offset calibration */ 00658 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM); 00659 00660 /* Select trimming settings depending on power mode */ 00661 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00662 { 00663 tmp_opamp_reg_trimming = &hopamp->Instance->OTR; 00664 00665 } 00666 else 00667 { 00668 /* high speed Mode */ 00669 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR; 00670 } 00671 00672 00673 /* Enable calibration */ 00674 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 00675 00676 /* Force internal reference on VP */ 00677 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); 00678 00679 /* 1st calibration - N */ 00680 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA); 00681 00682 /* Enable the selected opamp */ 00683 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00684 00685 /* Init trimming counter */ 00686 /* Medium value */ 00687 trimmingvaluen = 16U; 00688 delta = 8U; 00689 00690 while (delta != 0U) 00691 { 00692 /* Set candidate trimming */ 00693 /* OPAMP_POWERMODE_NORMAL */ 00694 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00695 00696 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 00697 /* Offset trim time: during calibration, minimum time needed between */ 00698 /* two steps to have 1 mV accuracy */ 00699 HAL_Delay(OPAMP_TRIMMING_DELAY); 00700 00701 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U) 00702 { 00703 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00704 trimmingvaluen += delta; 00705 } 00706 else 00707 { 00708 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 00709 trimmingvaluen -= delta; 00710 } 00711 /* Divide range by 2 to continue dichotomy sweep */ 00712 delta >>= 1; 00713 } 00714 00715 /* Still need to check if right calibration is current value or one step below */ 00716 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 00717 00718 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00719 00720 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 00721 /* Offset trim time: during calibration, minimum time needed between */ 00722 /* two steps to have 1 mV accuracy */ 00723 HAL_Delay(OPAMP_TRIMMING_DELAY); 00724 00725 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U) 00726 { 00727 /* Trimming value is actually one value more */ 00728 trimmingvaluen++; 00729 /* Set right trimming */ 00730 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00731 } 00732 00733 /* 2nd calibration - P */ 00734 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA); 00735 00736 /* Init trimming counter */ 00737 /* Medium value */ 00738 trimmingvaluep = 16U; 00739 delta = 8U; 00740 00741 while (delta != 0U) 00742 { 00743 /* Set candidate trimming */ 00744 /* OPAMP_POWERMODE_NORMAL */ 00745 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00746 00747 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 00748 /* Offset trim time: during calibration, minimum time needed between */ 00749 /* two steps to have 1 mV accuracy */ 00750 HAL_Delay(OPAMP_TRIMMING_DELAY); 00751 00752 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U) 00753 { 00754 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00755 trimmingvaluep += delta; 00756 } 00757 else 00758 { 00759 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 00760 trimmingvaluep -= delta; 00761 } 00762 00763 /* Divide range by 2 to continue dichotomy sweep */ 00764 delta >>= 1U; 00765 } 00766 00767 /* Still need to check if right calibration is current value or one step below */ 00768 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 00769 /* Set candidate trimming */ 00770 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00771 00772 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 00773 /* Offset trim time: during calibration, minimum time needed between */ 00774 /* two steps to have 1 mV accuracy */ 00775 HAL_Delay(OPAMP_TRIMMING_DELAY); 00776 00777 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U) 00778 { 00779 /* Trimming value is actually one value more */ 00780 trimmingvaluep++; 00781 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00782 } 00783 00784 /* Disable calibration & set normal mode (operating mode) */ 00785 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 00786 00787 /* Disable the OPAMP */ 00788 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00789 00790 /* Set operating mode back */ 00791 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); 00792 00793 /* Self calibration is successful */ 00794 /* Store calibration(user trimming) results in init structure. */ 00795 00796 /* Set user trimming mode */ 00797 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER; 00798 00799 /* Affect calibration parameters depending on mode normal/high speed */ 00800 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED) 00801 { 00802 /* Write calibration result N */ 00803 hopamp->Init.TrimmingValueN = trimmingvaluen; 00804 /* Write calibration result P */ 00805 hopamp->Init.TrimmingValueP = trimmingvaluep; 00806 } 00807 else 00808 { 00809 /* Write calibration result N */ 00810 hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen; 00811 /* Write calibration result P */ 00812 hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep; 00813 } 00814 /* Restore OPAMP mode after calibration */ 00815 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode); 00816 } 00817 00818 else 00819 { 00820 /* OPAMP can not be calibrated from this mode */ 00821 status = HAL_ERROR; 00822 } 00823 } 00824 return status; 00825 } 00826 00827 /** 00828 * @} 00829 */ 00830 00831 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions 00832 * @brief Peripheral Control functions 00833 * 00834 @verbatim 00835 =============================================================================== 00836 ##### Peripheral Control functions ##### 00837 =============================================================================== 00838 [..] 00839 This subsection provides a set of functions allowing to control the OPAMP data 00840 transfers. 00841 00842 00843 00844 @endverbatim 00845 * @{ 00846 */ 00847 00848 /** 00849 * @brief Lock the selected OPAMP configuration. 00850 * @note On STM32H7, HAL OPAMP lock is software lock only (in 00851 * contrast of hardware lock available on some other STM32 00852 * devices) 00853 * @param hopamp OPAMP handle 00854 * @retval HAL status 00855 */ 00856 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp) 00857 { 00858 HAL_StatusTypeDef status = HAL_OK; 00859 00860 /* Check the OPAMP handle allocation */ 00861 /* Check if OPAMP locked */ 00862 /* OPAMP can be locked when enabled and running in normal mode */ 00863 /* It is meaningless otherwise */ 00864 if(hopamp == NULL) 00865 { 00866 status = HAL_ERROR; 00867 } 00868 00869 else if(hopamp->State != HAL_OPAMP_STATE_BUSY) 00870 { 00871 status = HAL_ERROR; 00872 } 00873 else 00874 { 00875 /* Check the parameter */ 00876 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00877 00878 /* OPAMP state changed to locked */ 00879 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED; 00880 } 00881 return status; 00882 } 00883 00884 /** 00885 * @brief Return the OPAMP factory trimming value. 00886 * @note On STM32H7 OPAMP, user can retrieve factory trimming if 00887 * OPAMP has never been set to user trimming before. 00888 * Therefore, this function must be called when OPAMP init 00889 * parameter "UserTrimming" is set to trimming factory, 00890 * and before OPAMP calibration (function 00891 * "HAL_OPAMP_SelfCalibrate()"). 00892 * Otherwise, factory trimming value cannot be retrieved and 00893 * error status is returned. 00894 * @param hopamp OPAMP handle 00895 * @param trimmingoffset Trimming offset (P or N) 00896 * This parameter must be a value of @ref OPAMP_FactoryTrimming 00897 * @note Calibration parameter retrieved is corresponding to the mode 00898 * specified in OPAMP init structure (mode normal or high-speed). 00899 * To retrieve calibration parameters for both modes, repeat this 00900 * function after OPAMP init structure accordingly updated. 00901 * @retval Trimming value (P or N): range: 0->31 00902 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available 00903 * 00904 */ 00905 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset) 00906 { 00907 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue; 00908 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */ 00909 00910 /* Check the OPAMP handle allocation */ 00911 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */ 00912 if(hopamp == NULL) 00913 { 00914 return OPAMP_FACTORYTRIMMING_DUMMY; 00915 } 00916 00917 if(hopamp->State == HAL_OPAMP_STATE_READY) 00918 { 00919 /* Check the parameter */ 00920 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00921 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset)); 00922 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00923 00924 /* Check the trimming mode */ 00925 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U) 00926 { 00927 /* This function must called when OPAMP init parameter "UserTrimming" */ 00928 /* is set to trimming factory, and before OPAMP calibration (function */ 00929 /* "HAL_OPAMP_SelfCalibrate()"). */ 00930 /* Otherwise, factory trimming value cannot be retrieved and error */ 00931 /* status is returned. */ 00932 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY; 00933 } 00934 else 00935 { 00936 /* Select trimming settings depending on power mode */ 00937 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00938 { 00939 tmp_opamp_reg_trimming = &hopamp->Instance->OTR; 00940 } 00941 else 00942 { 00943 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR; 00944 } 00945 00946 /* Get factory trimming */ 00947 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P) 00948 { 00949 /* OPAMP_FACTORYTRIMMING_P */ 00950 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING; 00951 } 00952 else 00953 { 00954 /* OPAMP_FACTORYTRIMMING_N */ 00955 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN; 00956 } 00957 } 00958 } 00959 else 00960 { 00961 return OPAMP_FACTORYTRIMMING_DUMMY; 00962 } 00963 00964 return trimmingvalue; 00965 } 00966 00967 /** 00968 * @} 00969 */ 00970 00971 00972 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions 00973 * @brief Peripheral State functions 00974 * 00975 @verbatim 00976 =============================================================================== 00977 ##### Peripheral State functions ##### 00978 =============================================================================== 00979 [..] 00980 This subsection permits to get in run-time the status of the peripheral. 00981 00982 @endverbatim 00983 * @{ 00984 */ 00985 00986 /** 00987 * @brief Return the OPAMP handle state. 00988 * @param hopamp OPAMP handle 00989 * @retval HAL state 00990 */ 00991 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp) 00992 { 00993 /* Check the OPAMP handle allocation */ 00994 if(hopamp == NULL) 00995 { 00996 return HAL_OPAMP_STATE_RESET; 00997 } 00998 00999 /* Check the parameter */ 01000 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 01001 01002 /* Return OPAMP handle state */ 01003 return hopamp->State; 01004 } 01005 01006 /** 01007 * @} 01008 */ 01009 01010 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 01011 /** 01012 * @brief Register a User OPAMP Callback 01013 * To be used instead of the weak (surcharged) predefined callback 01014 * @param hopamp OPAMP handle 01015 * @param CallbackId ID of the callback to be registered 01016 * This parameter can be one of the following values: 01017 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID 01018 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID 01019 * @param pCallback pointer to the Callback function 01020 * @retval status 01021 */ 01022 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback) 01023 { 01024 HAL_StatusTypeDef status = HAL_OK; 01025 01026 if(pCallback == NULL) 01027 { 01028 return HAL_ERROR; 01029 } 01030 01031 /* Process locked */ 01032 __HAL_LOCK(hopamp); 01033 01034 if(hopamp->State == HAL_OPAMP_STATE_READY) 01035 { 01036 switch (CallbackId) 01037 { 01038 case HAL_OPAMP_MSPINIT_CB_ID : 01039 hopamp->MspInitCallback = pCallback; 01040 break; 01041 case HAL_OPAMP_MSPDEINIT_CB_ID : 01042 hopamp->MspDeInitCallback = pCallback; 01043 break; 01044 default : 01045 /* update return status */ 01046 status = HAL_ERROR; 01047 break; 01048 } 01049 } 01050 else if (hopamp->State == HAL_OPAMP_STATE_RESET) 01051 { 01052 switch (CallbackId) 01053 { 01054 case HAL_OPAMP_MSPINIT_CB_ID : 01055 hopamp->MspInitCallback = pCallback; 01056 break; 01057 case HAL_OPAMP_MSPDEINIT_CB_ID : 01058 hopamp->MspDeInitCallback = pCallback; 01059 break; 01060 default : 01061 /* update return status */ 01062 status = HAL_ERROR; 01063 break; 01064 } 01065 } 01066 else 01067 { 01068 /* update return status */ 01069 status = HAL_ERROR; 01070 } 01071 01072 /* Release Lock */ 01073 __HAL_UNLOCK(hopamp); 01074 return status; 01075 } 01076 01077 /** 01078 * @brief Unregister a User OPAMP Callback 01079 * OPAMP Callback is redirected to the weak (surcharged) predefined callback 01080 * @param hopamp OPAMP handle 01081 * @param CallbackId ID of the callback to be unregistered 01082 * This parameter can be one of the following values: 01083 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID 01084 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID 01085 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks 01086 * @retval status 01087 */ 01088 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId) 01089 { 01090 HAL_StatusTypeDef status = HAL_OK; 01091 01092 /* Process locked */ 01093 __HAL_LOCK(hopamp); 01094 01095 if(hopamp->State == HAL_OPAMP_STATE_READY) 01096 { 01097 switch (CallbackId) 01098 { 01099 case HAL_OPAMP_MSPINIT_CB_ID : 01100 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 01101 break; 01102 case HAL_OPAMP_MSPDEINIT_CB_ID : 01103 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 01104 break; 01105 case HAL_OPAMP_ALL_CB_ID : 01106 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 01107 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 01108 break; 01109 default : 01110 /* update return status */ 01111 status = HAL_ERROR; 01112 break; 01113 } 01114 } 01115 else if (hopamp->State == HAL_OPAMP_STATE_RESET) 01116 { 01117 switch (CallbackId) 01118 { 01119 case HAL_OPAMP_MSPINIT_CB_ID : 01120 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 01121 break; 01122 case HAL_OPAMP_MSPDEINIT_CB_ID : 01123 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 01124 break; 01125 default : 01126 /* update return status */ 01127 status = HAL_ERROR; 01128 break; 01129 } 01130 } 01131 else 01132 { 01133 /* update return status */ 01134 status = HAL_ERROR; 01135 } 01136 01137 /* Release Lock */ 01138 __HAL_UNLOCK(hopamp); 01139 return status; 01140 } 01141 01142 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 01143 /** 01144 * @} 01145 */ 01146 01147 /** 01148 * @} 01149 */ 01150 #endif /* HAL_OPAMP_MODULE_ENABLED */ 01151 /** 01152 * @} 01153 */ 01154 01155 /** 01156 * @} 01157 */ 01158