![]() |
|
|||
File indexing completed on 2025-05-11 08:23:08
0001 /** 0002 ****************************************************************************** 0003 * @file stm32h7xx_hal_opamp.c 0004 * @author MCD Application Team 0005 * @brief OPAMP HAL module driver. 0006 * This file provides firmware functions to manage the following 0007 * functionalities of the operational amplifier(s) peripheral: 0008 * + Initialization and de-initialization functions 0009 * + IO operation functions 0010 * + Peripheral Control functions 0011 * + Peripheral State functions 0012 * 0013 ****************************************************************************** 0014 * @attention 0015 * 0016 * Copyright (c) 2017 STMicroelectronics. 0017 * All rights reserved. 0018 * 0019 * This software is licensed under terms that can be found in the LICENSE file 0020 * in the root directory of this software component. 0021 * If no LICENSE file comes with this software, it is provided AS-IS. 0022 * 0023 ****************************************************************************** 0024 @verbatim 0025 ================================================================================ 0026 ##### OPAMP Peripheral Features ##### 0027 ================================================================================ 0028 0029 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2 0030 0031 (#) The OPAMP(s) provides several exclusive running modes. 0032 (++) Standalone mode 0033 (++) Programmable Gain Amplifier (PGA) modes 0034 (++) Follower mode 0035 0036 (#) Each OPAMP(s) can be configured in normal and high speed mode. 0037 0038 (#) The OPAMP(s) provide(s) calibration capabilities. 0039 (++) Calibration aims at correcting some offset for running mode. 0040 (++) The OPAMP uses either factory calibration settings OR user defined 0041 calibration (trimming) settings (i.e. trimming mode). 0042 (++) The user defined settings can be figured out using self calibration 0043 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll 0044 (++) HAL_OPAMP_SelfCalibrate: 0045 (+++) Runs automatically the calibration in 2 steps. 0046 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors). 0047 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is 0048 appropriate and enough in most cases). 0049 (+++) Runs automatically the calibration. 0050 (+++) Enables the user trimming mode 0051 (+++) Updates the init structure with trimming values with fresh calibration 0052 results. 0053 The user may store the calibration results for larger 0054 (ex monitoring the trimming as a function of temperature 0055 for instance) 0056 (+++) HAL_OPAMPEx_SelfCalibrateAll 0057 runs calibration of all OPAMPs in parallel to save search time. 0058 0059 (#) Running mode: Standalone mode 0060 (++) Gain is set externally (gain depends on external loads). 0061 (++) Follower mode also possible externally by connecting the inverting input to 0062 the output. 0063 0064 (#) Running mode: Follower mode 0065 (++) No Inverting Input is connected. 0066 0067 (#) Running mode: Programmable Gain Amplifier (PGA) mode 0068 (Resistor feedback output) 0069 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback 0070 output. 0071 (#) OPAMP gain can be selected as : 0072 0073 (##) Gain of x2, x4, x8 or x16 for non inverting mode with: 0074 (+++) VREF- referenced. 0075 (+++) Filtering on VINM0, VREF- referenced. 0076 (+++) VINM0 node for bias voltage and VINP0 for input signal. 0077 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering. 0078 0079 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with: 0080 (+++) VINM0 node for input signal and VINP0 for bias. 0081 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering. 0082 0083 (#) The OPAMPs inverting input can be selected according to the Reference Manual 0084 "OPAMP functional description" chapter. 0085 0086 (#) The OPAMPs non inverting input can be selected according to the Reference Manual 0087 "OPAMP functional description" chapter. 0088 0089 0090 ##### How to use this driver ##### 0091 ================================================================================ 0092 [..] 0093 0094 *** High speed / normal power mode *** 0095 ============================================ 0096 [..] To run in high speed mode: 0097 0098 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 0099 (++) Select OPAMP_POWERMODE_HIGHSPEED 0100 (++) Otherwise select OPAMP_POWERMODE_NORMAL 0101 0102 *** Calibration *** 0103 ============================================ 0104 [..] To run the OPAMP calibration self calibration: 0105 0106 (#) Start calibration using HAL_OPAMP_SelfCalibrate. 0107 Store the calibration results. 0108 0109 *** Running mode *** 0110 ============================================ 0111 0112 [..] To use the OPAMP, perform the following steps: 0113 0114 (#) Fill in the HAL_OPAMP_MspInit() to 0115 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE() 0116 (++) Configure the OPAMP input AND output in analog mode using 0117 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin. 0118 0119 (#) Registrate Callbacks 0120 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1 0121 allows the user to configure dynamically the driver callbacks. 0122 0123 (++) Use Functions HAL_OPAMP_RegisterCallback() to register a user callback, 0124 it allows to register following callbacks: 0125 (+++) MspInitCallback : OPAMP MspInit. 0126 (+++) MspDeInitCallback : OPAMP MspDeInit. 0127 This function takes as parameters the HAL peripheral handle, the Callback ID 0128 and a pointer to the user callback function. 0129 0130 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default 0131 weak (overridden) function. It allows to reset following callbacks: 0132 (+++) MspInitCallback : OPAMP MspInit. 0133 (+++) MspDeInitCallback : OPAMP MspDeInit. 0134 (+++) All Callbacks 0135 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 0136 (++) Select the mode 0137 (++) Select the inverting input 0138 (++) Select the non-inverting input 0139 (++) If PGA mode is enabled, Select if inverting input is connected. 0140 (++) Select either factory or user defined trimming mode. 0141 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values 0142 (typically values set by HAL_OPAMP_SelfCalibrate function). 0143 0144 (#) Enable the OPAMP using HAL_OPAMP_Start() function. 0145 0146 (#) Disable the OPAMP using HAL_OPAMP_Stop() function. 0147 0148 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function. 0149 Caution: On STM32H7, HAL OPAMP lock is software lock only (not 0150 hardware lock as on some other STM32 devices) 0151 0152 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function. 0153 0154 *** Running mode: change of configuration while OPAMP ON *** 0155 ============================================ 0156 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly) 0157 (#) If needed, fill in the HAL_OPAMP_MspInit() 0158 (++) This is the case for instance if you wish to use new OPAMP I/O 0159 0160 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 0161 (++) As in configure case, select first the parameters you wish to modify. 0162 0163 (#) Change from high speed mode to normal power mode (& vice versa) requires 0164 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init(). 0165 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode 0166 alone. 0167 0168 @endverbatim 0169 ****************************************************************************** 0170 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices: 0171 0172 +------------------------------------------------------------------------| 0173 | | | OPAMP1 | OPAMP2 | 0174 |-----------------|---------|----------------------|---------------------| 0175 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 | 0176 | | | VINM1-> PA7 | VINM1-> PG1 | 0177 | | | Internal: | Internal: | 0178 | | | ADC1_IN9 | OPAMP2_OUT | 0179 | | | ADC2_IN9 | PGA mode | 0180 | | | OPAMP1_OUT | | 0181 | | | PGA mode | | 0182 |-----------------|---------|----------------------|---------------------| 0183 | Non Inverting | VP_SEL | | | 0184 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) | 0185 | | | Internal: | Internal: | 0186 | Input | | DAC1_CH1_int | DAC1_CH2_int | 0187 | | | ADC1_IN8 | DAC2_CH1_int | 0188 | | | ADC2_IN8 | COMP2_INP | 0189 | | | COMP1_INP | | 0190 +------------------------------------------------------------------------| 0191 0192 0193 [..] Table 2. OPAMPs outputs for the STM32H7 devices: 0194 0195 +------------------------------------------------------------------------- 0196 | | | OPAMP1 | OPAMP2 | 0197 |-----------------|--------|-----------------------|---------------------| 0198 | Output | VOUT | PC4 | PE7 | 0199 | | | & ADC1_IN4| | & COMP2_INN7 if | 0200 | | | ADC2_IN4 |connected internally | 0201 | | | COMP1_INN7 if | | 0202 | | | connected internally | | 0203 |-----------------|--------|-----------------------|---------------------| 0204 */ 0205 0206 /* Includes ------------------------------------------------------------------*/ 0207 #include "stm32h7xx_hal.h" 0208 0209 /** @addtogroup STM32H7xx_HAL_Driver 0210 * @{ 0211 */ 0212 0213 /** @defgroup OPAMP OPAMP 0214 * @ingroup RTEMSBSPsARMSTM32H7 0215 * @brief OPAMP module driver 0216 * @{ 0217 */ 0218 0219 #ifdef HAL_OPAMP_MODULE_ENABLED 0220 0221 /* Private types -------------------------------------------------------------*/ 0222 /* Private variables ---------------------------------------------------------*/ 0223 /* Private constants ---------------------------------------------------------*/ 0224 /** @addtogroup OPAMP_Private_Constants 0225 * @{ 0226 */ 0227 0228 /* CSR register reset value */ 0229 #define OPAMP_CSR_RESET_VALUE 0x00000000U 0230 0231 /* CSR Init masks */ 0232 0233 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \ 0234 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM) 0235 0236 0237 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \ 0238 | OPAMP_CSR_USERTRIM) 0239 0240 0241 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \ 0242 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM) 0243 /** 0244 * @} 0245 */ 0246 0247 /* Private macros ------------------------------------------------------------*/ 0248 /* Private functions ---------------------------------------------------------*/ 0249 /* Exported functions --------------------------------------------------------*/ 0250 0251 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions 0252 * @ingroup RTEMSBSPsARMSTM32H7 0253 * @{ 0254 */ 0255 0256 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions 0257 * @ingroup RTEMSBSPsARMSTM32H7 0258 * @brief Initialization and Configuration functions 0259 * 0260 @verbatim 0261 ============================================================================== 0262 ##### Initialization and de-initialization functions ##### 0263 ============================================================================== 0264 0265 @endverbatim 0266 * @{ 0267 */ 0268 0269 /** 0270 * @brief Initialize the OPAMP according to the specified 0271 * parameters in the OPAMP_InitTypeDef and initialize the associated handle. 0272 * @note If the selected opamp is locked, initialization can't be performed. 0273 * To unlock the configuration, perform a system reset. 0274 * @param hopamp OPAMP handle 0275 * @retval HAL status 0276 */ 0277 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp) 0278 { 0279 HAL_StatusTypeDef status = HAL_OK; 0280 uint32_t updateotrlpotr; 0281 0282 /* Check the OPAMP handle allocation and lock status */ 0283 /* Init not allowed if calibration is ongoing */ 0284 if(hopamp == NULL) 0285 { 0286 return HAL_ERROR; 0287 } 0288 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 0289 { 0290 return HAL_ERROR; 0291 } 0292 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 0293 { 0294 return HAL_ERROR; 0295 } 0296 else 0297 { 0298 /* Check the parameter */ 0299 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0300 0301 /* Set OPAMP parameters */ 0302 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 0303 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode)); 0304 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput)); 0305 0306 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 0307 if(hopamp->State == HAL_OPAMP_STATE_RESET) 0308 { 0309 if(hopamp->MspInitCallback == NULL) 0310 { 0311 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 0312 } 0313 } 0314 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 0315 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE) 0316 { 0317 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput)); 0318 } 0319 0320 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE) 0321 { 0322 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain)); 0323 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect)); 0324 } 0325 0326 0327 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming)); 0328 0329 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER) 0330 { 0331 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 0332 { 0333 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP)); 0334 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN)); 0335 } 0336 else 0337 { 0338 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed)); 0339 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed)); 0340 } 0341 } 0342 0343 if(hopamp->State == HAL_OPAMP_STATE_RESET) 0344 { 0345 /* Allocate lock resource and initialize it */ 0346 hopamp->Lock = HAL_UNLOCKED; 0347 } 0348 0349 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 0350 hopamp->MspInitCallback(hopamp); 0351 #else 0352 /* Call MSP init function */ 0353 HAL_OPAMP_MspInit(hopamp); 0354 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 0355 0356 /* Set operating mode */ 0357 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON); 0358 /* In PGA mode InvertingInput is Not Applicable */ 0359 if (hopamp->Init.Mode == OPAMP_PGA_MODE) 0360 { 0361 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \ 0362 hopamp->Init.PowerMode | \ 0363 hopamp->Init.Mode | \ 0364 hopamp->Init.PgaGain | \ 0365 hopamp->Init.PgaConnect | \ 0366 hopamp->Init.NonInvertingInput | \ 0367 hopamp->Init.UserTrimming); 0368 } 0369 0370 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE) 0371 { 0372 /* In Follower mode InvertingInput is Not Applicable */ 0373 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \ 0374 hopamp->Init.PowerMode | \ 0375 hopamp->Init.Mode | \ 0376 hopamp->Init.NonInvertingInput | \ 0377 hopamp->Init.UserTrimming); 0378 } 0379 0380 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE) 0381 { 0382 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \ 0383 hopamp->Init.PowerMode | \ 0384 hopamp->Init.Mode | \ 0385 hopamp->Init.InvertingInput | \ 0386 hopamp->Init.NonInvertingInput | \ 0387 hopamp->Init.UserTrimming); 0388 } 0389 0390 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER) 0391 { 0392 /* Set power mode and associated calibration parameters */ 0393 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED) 0394 { 0395 /* OPAMP_POWERMODE_NORMAL */ 0396 /* Set calibration mode (factory or user) and values for */ 0397 /* transistors differential pair high (PMOS) and low (NMOS) for */ 0398 /* normal mode. */ 0399 updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \ 0400 | (hopamp->Init.TrimmingValueN)); 0401 MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 0402 } 0403 else 0404 { 0405 /* OPAMP_POWERMODE_HIGHSPEED*/ 0406 /* transistors differential pair high (PMOS) and low (NMOS) for */ 0407 /* high speed mode. */ 0408 updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \ 0409 | (hopamp->Init.TrimmingValueNHighSpeed)); 0410 MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 0411 } 0412 } 0413 0414 /* Update the OPAMP state*/ 0415 if (hopamp->State == HAL_OPAMP_STATE_RESET) 0416 { 0417 /* From RESET state to READY State */ 0418 hopamp->State = HAL_OPAMP_STATE_READY; 0419 } 0420 /* else: remain in READY or BUSY state (no update) */ 0421 return status; 0422 } 0423 } 0424 0425 /** 0426 * @brief DeInitialize the OPAMP peripheral 0427 * @note Deinitialization can be performed if the OPAMP configuration is locked. 0428 * (the lock is SW in H7) 0429 * @param hopamp OPAMP handle 0430 * @retval HAL status 0431 */ 0432 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp) 0433 { 0434 HAL_StatusTypeDef status = HAL_OK; 0435 0436 /* Check the OPAMP handle allocation */ 0437 /* DeInit not allowed if calibration is on going */ 0438 if(hopamp == NULL) 0439 { 0440 status = HAL_ERROR; 0441 } 0442 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 0443 { 0444 status = HAL_ERROR; 0445 } 0446 else 0447 { 0448 /* Check the parameter */ 0449 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0450 0451 /* Set OPAMP_CSR register to reset value */ 0452 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE); 0453 0454 /* DeInit the low level hardware */ 0455 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 0456 if(hopamp->MspDeInitCallback == NULL) 0457 { 0458 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 0459 } 0460 /* DeInit the low level hardware */ 0461 hopamp->MspDeInitCallback(hopamp); 0462 #else 0463 HAL_OPAMP_MspDeInit(hopamp); 0464 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 0465 0466 /* Update the OPAMP state*/ 0467 hopamp->State = HAL_OPAMP_STATE_RESET; 0468 /* Process unlocked */ 0469 __HAL_UNLOCK(hopamp); 0470 0471 } 0472 0473 return status; 0474 } 0475 0476 0477 /** 0478 * @brief Initialize the OPAMP MSP. 0479 * @param hopamp OPAMP handle 0480 * @retval None 0481 */ 0482 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp) 0483 { 0484 /* Prevent unused argument(s) compilation warning */ 0485 UNUSED(hopamp); 0486 0487 /* NOTE : This function should not be modified, when the callback is needed, 0488 the function "HAL_OPAMP_MspInit()" must be implemented in the user file. 0489 */ 0490 } 0491 0492 /** 0493 * @brief DeInitialize OPAMP MSP. 0494 * @param hopamp OPAMP handle 0495 * @retval None 0496 */ 0497 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp) 0498 { 0499 /* Prevent unused argument(s) compilation warning */ 0500 UNUSED(hopamp); 0501 /* NOTE : This function should not be modified, when the callback is needed, 0502 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file. 0503 */ 0504 } 0505 0506 /** 0507 * @} 0508 */ 0509 0510 0511 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions 0512 * @ingroup RTEMSBSPsARMSTM32H7 0513 * @brief IO operation functions 0514 * 0515 @verbatim 0516 =============================================================================== 0517 ##### IO operation functions ##### 0518 =============================================================================== 0519 [..] 0520 This subsection provides a set of functions allowing to manage the OPAMP 0521 start, stop and calibration actions. 0522 0523 @endverbatim 0524 * @{ 0525 */ 0526 0527 /** 0528 * @brief Start the OPAMP. 0529 * @param hopamp OPAMP handle 0530 * @retval HAL status 0531 */ 0532 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp) 0533 { 0534 HAL_StatusTypeDef status = HAL_OK; 0535 0536 /* Check the OPAMP handle allocation */ 0537 /* Check if OPAMP locked */ 0538 if(hopamp == NULL) 0539 { 0540 status = HAL_ERROR; 0541 } 0542 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 0543 { 0544 status = HAL_ERROR; 0545 } 0546 else 0547 { 0548 /* Check the parameter */ 0549 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0550 0551 if(hopamp->State == HAL_OPAMP_STATE_READY) 0552 { 0553 /* Enable the selected opamp */ 0554 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 0555 0556 /* Update the OPAMP state*/ 0557 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */ 0558 hopamp->State = HAL_OPAMP_STATE_BUSY; 0559 } 0560 else 0561 { 0562 status = HAL_ERROR; 0563 } 0564 0565 } 0566 return status; 0567 } 0568 0569 /** 0570 * @brief Stop the OPAMP. 0571 * @param hopamp OPAMP handle 0572 * @retval HAL status 0573 */ 0574 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp) 0575 { 0576 HAL_StatusTypeDef status = HAL_OK; 0577 0578 /* Check the OPAMP handle allocation */ 0579 /* Check if OPAMP locked */ 0580 /* Check if OPAMP calibration ongoing */ 0581 if(hopamp == NULL) 0582 { 0583 status = HAL_ERROR; 0584 } 0585 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 0586 { 0587 status = HAL_ERROR; 0588 } 0589 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 0590 { 0591 status = HAL_ERROR; 0592 } 0593 else 0594 { 0595 /* Check the parameter */ 0596 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0597 0598 if(hopamp->State == HAL_OPAMP_STATE_BUSY) 0599 { 0600 /* Disable the selected opamp */ 0601 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 0602 0603 /* Update the OPAMP state*/ 0604 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/ 0605 hopamp->State = HAL_OPAMP_STATE_READY; 0606 } 0607 else 0608 { 0609 status = HAL_ERROR; 0610 } 0611 } 0612 return status; 0613 } 0614 0615 /** 0616 * @brief Run the self calibration of one OPAMP. 0617 * @note Calibration is performed in the mode specified in OPAMP init 0618 * structure (mode normal or high-speed). To perform calibration for 0619 * both modes, repeat this function twice after OPAMP init structure 0620 * accordingly updated. 0621 * @param hopamp handle 0622 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled 0623 * @retval HAL status 0624 */ 0625 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp) 0626 { 0627 0628 HAL_StatusTypeDef status = HAL_OK; 0629 0630 uint32_t trimmingvaluen; 0631 uint32_t trimmingvaluep; 0632 uint32_t delta; 0633 uint32_t opampmode; 0634 0635 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */ 0636 0637 /* Check the OPAMP handle allocation */ 0638 /* Check if OPAMP locked */ 0639 if(hopamp == NULL) 0640 { 0641 status = HAL_ERROR; 0642 } 0643 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 0644 { 0645 status = HAL_ERROR; 0646 } 0647 else 0648 { 0649 0650 /* Check if OPAMP in calibration mode and calibration not yet enable */ 0651 if(hopamp->State == HAL_OPAMP_STATE_READY) 0652 { 0653 /* Check the parameter */ 0654 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0655 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 0656 0657 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL); 0658 0659 /* Use of standalone mode */ 0660 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE); 0661 /* user trimming values are used for offset calibration */ 0662 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM); 0663 0664 /* Select trimming settings depending on power mode */ 0665 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 0666 { 0667 tmp_opamp_reg_trimming = &hopamp->Instance->OTR; 0668 0669 } 0670 else 0671 { 0672 /* high speed Mode */ 0673 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR; 0674 } 0675 0676 0677 /* Enable calibration */ 0678 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 0679 0680 /* Force internal reference on VP */ 0681 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); 0682 0683 /* 1st calibration - N */ 0684 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA); 0685 0686 /* Enable the selected opamp */ 0687 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 0688 0689 /* Init trimming counter */ 0690 /* Medium value */ 0691 trimmingvaluen = 16U; 0692 delta = 8U; 0693 0694 while (delta != 0U) 0695 { 0696 /* Set candidate trimming */ 0697 /* OPAMP_POWERMODE_NORMAL */ 0698 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 0699 0700 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 0701 /* Offset trim time: during calibration, minimum time needed between */ 0702 /* two steps to have 1 mV accuracy */ 0703 HAL_Delay(OPAMP_TRIMMING_DELAY); 0704 0705 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U) 0706 { 0707 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 0708 trimmingvaluen += delta; 0709 } 0710 else 0711 { 0712 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 0713 trimmingvaluen -= delta; 0714 } 0715 /* Divide range by 2 to continue dichotomy sweep */ 0716 delta >>= 1; 0717 } 0718 0719 /* Still need to check if right calibration is current value or one step below */ 0720 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 0721 0722 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 0723 0724 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 0725 /* Offset trim time: during calibration, minimum time needed between */ 0726 /* two steps to have 1 mV accuracy */ 0727 HAL_Delay(OPAMP_TRIMMING_DELAY); 0728 0729 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U) 0730 { 0731 /* Trimming value is actually one value more */ 0732 trimmingvaluen++; 0733 /* Set right trimming */ 0734 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 0735 } 0736 0737 /* 2nd calibration - P */ 0738 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA); 0739 0740 /* Init trimming counter */ 0741 /* Medium value */ 0742 trimmingvaluep = 16U; 0743 delta = 8U; 0744 0745 while (delta != 0U) 0746 { 0747 /* Set candidate trimming */ 0748 /* OPAMP_POWERMODE_NORMAL */ 0749 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 0750 0751 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 0752 /* Offset trim time: during calibration, minimum time needed between */ 0753 /* two steps to have 1 mV accuracy */ 0754 HAL_Delay(OPAMP_TRIMMING_DELAY); 0755 0756 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U) 0757 { 0758 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 0759 trimmingvaluep += delta; 0760 } 0761 else 0762 { 0763 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 0764 trimmingvaluep -= delta; 0765 } 0766 0767 /* Divide range by 2 to continue dichotomy sweep */ 0768 delta >>= 1U; 0769 } 0770 0771 /* Still need to check if right calibration is current value or one step below */ 0772 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 0773 /* Set candidate trimming */ 0774 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 0775 0776 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 0777 /* Offset trim time: during calibration, minimum time needed between */ 0778 /* two steps to have 1 mV accuracy */ 0779 HAL_Delay(OPAMP_TRIMMING_DELAY); 0780 0781 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U) 0782 { 0783 /* Trimming value is actually one value more */ 0784 trimmingvaluep++; 0785 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 0786 } 0787 0788 /* Disable calibration & set normal mode (operating mode) */ 0789 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 0790 0791 /* Disable the OPAMP */ 0792 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 0793 0794 /* Set operating mode back */ 0795 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); 0796 0797 /* Self calibration is successful */ 0798 /* Store calibration(user trimming) results in init structure. */ 0799 0800 /* Set user trimming mode */ 0801 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER; 0802 0803 /* Affect calibration parameters depending on mode normal/high speed */ 0804 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED) 0805 { 0806 /* Write calibration result N */ 0807 hopamp->Init.TrimmingValueN = trimmingvaluen; 0808 /* Write calibration result P */ 0809 hopamp->Init.TrimmingValueP = trimmingvaluep; 0810 } 0811 else 0812 { 0813 /* Write calibration result N */ 0814 hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen; 0815 /* Write calibration result P */ 0816 hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep; 0817 } 0818 /* Restore OPAMP mode after calibration */ 0819 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode); 0820 } 0821 0822 else 0823 { 0824 /* OPAMP can not be calibrated from this mode */ 0825 status = HAL_ERROR; 0826 } 0827 } 0828 return status; 0829 } 0830 0831 /** 0832 * @} 0833 */ 0834 0835 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions 0836 * @ingroup RTEMSBSPsARMSTM32H7 0837 * @brief Peripheral Control functions 0838 * 0839 @verbatim 0840 =============================================================================== 0841 ##### Peripheral Control functions ##### 0842 =============================================================================== 0843 [..] 0844 This subsection provides a set of functions allowing to control the OPAMP data 0845 transfers. 0846 0847 0848 0849 @endverbatim 0850 * @{ 0851 */ 0852 0853 /** 0854 * @brief Lock the selected OPAMP configuration. 0855 * @note On STM32H7, HAL OPAMP lock is software lock only (in 0856 * contrast of hardware lock available on some other STM32 0857 * devices) 0858 * @param hopamp OPAMP handle 0859 * @retval HAL status 0860 */ 0861 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp) 0862 { 0863 HAL_StatusTypeDef status = HAL_OK; 0864 0865 /* Check the OPAMP handle allocation */ 0866 /* Check if OPAMP locked */ 0867 /* OPAMP can be locked when enabled and running in normal mode */ 0868 /* It is meaningless otherwise */ 0869 if(hopamp == NULL) 0870 { 0871 status = HAL_ERROR; 0872 } 0873 0874 else if(hopamp->State != HAL_OPAMP_STATE_BUSY) 0875 { 0876 status = HAL_ERROR; 0877 } 0878 else 0879 { 0880 /* Check the parameter */ 0881 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0882 0883 /* OPAMP state changed to locked */ 0884 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED; 0885 } 0886 return status; 0887 } 0888 0889 /** 0890 * @brief Return the OPAMP factory trimming value. 0891 * @note On STM32H7 OPAMP, user can retrieve factory trimming if 0892 * OPAMP has never been set to user trimming before. 0893 * Therefore, this function must be called when OPAMP init 0894 * parameter "UserTrimming" is set to trimming factory, 0895 * and before OPAMP calibration (function 0896 * "HAL_OPAMP_SelfCalibrate()"). 0897 * Otherwise, factory trimming value cannot be retrieved and 0898 * error status is returned. 0899 * @param hopamp OPAMP handle 0900 * @param trimmingoffset Trimming offset (P or N) 0901 * This parameter must be a value of @ref OPAMP_FactoryTrimming 0902 * @note Calibration parameter retrieved is corresponding to the mode 0903 * specified in OPAMP init structure (mode normal or high-speed). 0904 * To retrieve calibration parameters for both modes, repeat this 0905 * function after OPAMP init structure accordingly updated. 0906 * @retval Trimming value (P or N): range: 0->31 0907 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available 0908 * 0909 */ 0910 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset) 0911 { 0912 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue; 0913 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */ 0914 0915 /* Check the OPAMP handle allocation */ 0916 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */ 0917 if(hopamp == NULL) 0918 { 0919 return OPAMP_FACTORYTRIMMING_DUMMY; 0920 } 0921 0922 if(hopamp->State == HAL_OPAMP_STATE_READY) 0923 { 0924 /* Check the parameter */ 0925 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 0926 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset)); 0927 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 0928 0929 /* Check the trimming mode */ 0930 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U) 0931 { 0932 /* This function must called when OPAMP init parameter "UserTrimming" */ 0933 /* is set to trimming factory, and before OPAMP calibration (function */ 0934 /* "HAL_OPAMP_SelfCalibrate()"). */ 0935 /* Otherwise, factory trimming value cannot be retrieved and error */ 0936 /* status is returned. */ 0937 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY; 0938 } 0939 else 0940 { 0941 /* Select trimming settings depending on power mode */ 0942 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 0943 { 0944 tmp_opamp_reg_trimming = &hopamp->Instance->OTR; 0945 } 0946 else 0947 { 0948 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR; 0949 } 0950 0951 /* Get factory trimming */ 0952 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P) 0953 { 0954 /* OPAMP_FACTORYTRIMMING_P */ 0955 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING; 0956 } 0957 else 0958 { 0959 /* OPAMP_FACTORYTRIMMING_N */ 0960 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN; 0961 } 0962 } 0963 } 0964 else 0965 { 0966 return OPAMP_FACTORYTRIMMING_DUMMY; 0967 } 0968 0969 return trimmingvalue; 0970 } 0971 0972 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1) 0973 /** 0974 * @brief Register a User OPAMP Callback 0975 * To be used instead of the weak (overridden) predefined callback 0976 * @param hopamp OPAMP handle 0977 * @param CallbackId ID of the callback to be registered 0978 * This parameter can be one of the following values: 0979 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID 0980 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID 0981 * @param pCallback pointer to the Callback function 0982 * @retval status 0983 */ 0984 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback) 0985 { 0986 HAL_StatusTypeDef status = HAL_OK; 0987 0988 if(pCallback == NULL) 0989 { 0990 return HAL_ERROR; 0991 } 0992 0993 /* Process locked */ 0994 __HAL_LOCK(hopamp); 0995 0996 if(hopamp->State == HAL_OPAMP_STATE_READY) 0997 { 0998 switch (CallbackId) 0999 { 1000 case HAL_OPAMP_MSPINIT_CB_ID : 1001 hopamp->MspInitCallback = pCallback; 1002 break; 1003 case HAL_OPAMP_MSPDEINIT_CB_ID : 1004 hopamp->MspDeInitCallback = pCallback; 1005 break; 1006 default : 1007 /* update return status */ 1008 status = HAL_ERROR; 1009 break; 1010 } 1011 } 1012 else if (hopamp->State == HAL_OPAMP_STATE_RESET) 1013 { 1014 switch (CallbackId) 1015 { 1016 case HAL_OPAMP_MSPINIT_CB_ID : 1017 hopamp->MspInitCallback = pCallback; 1018 break; 1019 case HAL_OPAMP_MSPDEINIT_CB_ID : 1020 hopamp->MspDeInitCallback = pCallback; 1021 break; 1022 default : 1023 /* update return status */ 1024 status = HAL_ERROR; 1025 break; 1026 } 1027 } 1028 else 1029 { 1030 /* update return status */ 1031 status = HAL_ERROR; 1032 } 1033 1034 /* Release Lock */ 1035 __HAL_UNLOCK(hopamp); 1036 return status; 1037 } 1038 1039 /** 1040 * @brief Unregister a User OPAMP Callback 1041 * OPAMP Callback is redirected to the weak (overridden) predefined callback 1042 * @param hopamp OPAMP handle 1043 * @param CallbackId ID of the callback to be unregistered 1044 * This parameter can be one of the following values: 1045 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID 1046 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID 1047 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks 1048 * @retval status 1049 */ 1050 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId) 1051 { 1052 HAL_StatusTypeDef status = HAL_OK; 1053 1054 /* Process locked */ 1055 __HAL_LOCK(hopamp); 1056 1057 if(hopamp->State == HAL_OPAMP_STATE_READY) 1058 { 1059 switch (CallbackId) 1060 { 1061 case HAL_OPAMP_MSPINIT_CB_ID : 1062 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 1063 break; 1064 case HAL_OPAMP_MSPDEINIT_CB_ID : 1065 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 1066 break; 1067 case HAL_OPAMP_ALL_CB_ID : 1068 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 1069 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 1070 break; 1071 default : 1072 /* update return status */ 1073 status = HAL_ERROR; 1074 break; 1075 } 1076 } 1077 else if (hopamp->State == HAL_OPAMP_STATE_RESET) 1078 { 1079 switch (CallbackId) 1080 { 1081 case HAL_OPAMP_MSPINIT_CB_ID : 1082 hopamp->MspInitCallback = HAL_OPAMP_MspInit; 1083 break; 1084 case HAL_OPAMP_MSPDEINIT_CB_ID : 1085 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit; 1086 break; 1087 default : 1088 /* update return status */ 1089 status = HAL_ERROR; 1090 break; 1091 } 1092 } 1093 else 1094 { 1095 /* update return status */ 1096 status = HAL_ERROR; 1097 } 1098 1099 /* Release Lock */ 1100 __HAL_UNLOCK(hopamp); 1101 return status; 1102 } 1103 1104 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */ 1105 1106 /** 1107 * @} 1108 */ 1109 1110 1111 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions 1112 * @ingroup RTEMSBSPsARMSTM32H7 1113 * @brief Peripheral State functions 1114 * 1115 @verbatim 1116 =============================================================================== 1117 ##### Peripheral State functions ##### 1118 =============================================================================== 1119 [..] 1120 This subsection permits to get in run-time the status of the peripheral. 1121 1122 @endverbatim 1123 * @{ 1124 */ 1125 1126 /** 1127 * @brief Return the OPAMP handle state. 1128 * @param hopamp OPAMP handle 1129 * @retval HAL state 1130 */ 1131 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp) 1132 { 1133 /* Check the OPAMP handle allocation */ 1134 if(hopamp == NULL) 1135 { 1136 return HAL_OPAMP_STATE_RESET; 1137 } 1138 1139 /* Check the parameter */ 1140 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 1141 1142 /* Return OPAMP handle state */ 1143 return hopamp->State; 1144 } 1145 1146 /** 1147 * @} 1148 */ 1149 1150 /** 1151 * @} 1152 */ 1153 #endif /* HAL_OPAMP_MODULE_ENABLED */ 1154 /** 1155 * @} 1156 */ 1157 1158 /** 1159 * @} 1160 */ 1161
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |