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.
Fork of TUKS-COURSE-TIMER by
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 17:38:49 by
