mbed library sources
Fork of mbed-src by
Diff: targets/cmsis/TARGET_STM/TARGET_STM32F3/stm32f3xx_hal_opamp.c
- Revision:
- 385:be64abf45658
- Parent:
- 375:3d36234a1087
diff -r ef87175507f1 -r be64abf45658 targets/cmsis/TARGET_STM/TARGET_STM32F3/stm32f3xx_hal_opamp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/cmsis/TARGET_STM/TARGET_STM32F3/stm32f3xx_hal_opamp.c Tue Nov 04 09:45:07 2014 +0000 @@ -0,0 +1,889 @@ +/** + ****************************************************************************** + * @file stm32f3xx_hal_opamp.c + * @author MCD Application Team + * @version V1.1.0 + * @date 12-Sept-2014 + * @brief OPAMP HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the operational amplifiers (OPAMP1,...OPAMP4) + * peripheral: + * + OPAMP Configuration + * + OPAMP calibration + * + * Thanks to + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim +================================================================================ + ##### OPAMP Peripheral Features ##### +================================================================================ + + [..] The device integrates up to 4 operational amplifiers OPAMP1, OPAMP2, + OPAMP3 and OPAMP4: + + (#) The OPAMP(s) provides several exclusive running modes. + (+) Standalone mode + (+) Programmable Gain Amplifier (PGA) mode (Resistor feedback output) + (+) Follower mode + + (#) The OPAMP(s) provide(s) calibration capabilities. + (+) Calibration aims at correcting some offset for running mode. + (+) The OPAMP uses either factory calibration settings OR user defined + calibration (trimming) settings (i.e. trimming mode). + (+) The user defined settings can be figured out using self calibration + handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll + (+) HAL_OPAMP_SelfCalibrate: + (++) Runs automatically the calibration in 2 steps. + (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors). + (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is + appropriate and enough in most cases). + (++) Enables the user trimming mode + (++) Updates the init structure with trimming values with fresh calibration + results. + The user may store the calibration results for larger + (ex monitoring the trimming as a function of temperature + for instance) + (++) for STM32F3 devices having 2 or 4 OPAMPs + HAL_OPAMPEx_SelfCalibrateAll + runs calibration of 2 or 4 OPAMPs in parallel. + + (#) For any running mode, an additional Timer-controlled Mux (multiplexer) + mode can be set on top. + (+) Timer-controlled Mux mode allows Automatic switching between inverting + and non-inverting input. + (+) Hence on top of defaults (primary) inverting and non-inverting inputs, + the user shall select secondary inverting and non inverting inputs. + (+) TIM1 CC6 provides the alternate switching tempo between defaults + (primary) and secondary inputs. + + (#) Running mode: Standalone mode + (+) Gain is set externally (gain depends on external loads). + (+) Follower mode also possible externally by connecting the inverting input to + the output. + + (#) Running mode: Follower mode + (+) No Inverting Input is connected. + + (#) Running mode: Programmable Gain Amplifier (PGA) mode + (Resistor feedback output) + (+) The OPAMP(s) output(s) can be internally connected to resistor feedback + output. + (+) OPAMP gain is either 2, 4, 8 or 16. + + (#) The OPAMPs non inverting input (both default and secondary) can be + selected among the list shown by table below. + + (#) The OPAMPs non inverting input (both default and secondary) can be + selected among the list shown by table below. + + [..] Table 1. OPAMPs inverting/non-inverting inputs for the STM32F3 devices: + + +--------------------------------------------------------------+ + | | | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 | + |-----------------|--------|--------|--------|--------|--------| + | | No conn| X | X | X | X | + | Inverting Input | VM0 | PC5 | PC5 | PB10 | PB10 | + | (1) | VM1 | PA3 | PA5 | PB2 | PD8 | + |-----------------|--------|--------|--------|--------|--------| + | | VP0 | PA1 | PA7 | PB0 | PB13 | + | Non Inverting | VP1 | PA7 | PD14 | PB13 | PD11 | + | Input | VP2 | PA3 | PB0 | PA1 | PA4 | + | | VP3 | PA5 | PB14 | PA5 | PB11 | + +--------------------------------------------------------------+ + (1): NA in follower mode. + + [..] Table 2. OPAMPs outputs for the STM32F3 devices: + + +--------------------------------------------------------------+ + | | | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 | + |-----------------|--------|--------|--------|--------|--------| + | Output | | PA2 | PA6 | PB1 | PB12 | + |-----------------|--------|--------|--------|--------|--------| + + + ##### How to use this driver ##### +================================================================================ + [..] + + *** Calibration *** + ============================================ + To run the opamp calibration self calibration: + + (#) Start calibration using HAL_OPAMP_SelfCalibrate. + Store the calibration results. + + *** Running mode *** + ============================================ + + To use the opamp, perform the following steps: + + (#) Fill in the HAL_OPAMP_MspInit() to + (+) Configure the opamp input AND output in analog mode using + HAL_GPIO_Init() to map the opamp output to the GPIO pin. + + (#) Configure the opamp using HAL_OPAMP_Init() function: + (+) Select the mode + (+) Select the inverting input + (+) Select the non-inverting input + (+) Select if the Timer controlled Mux mode is enabled/disabled + (+) If the Timer controlled Mux mode is enabled, select the secondary inverting input + (+) If the Timer controlled Mux mode is enabled, Select the secondary non-inverting input + (+) If PGA mode is enabled, Select if inverting input is connected. + (+) Select either factory or user defined trimming mode. + (+) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values + (typ. settings returned by HAL_OPAMP_SelfCalibrate function). + + (#) Enable the opamp using HAL_OPAMP_Start() function. + + (#) Disable the opamp using HAL_OPAMP_Stop() function. + + (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function. From then The configuration + can only be modified after HW reset. + + *** Running mode: change of configuration while OPAMP ON *** + ============================================ + To Re-configure OPAMP when OPAMP is ON (change on the fly) + (#) If needed, Fill in the HAL_OPAMP_MspInit() + (+) This is the case for instance if you wish to use new OPAMP I/O + + (#) Configure the opamp using HAL_OPAMP_Init() function: + (+) As in configure case, selects first the parameters you wish to modify. + + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f3xx_hal.h" + +/** @addtogroup STM32F3xx_HAL_Driver + * @{ + */ + +/** @defgroup OPAMP OPAMP HAL module driver + * @brief OPAMP HAL module driver + * @{ + */ + +#ifdef HAL_OPAMP_MODULE_ENABLED + +#if defined(STM32F302xE) || defined(STM32F303xE) || defined(STM32F398xx) || \ + defined(STM32F302xC) || defined(STM32F303xC) || defined(STM32F358xx) || \ + defined(STM32F303x8) || defined(STM32F334x8) || defined(STM32F328xx) || \ + defined(STM32F301x8) || defined(STM32F302x8) || defined(STM32F318xx) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup OPAMP_Private_Define OPAMP Private Define + * @{ + */ +/* CSR register reset value */ +#define OPAMP_CSR_RESET_VALUE ((uint32_t)0x00000000) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions + * @{ + */ + +/** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization/de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the OPAMP according to the specified + * parameters in the OPAMP_InitTypeDef and create the associated handle. + * @note If the selected opamp is locked, initialization can't be performed. + * To unlock the configuration, perform a system reset. + * @param hopamp: OPAMP handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp) + +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OPAMP handle allocation and lock status */ + /* Init not allowed if calibration is ongoing */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \ + || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)) + { + return HAL_ERROR; + } + else + { + + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + /* Set OPAMP parameters */ + assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode)); + assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput)); + if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE) + { + assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput)); + } + + assert_param(IS_OPAMP_TIMERCONTROLLED_MUXMODE(hopamp->Init.TimerControlledMuxmode)); + + if ((hopamp->Init.TimerControlledMuxmode) == OPAMP_TIMERCONTROLLEDMUXMODE_ENABLE) + { + assert_param(IS_OPAMP_SEC_NONINVERTINGINPUT(hopamp->Init.NonInvertingInputSecondary)); + if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE) + { + assert_param(IS_OPAMP_SEC_INVERTINGINPUT(hopamp->Init.InvertingInputSecondary)); + } + } + + if ((hopamp->Init.Mode) == OPAMP_PGA_MODE) + { + assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect)); + assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain)); + } + + assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming)); + if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER) + { + assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP)); + assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN)); + } + + /* Init SYSCFG and the low level hardware to access opamp */ + __SYSCFG_CLK_ENABLE(); + + /* Call MSP init function */ + HAL_OPAMP_MspInit(hopamp); + + /* Set OPAMP parameters */ + /* Set bits according to hopamp->hopamp->Init.Mode value */ + /* Set bits according to hopamp->hopamp->Init.InvertingInput value */ + /* Set bits according to hopamp->hopamp->Init.NonInvertingInput value */ + /* Set bits according to hopamp->hopamp->Init.TimerControlledMuxmode value */ + /* Set bits according to hopamp->hopamp->Init.InvertingInputSecondary value */ + /* Set bits according to hopamp->hopamp->Init.NonInvertingInputSecondary value */ + /* Set bits according to hopamp->hopamp->Init.PgaConnect value */ + /* Set bits according to hopamp->hopamp->Init.PgaGain value */ + /* Set bits according to hopamp->hopamp->Init.UserTrimming value */ + /* Set bits according to hopamp->hopamp->Init.TrimmingValueP value */ + /* Set bits according to hopamp->hopamp->Init.TrimmingValueN value */ + + + /* check if OPAMP_PGA_MODE & in Follower mode */ + /* - InvertingInput */ + /* - InvertingInputSecondary */ + /* are Not Applicable */ + + if ((hopamp->Init.Mode == OPAMP_PGA_MODE) || (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)) + { + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \ + hopamp->Init.Mode | \ + hopamp->Init.NonInvertingInput | \ + hopamp->Init.TimerControlledMuxmode | \ + hopamp->Init.NonInvertingInputSecondary | \ + hopamp->Init.PgaConnect | \ + hopamp->Init.PgaGain | \ + hopamp->Init.UserTrimming | \ + (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \ + (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING)); + } + else /* OPAMP_STANDALONE_MODE */ + { + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \ + hopamp->Init.Mode | \ + hopamp->Init.InvertingInput | \ + hopamp->Init.NonInvertingInput | \ + hopamp->Init.TimerControlledMuxmode | \ + hopamp->Init.InvertingInputSecondary | \ + hopamp->Init.NonInvertingInputSecondary | \ + hopamp->Init.PgaConnect | \ + hopamp->Init.PgaGain | \ + hopamp->Init.UserTrimming | \ + (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \ + (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING)); + } + + /* Update the OPAMP state*/ + if (hopamp->State == HAL_OPAMP_STATE_RESET) + { + /* From RESET state to READY State */ + hopamp->State = HAL_OPAMP_STATE_READY; + } + /* else: remain in READY or BUSY state (no update) */ + + return status; + } +} + + +/** + * @brief DeInitializes the OPAMP peripheral + * @note Deinitialization can't be performed if the OPAMP configuration is locked. + * To unlock the configuration, perform a system reset. + * @param hopamp: OPAMP handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OPAMP handle allocation */ + /* Check if OPAMP locked */ + /* DeInit not allowed if calibration is ongoing */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \ + || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)) + { + status = HAL_ERROR; + } + else + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + /* Set OPAMP_CSR register to reset value */ + WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE); + + /* DeInit the low level hardware: GPIO, CLOCK and NVIC */ + HAL_OPAMP_MspDeInit(hopamp); + + /* Update the OPAMP state*/ + hopamp->State = HAL_OPAMP_STATE_RESET; + } + return status; +} + +/** + * @brief Initializes the OPAMP MSP. + * @param hopamp: OPAMP handle + * @retval None + */ +__weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OPAMP_MspInit could be implemented in the user file + */ + + /* Example */ +} + +/** + * @brief DeInitializes OPAMP MSP. + * @param hopamp: OPAMP handle + * @retval None + */ +__weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OPAMP_MspDeInit could be implemented in the user file + */ + +} + +/** + * @} + */ + + +/** @defgroup OPAMP_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the OPAMP data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Start the opamp + * @param hopamp: OPAMP handle + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OPAMP handle allocation */ + /* Check if OPAMP locked */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) + + { + status = HAL_ERROR; + } + else + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + if(hopamp->State == HAL_OPAMP_STATE_READY) + { + /* Enable the selected opamp */ + SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); + + /* Update the OPAMP state*/ + /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */ + hopamp->State = HAL_OPAMP_STATE_BUSY; + } + else + { + status = HAL_ERROR; + } + + + } + return status; +} + +/** + * @brief Stop the opamp + * @param hopamp: OPAMP handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OPAMP handle allocation */ + /* Check if OPAMP locked */ + /* Check if OPAMP calibration ongoing */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \ + || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)) + { + status = HAL_ERROR; + } + else + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + if(hopamp->State == HAL_OPAMP_STATE_BUSY) + { + /* Disable the selected opamp */ + CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); + + /* Update the OPAMP state*/ + /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/ + hopamp->State = HAL_OPAMP_STATE_READY; + } + else + { + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Run the self calibration of one OPAMP + * @param hopamp handle + * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled + * @retval HAL status + * @note Calibration runs about 25 ms. + */ + +HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp) +{ + + HAL_StatusTypeDef status = HAL_OK; + + uint32_t trimmingvaluen = 0; + uint32_t trimmingvaluep = 0; + uint32_t delta; + + /* Check the OPAMP handle allocation */ + /* Check if OPAMP locked */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) + { + status = HAL_ERROR; + } + else + { + + /* Check if OPAMP in calibration mode and calibration not yet enable */ + if(hopamp->State == HAL_OPAMP_STATE_READY) + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + /* Set Calibration mode */ + /* Non-inverting input connected to calibration reference voltage. */ + SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); + + /* user trimming values are used for offset calibration */ + SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM); + + /* Enable calibration */ + SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); + + /* 1st calibration - N */ + /* Select 90% VREF */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA); + + /* Enable the selected opamp */ + SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); + + /* Init trimming counter */ + /* Medium value */ + trimmingvaluen = 16; + delta = 8; + + while (delta != 0) + { + /* Set candidate trimming */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING); + + /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ + /* Offset trim time: during calibration, minimum time needed between */ + /* two steps to have 1 mV accuracy */ + HAL_Delay(2); + + if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) + { + /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */ + trimmingvaluen += delta; + } + else + { + /* OPAMP_CSR_OUTCAL is LOW try lower trimming */ + trimmingvaluen -= delta; + } + + delta >>= 1; + } + + /* Still need to check if righ calibration is current value or un step below */ + /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING); + + /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ + /* Offset trim time: during calibration, minimum time needed between */ + /* two steps to have 1 mV accuracy */ + HAL_Delay(2); + + if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) + { + /* OPAMP_CSR_OUTCAL is actually one value more */ + trimmingvaluen++; + /* Set right trimming */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING); + } + + /* 2nd calibration - P */ + /* Select 10% VREF */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA); + + /* Init trimming counter */ + /* Medium value */ + trimmingvaluep = 16; + delta = 8; + + while (delta != 0) + { + /* Set candidate trimming */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING); + + /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ + /* Offset trim time: during calibration, minimum time needed between */ + /* two steps to have 1 mV accuracy */ + HAL_Delay(2); + + if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) + { + /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */ + trimmingvaluep += delta; + } + else + { + trimmingvaluep -= delta; + } + + delta >>= 1; + } + + /* Still need to check if righ calibration is current value or un step below */ + /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ + /* Set candidate trimming */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING); + + /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ + /* Offset trim time: during calibration, minimum time needed between */ + /* two steps to have 1 mV accuracy */ + HAL_Delay(2); + + if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) + { + /* OPAMP_CSR_OUTCAL is actually one value more */ + trimmingvaluep++; + /* Set right trimming */ + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING); + } + + /* Disable calibration */ + CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON); + + /* Disable the OPAMP */ + CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); + + /* Set normale operating mode */ + /* Non-inverting input connected to calibration reference voltage. */ + CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP); + + /* Self calibration is successful */ + /* Store calibration(user timming) results in init structure. */ + + /* Write calibration result N */ + hopamp->Init.TrimmingValueN = trimmingvaluen; + + /* Write calibration result P */ + hopamp->Init.TrimmingValueP = trimmingvaluep; + + /* Select user timming mode */ + /* And updated with calibrated settings */ + hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER; + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING); + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING); + } + + else + { + /* OPAMP can not be calibrated from this mode */ + status = HAL_ERROR; + } + } + return status; +} + +/** + * @} + */ + +/** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions + * @brief management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the OPAMP data + transfers. + + + +@endverbatim + * @{ + */ + +/** + * @brief Lock the selected opamp configuration. + * @param hopamp: OPAMP handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OPAMP handle allocation */ + /* Check if OPAMP locked */ + /* OPAMP can be locked when enabled and running in normal mode */ + /* It is meaningless otherwise */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \ + || (hopamp->State == HAL_OPAMP_STATE_READY) \ + || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\ + || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) + + { + status = HAL_ERROR; + } + + else + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + /* Lock OPAMP */ + SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_LOCK); + + /* OPAMP state changed to locked */ + hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED; + } + return status; +} + +/** + * @} + */ + +/** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permit to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the OPAMP state + * @param hopamp : OPAMP handle + * @retval HAL state + */ +HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp) +{ + /* Check the OPAMP handle allocation */ + if(hopamp == HAL_NULL) + { + return HAL_OPAMP_STATE_RESET; + } + + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + + return hopamp->State; +} + +/** + * @brief Return the OPAMP factory trimming value + * @param hopamp : OPAMP handle + * @param trimmingoffset : Trimming offset (P or N) + * @retval Trimming value (P or N): range: 0->31 + * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available + */ + +OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset) +{ + uint32_t oldusertrimming = 0; + OPAMP_TrimmingValueTypeDef oldtrimmingvaluep = 0, oldtrimmingvaluen = 0, trimmingvalue = 0; + + /* Check the OPAMP handle allocation */ + /* Value can be retrieved in HAL_OPAMP_STATE_READY state */ + if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \ + || (hopamp->State == HAL_OPAMP_STATE_BUSY) \ + || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\ + || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)) + { + return OPAMP_FACTORYTRIMMING_DUMMY; + } + else + { + /* Check the parameter */ + assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); + assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset)); + + /* Check the trimming mode */ + if ((READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)) != RESET) + { + /* User trimming is used */ + oldusertrimming = OPAMP_TRIMMING_USER; + /* Store the TrimmingValueP & TrimmingValueN */ + oldtrimmingvaluep = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING; + oldtrimmingvaluen = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING; + } + + /* Set factory timming mode */ + CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_USERTRIM); + + /* Get factory trimming */ + if (trimmingoffset == OPAMP_FACTORYTRIMMING_P) + { + /* Return TrimOffsetP */ + trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING); + } + else + { + /* Return TrimOffsetN */ + trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING); + } + + /* Restore user trimming configuration if it was formerly set */ + /* Check if user trimming was used */ + if (oldusertrimming == OPAMP_TRIMMING_USER) + { + /* Restore user trimming */ + SET_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM); + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, oldtrimmingvaluep<<OPAMP_INPUT_NONINVERTING); + MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, oldtrimmingvaluen<<OPAMP_INPUT_INVERTING); + } + } + return trimmingvalue; +} +/** + * @} + */ + +/** + * @} + */ +#endif /* STM32F302xE || STM32F303xE || STM32F398xx || */ + /* STM32F302xC || STM32F303xC || STM32F358xx || */ + /* STM32F303x8 || STM32F334x8 || STM32F328xx || */ + /* STM32F301x8 || STM32F302x8 || STM32F318xx */ + +#endif /* HAL_OPAMP_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/