TUKS MCU Introductory course / TUKS-COURSE-THERMOMETER

Fork of TUKS-COURSE-TIMER by TUKS MCU Introductory course

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_opamp.c Source File

stm32l4xx_hal_opamp.c

Go to the documentation of this file.
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>&copy; 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****/