Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stm32l4xx_hal_opamp.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4xx_hal_opamp.c 00004 * @author MCD Application Team 00005 * @version V1.5.1 00006 * @date 31-May-2016 00007 * @brief OPAMP HAL module driver. 00008 * This file provides firmware functions to manage the following 00009 * functionalities of the operational amplifier(s) peripheral: 00010 * + OPAMP configuration 00011 * + OPAMP calibration 00012 * Thanks to 00013 * + Initialization and de-initialization functions 00014 * + IO operation functions 00015 * + Peripheral Control functions 00016 * + Peripheral State functions 00017 * 00018 @verbatim 00019 ================================================================================ 00020 ##### OPAMP Peripheral Features ##### 00021 ================================================================================ 00022 00023 [..] The device integrates 1 or 2 operational amplifiers OPAMP1 & OPAMP2 00024 00025 (#) The OPAMP(s) provide(s) several exclusive running modes. 00026 (++) 1 OPAMP: STM32L431xx STM32L432xx STM32L433xx STM32L442xx STM32L443xx 00027 (++) 2 OPAMP: STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx 00028 00029 (#) The OPAMP(s) provide(s) several exclusive running modes. 00030 (++) Standalone mode 00031 (++) Programmable Gain Amplifier (PGA) mode (Resistor feedback output) 00032 (++) Follower mode 00033 00034 (#) All OPAMP (same for all OPAMPs) can operate in 00035 (++) Either Low range (VDDA < 2.4V) power supply 00036 (++) Or High range (VDDA > 2.4V) power supply 00037 00038 (#) Each OPAMP(s) can be configured in normal and low power mode. 00039 00040 (#) The OPAMP(s) provide(s) calibration capabilities. 00041 (++) Calibration aims at correcting some offset for running mode. 00042 (++) The OPAMP uses either factory calibration settings OR user defined 00043 calibration (trimming) settings (i.e. trimming mode). 00044 (++) The user defined settings can be figured out using self calibration 00045 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll 00046 (++) HAL_OPAMP_SelfCalibrate: 00047 (+++) Runs automatically the calibration. 00048 (+++) Enables the user trimming mode 00049 (+++) Updates the init structure with trimming values with fresh calibration 00050 results. 00051 The user may store the calibration results for larger 00052 (ex monitoring the trimming as a function of temperature 00053 for instance) 00054 (+++) HAL_OPAMPEx_SelfCalibrateAll 00055 runs calibration of all OPAMPs in parallel to save search time. 00056 00057 (#) Running mode: Standalone mode 00058 (++) Gain is set externally (gain depends on external loads). 00059 (++) Follower mode also possible externally by connecting the inverting input to 00060 the output. 00061 00062 (#) Running mode: Follower mode 00063 (++) No Inverting Input is connected. 00064 00065 (#) Running mode: Programmable Gain Amplifier (PGA) mode 00066 (Resistor feedback output) 00067 (++) The OPAMP(s) output(s) can be internally connected to resistor feedback 00068 output. 00069 (++) OPAMP gain is either 2, 4, 8 or 16. 00070 00071 (#) The OPAMPs inverting input can be selected according to the Reference Manual 00072 "OPAMP function description" chapter. 00073 00074 (#) The OPAMPs non inverting input can be selected according to the Reference Manual 00075 "OPAMP function description" chapter. 00076 00077 00078 ##### How to use this driver ##### 00079 ================================================================================ 00080 [..] 00081 00082 *** Power supply range *** 00083 ============================================ 00084 [..] To run in low power mode: 00085 00086 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00087 (++) Select OPAMP_POWERSUPPLY_LOW (VDDA lower than 2.4V) 00088 (++) Otherwise select OPAMP_POWERSUPPLY_HIGH (VDDA higher than 2.4V) 00089 00090 *** Low / normal power mode *** 00091 ============================================ 00092 [..] To run in low power mode: 00093 00094 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00095 (++) Select OPAMP_POWERMODE_LOWPOWER 00096 (++) Otherwise select OPAMP_POWERMODE_NORMAL 00097 00098 *** Calibration *** 00099 ============================================ 00100 [..] To run the OPAMP calibration self calibration: 00101 00102 (#) Start calibration using HAL_OPAMP_SelfCalibrate. 00103 Store the calibration results. 00104 00105 *** Running mode *** 00106 ============================================ 00107 00108 [..] To use the OPAMP, perform the following steps: 00109 00110 (#) Fill in the HAL_OPAMP_MspInit() to 00111 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE() 00112 (++) Configure the OPAMP input AND output in analog mode using 00113 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin. 00114 00115 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00116 (++) Select the mode 00117 (++) Select the inverting input 00118 (++) Select the non-inverting input 00119 (++) If PGA mode is enabled, Select if inverting input is connected. 00120 (++) Select either factory or user defined trimming mode. 00121 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values 00122 (typically values set by HAL_OPAMP_SelfCalibrate function). 00123 00124 (#) Enable the OPAMP using HAL_OPAMP_Start() function. 00125 00126 (#) Disable the OPAMP using HAL_OPAMP_Stop() function. 00127 00128 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function. 00129 Caution: On STM32L4, HAL OPAMP lock is software lock only (not 00130 hardware lock as on some other STM32 devices) 00131 00132 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function. 00133 00134 *** Running mode: change of configuration while OPAMP ON *** 00135 ============================================ 00136 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly) 00137 (#) If needed, fill in the HAL_OPAMP_MspInit() 00138 (++) This is the case for instance if you wish to use new OPAMP I/O 00139 00140 (#) Configure the OPAMP using HAL_OPAMP_Init() function: 00141 (++) As in configure case, select first the parameters you wish to modify. 00142 00143 (#) Change from low power mode to normal power mode (& vice versa) requires 00144 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init(). 00145 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode 00146 alone. 00147 00148 @endverbatim 00149 ****************************************************************************** 00150 00151 Table 1. OPAMPs inverting/non-inverting inputs for the STM32L4 devices: 00152 +------------------------------------------------------------------------| 00153 | | | OPAMP1 | OPAMP2 | 00154 |-----------------|---------|----------------------|---------------------| 00155 | Inverting Input | VM_SEL | | | 00156 | | | IO0-> PA1 | IO0-> PA7 | 00157 | | | LOW LEAKAGE IO (2) | LOW LEAKAGE IO (2) | 00158 | | | Not connected | Not connected | 00159 | (1) | | PGA mode only | PGA mode only | 00160 |-----------------|---------|----------------------|---------------------| 00161 | Non Inverting | VP_SEL | | | 00162 | | | IO0-> PA0 (GPIO) | IO0-> PA6 (GPIO) | 00163 | Input | | DAC1_OUT1 internal | DAC1_OUT2 internal | 00164 +------------------------------------------------------------------------| 00165 (1): NA in follower mode. 00166 (2): Available on some package only (ex. BGA132). 00167 00168 00169 Table 2. OPAMPs outputs for the STM32L4 devices: 00170 00171 +------------------------------------------------------------------------- 00172 | | | OPAMP1 | OPAMP2 | 00173 |-----------------|--------|-----------------------|---------------------| 00174 | Output | VOUT | PA3 | PB0 | 00175 | | | & (1) ADC12_IN if | & (1) ADC12_IN if | 00176 | | | connected internally | connected internally| 00177 |-----------------|--------|-----------------------|---------------------| 00178 (1): ADC1 or ADC2 shall select IN15. 00179 00180 ****************************************************************************** 00181 * @attention 00182 * 00183 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00184 * 00185 * Redistribution and use in source and binary forms, with or without modification, 00186 * are permitted provided that the following conditions are met: 00187 * 1. Redistributions of source code must retain the above copyright notice, 00188 * this list of conditions and the following disclaimer. 00189 * 2. Redistributions in binary form must reproduce the above copyright notice, 00190 * this list of conditions and the following disclaimer in the documentation 00191 * and/or other materials provided with the distribution. 00192 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00193 * may be used to endorse or promote products derived from this software 00194 * without specific prior written permission. 00195 * 00196 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00197 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00198 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00199 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00200 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00201 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00202 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00203 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00204 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00205 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00206 * 00207 ****************************************************************************** 00208 */ 00209 00210 /* Includes ------------------------------------------------------------------*/ 00211 #include "stm32l4xx_hal.h" 00212 00213 /** @addtogroup STM32L4xx_HAL_Driver 00214 * @{ 00215 */ 00216 00217 /** @defgroup OPAMP OPAMP 00218 * @brief OPAMP module driver 00219 * @{ 00220 */ 00221 00222 #ifdef HAL_OPAMP_MODULE_ENABLED 00223 00224 /* Private types -------------------------------------------------------------*/ 00225 /* Private variables ---------------------------------------------------------*/ 00226 /* Private constants ---------------------------------------------------------*/ 00227 /** @addtogroup OPAMP_Private_Constants 00228 * @{ 00229 */ 00230 00231 /* CSR register reset value */ 00232 #define OPAMP_CSR_RESET_VALUE ((uint32_t)0x00000000) 00233 00234 #define OPAMP_CSR_RESET_BITS (OPAMP_CSR_OPAMPxEN | OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE \ 00235 | OPAMP_CSR_PGGAIN | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \ 00236 | OPAMP_CSR_CALON | OPAMP_CSR_USERTRIM) 00237 00238 /* CSR Init masks */ 00239 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_PGGAIN \ 00240 | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM) 00241 00242 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_VPSEL \ 00243 | OPAMP_CSR_USERTRIM) 00244 00245 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_VPSEL \ 00246 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM) 00247 00248 00249 /** 00250 * @} 00251 */ 00252 00253 /* Private macros ------------------------------------------------------------*/ 00254 /* Private functions ---------------------------------------------------------*/ 00255 /* Exported functions --------------------------------------------------------*/ 00256 00257 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions 00258 * @{ 00259 */ 00260 00261 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions 00262 * @brief Initialization and Configuration functions 00263 * 00264 @verbatim 00265 ============================================================================== 00266 ##### Initialization and de-initialization functions ##### 00267 ============================================================================== 00268 00269 @endverbatim 00270 * @{ 00271 */ 00272 00273 /** 00274 * @brief Initializes the OPAMP according to the specified 00275 * parameters in the OPAMP_InitTypeDef and initialize the associated handle. 00276 * @note If the selected opamp is locked, initialization can't be performed. 00277 * To unlock the configuration, perform a system reset. 00278 * @param hopamp: OPAMP handle 00279 * @retval HAL status 00280 */ 00281 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp) 00282 { 00283 HAL_StatusTypeDef status = HAL_OK; 00284 uint32_t updateotrlpotr = 0; 00285 00286 /* Check the OPAMP handle allocation and lock status */ 00287 /* Init not allowed if calibration is ongoing */ 00288 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) 00289 || (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_POWER_SUPPLY_RANGE(hopamp->Init.PowerSupplyRange)); 00300 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00301 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode)); 00302 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput)); 00303 00304 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE) 00305 { 00306 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput)); 00307 } 00308 00309 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE) 00310 { 00311 assert_param(IS_OPAMP_INVERTING_INPUT_PGA(hopamp->Init.InvertingInput)); 00312 } 00313 00314 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE) 00315 { 00316 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain)); 00317 } 00318 00319 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming)); 00320 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER) 00321 { 00322 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00323 { 00324 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP)); 00325 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN)); 00326 } 00327 else 00328 { 00329 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePLowPower)); 00330 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNLowPower)); 00331 } 00332 } 00333 00334 if(hopamp->State == HAL_OPAMP_STATE_RESET) 00335 { 00336 /* Allocate lock resource and initialize it */ 00337 hopamp->Lock = HAL_UNLOCKED; 00338 } 00339 00340 /* Call MSP init function */ 00341 HAL_OPAMP_MspInit(hopamp); 00342 00343 /* Set operating mode */ 00344 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON); 00345 00346 if (hopamp->Init.Mode == OPAMP_PGA_MODE) 00347 { 00348 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \ 00349 hopamp->Init.PowerMode | \ 00350 hopamp->Init.Mode | \ 00351 hopamp->Init.PgaGain | \ 00352 hopamp->Init.InvertingInput | \ 00353 hopamp->Init.NonInvertingInput | \ 00354 hopamp->Init.UserTrimming); 00355 } 00356 00357 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE) 00358 { 00359 /* In Follower mode InvertingInput is Not Applicable */ 00360 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \ 00361 hopamp->Init.PowerMode | \ 00362 hopamp->Init.Mode | \ 00363 hopamp->Init.NonInvertingInput | \ 00364 hopamp->Init.UserTrimming); 00365 } 00366 00367 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE) 00368 { 00369 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \ 00370 hopamp->Init.PowerMode | \ 00371 hopamp->Init.Mode | \ 00372 hopamp->Init.InvertingInput | \ 00373 hopamp->Init.NonInvertingInput | \ 00374 hopamp->Init.UserTrimming); 00375 } 00376 00377 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER) 00378 { 00379 /* Set power mode and associated calibration parameters */ 00380 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER) 00381 { 00382 /* OPAMP_POWERMODE_NORMAL */ 00383 /* Set calibration mode (factory or user) and values for */ 00384 /* transistors differential pair high (PMOS) and low (NMOS) for */ 00385 /* normal mode. */ 00386 updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \ 00387 | (hopamp->Init.TrimmingValueN)); 00388 MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 00389 } 00390 else 00391 { 00392 /* OPAMP_POWERMODE_LOWPOWER */ 00393 /* transistors differential pair high (PMOS) and low (NMOS) for */ 00394 /* low power mode. */ 00395 updateotrlpotr = (((hopamp->Init.TrimmingValuePLowPower) << (OPAMP_INPUT_NONINVERTING)) \ 00396 | (hopamp->Init.TrimmingValueNLowPower)); 00397 MODIFY_REG(hopamp->Instance->LPOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr); 00398 } 00399 } 00400 00401 /* Configure the power supply range */ 00402 /* The OPAMP_CSR_OPARANGE is common configuration for all OPAMPs */ 00403 /* bit OPAMP1_CSR_OPARANGE is used for both OPAMPs */ 00404 MODIFY_REG(OPAMP1->CSR, OPAMP1_CSR_OPARANGE, hopamp->Init.PowerSupplyRange); 00405 00406 /* Update the OPAMP state*/ 00407 if (hopamp->State == HAL_OPAMP_STATE_RESET) 00408 { 00409 /* From RESET state to READY State */ 00410 hopamp->State = HAL_OPAMP_STATE_READY; 00411 } 00412 /* else: remain in READY or BUSY state (no update) */ 00413 return status; 00414 } 00415 } 00416 00417 /** 00418 * @brief DeInitialize the OPAMP peripheral. 00419 * @note Deinitialization can be performed if the OPAMP configuration is locked. 00420 * (the lock is SW in L4) 00421 * @param hopamp: OPAMP handle 00422 * @retval HAL status 00423 */ 00424 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp) 00425 { 00426 HAL_StatusTypeDef status = HAL_OK; 00427 00428 /* Check the OPAMP handle allocation */ 00429 /* DeInit not allowed if calibration is ongoing */ 00430 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)) 00431 { 00432 status = HAL_ERROR; 00433 } 00434 else 00435 { 00436 /* Check the parameter */ 00437 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00438 00439 /* Set OPAMP_CSR register to reset value */ 00440 /* Mind that OPAMP1_CSR_OPARANGE of CSR of OPAMP1 remains unchanged (applies to both OPAMPs) */ 00441 /* OPAMP shall be disabled first separately */ 00442 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00443 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_BITS, OPAMP_CSR_RESET_VALUE); 00444 00445 /* DeInit the low level hardware: GPIO, CLOCK and NVIC */ 00446 HAL_OPAMP_MspDeInit(hopamp); 00447 00448 /* Update the OPAMP state*/ 00449 hopamp->State = HAL_OPAMP_STATE_RESET; 00450 } 00451 00452 /* Process unlocked */ 00453 __HAL_UNLOCK(hopamp); 00454 00455 return status; 00456 } 00457 00458 00459 /** 00460 * @brief Initialize the OPAMP MSP. 00461 * @param hopamp: OPAMP handle 00462 * @retval None 00463 */ 00464 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp) 00465 { 00466 /* Prevent unused argument(s) compilation warning */ 00467 UNUSED(hopamp); 00468 00469 /* NOTE : This function should not be modified, when the callback is needed, 00470 the function "HAL_OPAMP_MspInit()" must be implemented in the user file. 00471 */ 00472 } 00473 00474 /** 00475 * @brief DeInitialize OPAMP MSP. 00476 * @param hopamp: OPAMP handle 00477 * @retval None 00478 */ 00479 __weak void HAL_OPAMP_MspDeInit(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_MspDeInit()" must be implemented in the user file. 00486 */ 00487 } 00488 00489 /** 00490 * @} 00491 */ 00492 00493 00494 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions 00495 * @brief IO operation functions 00496 * 00497 @verbatim 00498 =============================================================================== 00499 ##### IO operation functions ##### 00500 =============================================================================== 00501 [..] 00502 This subsection provides a set of functions allowing to manage the OPAMP 00503 start, stop and calibration actions. 00504 00505 @endverbatim 00506 * @{ 00507 */ 00508 00509 /** 00510 * @brief Start the OPAMP. 00511 * @param hopamp: OPAMP handle 00512 * @retval HAL status 00513 */ 00514 00515 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp) 00516 { 00517 HAL_StatusTypeDef status = HAL_OK; 00518 00519 /* Check the OPAMP handle allocation */ 00520 /* Check if OPAMP locked */ 00521 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) 00522 { 00523 status = HAL_ERROR; 00524 } 00525 else 00526 { 00527 /* Check the parameter */ 00528 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00529 00530 if(hopamp->State == HAL_OPAMP_STATE_READY) 00531 { 00532 /* Enable the selected opamp */ 00533 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00534 00535 /* Update the OPAMP state*/ 00536 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */ 00537 hopamp->State = HAL_OPAMP_STATE_BUSY; 00538 } 00539 else 00540 { 00541 status = HAL_ERROR; 00542 } 00543 00544 } 00545 return status; 00546 } 00547 00548 /** 00549 * @brief Stop the OPAMP. 00550 * @param hopamp: OPAMP handle 00551 * @retval HAL status 00552 */ 00553 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp) 00554 { 00555 HAL_StatusTypeDef status = HAL_OK; 00556 00557 /* Check the OPAMP handle allocation */ 00558 /* Check if OPAMP locked */ 00559 /* Check if OPAMP calibration ongoing */ 00560 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \ 00561 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)) 00562 { 00563 status = HAL_ERROR; 00564 } 00565 else 00566 { 00567 /* Check the parameter */ 00568 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00569 00570 if(hopamp->State == HAL_OPAMP_STATE_BUSY) 00571 { 00572 /* Disable the selected opamp */ 00573 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00574 00575 /* Update the OPAMP state*/ 00576 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/ 00577 hopamp->State = HAL_OPAMP_STATE_READY; 00578 } 00579 else 00580 { 00581 status = HAL_ERROR; 00582 } 00583 } 00584 return status; 00585 } 00586 00587 /** 00588 * @brief Run the self calibration of one OPAMP. 00589 * @note Calibration is performed in the mode specified in OPAMP init 00590 * structure (mode normal or low-power). To perform calibration for 00591 * both modes, repeat this function twice after OPAMP init structure 00592 * accordingly updated. 00593 * @note Calibration runs about 10 ms. 00594 * @param hopamp handle 00595 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled 00596 * @retval HAL status 00597 00598 */ 00599 00600 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp) 00601 { 00602 00603 HAL_StatusTypeDef status = HAL_OK; 00604 00605 uint32_t trimmingvaluen = 0; 00606 uint32_t trimmingvaluep = 0; 00607 uint32_t delta; 00608 uint32_t opampmode; 00609 00610 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */ 00611 00612 /* Check the OPAMP handle allocation */ 00613 /* Check if OPAMP locked */ 00614 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) 00615 { 00616 status = HAL_ERROR; 00617 } 00618 else 00619 { 00620 /* Check if OPAMP in calibration mode and calibration not yet enable */ 00621 if(hopamp->State == HAL_OPAMP_STATE_READY) 00622 { 00623 /* Check the parameter */ 00624 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00625 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00626 00627 /* Save OPAMP mode as in */ 00628 /* STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx */ 00629 /* the calibration is not working in PGA mode */ 00630 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_OPAMODE); 00631 00632 /* Use of standalone mode */ 00633 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE); 00634 00635 /* user trimming values are used for offset calibration */ 00636 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM); 00637 00638 /* Select trimming settings depending on power mode */ 00639 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00640 { 00641 tmp_opamp_reg_trimming = &hopamp->Instance->OTR; 00642 } 00643 else 00644 { 00645 tmp_opamp_reg_trimming = &hopamp->Instance->LPOTR; 00646 } 00647 00648 /* Enable calibration */ 00649 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 00650 00651 /* 1st calibration - N */ 00652 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALSEL); 00653 00654 /* Enable the selected opamp */ 00655 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00656 00657 /* Init trimming counter */ 00658 /* Medium value */ 00659 trimmingvaluen = 16; 00660 delta = 8; 00661 00662 while (delta != 0) 00663 { 00664 /* Set candidate trimming */ 00665 /* OPAMP_POWERMODE_NORMAL */ 00666 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00667 00668 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00669 /* Offset trim time: during calibration, minimum time needed between */ 00670 /* two steps to have 1 mV accuracy */ 00671 HAL_Delay(OPAMP_TRIMMING_DELAY); 00672 00673 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00674 { 00675 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00676 trimmingvaluen -= delta; 00677 } 00678 else 00679 { 00680 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 00681 trimmingvaluen += delta; 00682 } 00683 /* Divide range by 2 to continue dichotomy sweep */ 00684 delta >>= 1; 00685 } 00686 00687 /* Still need to check if right calibration is current value or one step below */ 00688 /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */ 00689 /* Set candidate trimming */ 00690 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00691 00692 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00693 /* Offset trim time: during calibration, minimum time needed between */ 00694 /* two steps to have 1 mV accuracy */ 00695 HAL_Delay(OPAMP_TRIMMING_DELAY); 00696 00697 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) == 0) 00698 { 00699 /* Trimming value is actually one value more */ 00700 trimmingvaluen++; 00701 /* Set right trimming */ 00702 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen); 00703 } 00704 00705 /* 2nd calibration - P */ 00706 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALSEL); 00707 00708 /* Init trimming counter */ 00709 /* Medium value */ 00710 trimmingvaluep = 16; 00711 delta = 8; 00712 00713 while (delta != 0) 00714 { 00715 /* Set candidate trimming */ 00716 /* OPAMP_POWERMODE_NORMAL */ 00717 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00718 00719 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00720 /* Offset trim time: during calibration, minimum time needed between */ 00721 /* two steps to have 1 mV accuracy */ 00722 HAL_Delay(OPAMP_TRIMMING_DELAY); 00723 00724 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00725 { 00726 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00727 trimmingvaluep += delta; 00728 } 00729 else 00730 { 00731 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 00732 trimmingvaluep -= delta; 00733 } 00734 00735 /* Divide range by 2 to continue dichotomy sweep */ 00736 delta >>= 1; 00737 } 00738 00739 /* Still need to check if right calibration is current value or one step below */ 00740 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 00741 /* Set candidate trimming */ 00742 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00743 00744 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00745 /* Offset trim time: during calibration, minimum time needed between */ 00746 /* two steps to have 1 mV accuracy */ 00747 HAL_Delay(OPAMP_TRIMMING_DELAY); 00748 00749 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00750 { 00751 /* Trimming value is actually one value more */ 00752 trimmingvaluep++; 00753 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING)); 00754 } 00755 00756 /* Disable the OPAMP */ 00757 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00758 00759 /* Disable calibration & set normal mode (operating mode) */ 00760 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); 00761 00762 /* Self calibration is successful */ 00763 /* Store calibration(user trimming) results in init structure. */ 00764 00765 /* Set user trimming mode */ 00766 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER; 00767 00768 /* Affect calibration parameters depending on mode normal/low power */ 00769 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER) 00770 { 00771 /* Write calibration result N */ 00772 hopamp->Init.TrimmingValueN = trimmingvaluen; 00773 /* Write calibration result P */ 00774 hopamp->Init.TrimmingValueP = trimmingvaluep; 00775 } 00776 else 00777 { 00778 /* Write calibration result N */ 00779 hopamp->Init.TrimmingValueNLowPower = trimmingvaluen; 00780 /* Write calibration result P */ 00781 hopamp->Init.TrimmingValuePLowPower = trimmingvaluep; 00782 } 00783 00784 /* Restore OPAMP mode after calibration */ 00785 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode); 00786 } 00787 else 00788 { 00789 /* OPAMP can not be calibrated from this mode */ 00790 status = HAL_ERROR; 00791 } 00792 } 00793 return status; 00794 } 00795 00796 /** 00797 * @} 00798 */ 00799 00800 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions 00801 * @brief Peripheral Control functions 00802 * 00803 @verbatim 00804 =============================================================================== 00805 ##### Peripheral Control functions ##### 00806 =============================================================================== 00807 [..] 00808 This subsection provides a set of functions allowing to control the OPAMP data 00809 transfers. 00810 00811 00812 00813 @endverbatim 00814 * @{ 00815 */ 00816 00817 /** 00818 * @brief Lock the selected OPAMP configuration. 00819 * @note On STM32L4, HAL OPAMP lock is software lock only (in 00820 * contrast of hardware lock available on some other STM32 00821 * devices). 00822 * @param hopamp: OPAMP handle 00823 * @retval HAL status 00824 */ 00825 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp) 00826 { 00827 HAL_StatusTypeDef status = HAL_OK; 00828 00829 /* Check the OPAMP handle allocation */ 00830 /* Check if OPAMP locked */ 00831 /* OPAMP can be locked when enabled and running in normal mode */ 00832 /* It is meaningless otherwise */ 00833 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \ 00834 || (hopamp->State == HAL_OPAMP_STATE_READY) \ 00835 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\ 00836 || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) 00837 00838 { 00839 status = HAL_ERROR; 00840 } 00841 00842 else 00843 { 00844 /* Check the parameter */ 00845 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00846 00847 /* OPAMP state changed to locked */ 00848 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED; 00849 } 00850 return status; 00851 } 00852 00853 /** 00854 * @brief Return the OPAMP factory trimming value. 00855 * @note On STM32L4 OPAMP, user can retrieve factory trimming if 00856 * OPAMP has never been set to user trimming before. 00857 * Therefore, this function must be called when OPAMP init 00858 * parameter "UserTrimming" is set to trimming factory, 00859 * and before OPAMP calibration (function 00860 * "HAL_OPAMP_SelfCalibrate()"). 00861 * Otherwise, factory trimming value cannot be retrieved and 00862 * error status is returned. 00863 * @param hopamp : OPAMP handle 00864 * @param trimmingoffset : Trimming offset (P or N) 00865 * This parameter must be a value of @ref OPAMP_FactoryTrimming 00866 * @note Calibration parameter retrieved is corresponding to the mode 00867 * specified in OPAMP init structure (mode normal or low-power). 00868 * To retrieve calibration parameters for both modes, repeat this 00869 * function after OPAMP init structure accordingly updated. 00870 * @retval Trimming value (P or N): range: 0->31 00871 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available 00872 * 00873 */ 00874 00875 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset) 00876 { 00877 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue; 00878 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */ 00879 00880 /* Check the OPAMP handle allocation */ 00881 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */ 00882 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \ 00883 || (hopamp->State == HAL_OPAMP_STATE_BUSY) \ 00884 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\ 00885 || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) 00886 { 00887 return OPAMP_FACTORYTRIMMING_DUMMY; 00888 } 00889 else 00890 { 00891 /* Check the parameter */ 00892 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00893 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset)); 00894 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode)); 00895 00896 /* Check the trimming mode */ 00897 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM) != RESET) 00898 { 00899 /* This function must called when OPAMP init parameter "UserTrimming" */ 00900 /* is set to trimming factory, and before OPAMP calibration (function */ 00901 /* "HAL_OPAMP_SelfCalibrate()"). */ 00902 /* Otherwise, factory trimming value cannot be retrieved and error */ 00903 /* status is returned. */ 00904 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY; 00905 } 00906 else 00907 { 00908 /* Select trimming settings depending on power mode */ 00909 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00910 { 00911 tmp_opamp_reg_trimming = &OPAMP->OTR; 00912 } 00913 else 00914 { 00915 tmp_opamp_reg_trimming = &OPAMP->LPOTR; 00916 } 00917 00918 /* Get factory trimming */ 00919 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P) 00920 { 00921 /* OPAMP_FACTORYTRIMMING_P */ 00922 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING; 00923 } 00924 else 00925 { 00926 /* OPAMP_FACTORYTRIMMING_N */ 00927 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN; 00928 } 00929 } 00930 } 00931 return trimmingvalue; 00932 } 00933 00934 /** 00935 * @} 00936 */ 00937 00938 00939 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions 00940 * @brief Peripheral State functions 00941 * 00942 @verbatim 00943 =============================================================================== 00944 ##### Peripheral State functions ##### 00945 =============================================================================== 00946 [..] 00947 This subsection permits to get in run-time the status of the peripheral. 00948 00949 @endverbatim 00950 * @{ 00951 */ 00952 00953 /** 00954 * @brief Return the OPAMP handle state. 00955 * @param hopamp : OPAMP handle 00956 * @retval HAL state 00957 */ 00958 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp) 00959 { 00960 /* Check the OPAMP handle allocation */ 00961 if(hopamp == NULL) 00962 { 00963 return HAL_OPAMP_STATE_RESET; 00964 } 00965 00966 /* Check the parameter */ 00967 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00968 00969 /* Return OPAMP handle state */ 00970 return hopamp->State; 00971 } 00972 00973 /** 00974 * @} 00975 */ 00976 00977 /** 00978 * @} 00979 */ 00980 00981 /** 00982 * @} 00983 */ 00984 00985 #endif /* HAL_OPAMP_MODULE_ENABLED */ 00986 /** 00987 * @} 00988 */ 00989 00990 /** 00991 * @} 00992 */ 00993 00994 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 10:59:58 by
