mbed library sources
Fork of mbed-src by
targets/cmsis/TARGET_STM/TARGET_NUCLEO_F334R8/stm32f3xx_hal_opamp.c
- Committer:
- mbed_official
- Date:
- 2014-06-24
- Revision:
- 237:f3da66175598
File content as of revision 237:f3da66175598:
/** ****************************************************************************** * @file stm32f3xx_hal_opamp.c * @author MCD Application Team * @version V1.0.1 * @date 18-June-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_SelfCalibrate2opamp or HAL_OPAMPEx_SelfCalibrate4opamp (+) 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_SelfCalibrate2opamp, HAL_OPAMPEx_SelfCalibrate4opamp 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_COMP_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 youu 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 * @brief OPAMP HAL module driver * @{ */ #ifdef HAL_OPAMP_MODULE_ENABLED #if defined (STM32F303xC) || defined (STM32F358xx) || defined (STM32F302xC) || \ defined (STM32F303x8) || defined (STM32F328xx) || defined (STM32F302x8) || \ defined (STM32F301x8) || defined (STM32F318xx) || defined (STM32F334x8) /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* CSR register reset value */ #define OPAMP_CSR_RESET_VALUE ((uint32_t)0x00000000) /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** @defgroup OPAMP_Private_Functions * @{ */ /** @defgroup HAL_OPAMP_Group1 Initialization/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 == 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) || ((hopamp->Init.Mode) == OPAMP_PGA_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) || ((hopamp->Init.Mode) == OPAMP_PGA_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 { 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 == 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 HAL_OPAMP_Group2 I/O 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 == 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 == 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 == 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); /* 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 HAL_OPAMP_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 == 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 HAL_OPAMP_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 == 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 == 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 /* STM32F303xC STM32F358xx STM32F302xC STM32F303x8 STM32F328xx STM32F302x8 STM32F301x8 STM32F318xx STM32F334x8 */ #endif /* HAL_OPAMP_MODULE_ENABLED */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/