Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of TUKS-COURSE-TIMER by
stm32l4xx_hal_opamp_ex.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4xx_hal_opamp_ex.c 00004 * @author MCD Application Team 00005 * @version V1.5.1 00006 * @date 31-May-2016 00007 * @brief Extended OPAMP HAL module driver. 00008 * This file provides firmware functions to manage the following 00009 * functionalities of the operational amplifier(s)(OPAMP1, OPAMP2 etc) 00010 * peripheral: 00011 * + Extended Initialization and de-initialization functions 00012 * + Extended Peripheral Control functions 00013 * 00014 @verbatim 00015 ****************************************************************************** 00016 * @attention 00017 * 00018 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00019 * 00020 * Redistribution and use in source and binary forms, with or without modification, 00021 * are permitted provided that the following conditions are met: 00022 * 1. Redistributions of source code must retain the above copyright notice, 00023 * this list of conditions and the following disclaimer. 00024 * 2. Redistributions in binary form must reproduce the above copyright notice, 00025 * this list of conditions and the following disclaimer in the documentation 00026 * and/or other materials provided with the distribution. 00027 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00028 * may be used to endorse or promote products derived from this software 00029 * without specific prior written permission. 00030 * 00031 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00032 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00033 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00034 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00035 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00036 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00037 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00038 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00039 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00040 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00041 * 00042 ****************************************************************************** 00043 */ 00044 00045 /* Includes ------------------------------------------------------------------*/ 00046 #include "stm32l4xx_hal.h" 00047 00048 /** @addtogroup STM32L4xx_HAL_Driver 00049 * @{ 00050 */ 00051 00052 /** @defgroup OPAMPEx OPAMPEx 00053 * @brief OPAMP Extended HAL module driver 00054 * @{ 00055 */ 00056 00057 #ifdef HAL_OPAMP_MODULE_ENABLED 00058 00059 /* Private typedef -----------------------------------------------------------*/ 00060 /* Private define ------------------------------------------------------------*/ 00061 /* Private macro -------------------------------------------------------------*/ 00062 /* Private variables ---------------------------------------------------------*/ 00063 /* Private function prototypes -----------------------------------------------*/ 00064 /* Exported functions --------------------------------------------------------*/ 00065 00066 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions 00067 * @{ 00068 */ 00069 00070 #if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) 00071 00072 /** @addtogroup OPAMPEx_Exported_Functions_Group1 00073 * @brief Extended operation functions 00074 * 00075 @verbatim 00076 =============================================================================== 00077 ##### Extended IO operation functions ##### 00078 =============================================================================== 00079 [..] 00080 (+) OPAMP Self calibration. 00081 00082 @endverbatim 00083 * @{ 00084 */ 00085 00086 /* 2 OPAMPS available */ 00087 /* 2 OPAMPS can be calibrated in parallel */ 00088 /* Not available on STM32L43x/STM32L44x where only one OPAMP available */ 00089 00090 /** 00091 * @brief Run the self calibration of the 2 OPAMPs in parallel. 00092 * @note Trimming values (PMOS & NMOS) are updated and user trimming is 00093 * enabled is calibration is successful. 00094 * @note Calibration is performed in the mode specified in OPAMP init 00095 * structure (mode normal or low-power). To perform calibration for 00096 * both modes, repeat this function twice after OPAMP init structure 00097 * accordingly updated. 00098 * @note Calibration runs about 10 ms (5 dichotomy steps, repeated for P 00099 * and N transistors: 10 steps with 1 ms for each step). 00100 * @param hopamp1 handle 00101 * @param hopamp2 handle 00102 * @retval HAL status 00103 */ 00104 00105 HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2) 00106 { 00107 HAL_StatusTypeDef status = HAL_OK; 00108 00109 uint32_t trimmingvaluen1 = 0; 00110 uint32_t trimmingvaluep1 = 0; 00111 uint32_t trimmingvaluen2 = 0; 00112 uint32_t trimmingvaluep2 = 0; 00113 00114 /* Selection of register of trimming depending on power mode: OTR or LPOTR */ 00115 __IO uint32_t* tmp_opamp1_reg_trimming; 00116 __IO uint32_t* tmp_opamp2_reg_trimming; 00117 00118 uint32_t delta; 00119 uint32_t opampmode1; 00120 uint32_t opampmode2; 00121 00122 if((hopamp1 == NULL) || (hopamp1->State == HAL_OPAMP_STATE_BUSYLOCKED) || \ 00123 (hopamp2 == NULL) || (hopamp2->State == HAL_OPAMP_STATE_BUSYLOCKED)) 00124 { 00125 status = HAL_ERROR; 00126 } 00127 else 00128 { 00129 /* Check if OPAMP in calibration mode and calibration not yet enable */ 00130 if((hopamp1->State == HAL_OPAMP_STATE_READY) && (hopamp2->State == HAL_OPAMP_STATE_READY)) 00131 { 00132 /* Check the parameter */ 00133 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance)); 00134 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance)); 00135 00136 assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode)); 00137 assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode)); 00138 00139 /* Save OPAMP mode as in */ 00140 /* STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx */ 00141 /* the calibration is not working in PGA mode */ 00142 opampmode1 = READ_BIT(hopamp1->Instance->CSR,OPAMP_CSR_OPAMODE); 00143 opampmode2 = READ_BIT(hopamp2->Instance->CSR,OPAMP_CSR_OPAMODE); 00144 00145 /* Use of standalone mode */ 00146 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE); 00147 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE); 00148 00149 /* user trimming values are used for offset calibration */ 00150 SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM); 00151 SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM); 00152 00153 /* Select trimming settings depending on power mode */ 00154 if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00155 { 00156 tmp_opamp1_reg_trimming = &OPAMP1->OTR; 00157 } 00158 else 00159 { 00160 tmp_opamp1_reg_trimming = &OPAMP1->LPOTR; 00161 } 00162 00163 if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMAL) 00164 { 00165 tmp_opamp2_reg_trimming = &OPAMP2->OTR; 00166 } 00167 else 00168 { 00169 tmp_opamp2_reg_trimming = &OPAMP2->LPOTR; 00170 } 00171 00172 /* Enable calibration */ 00173 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON); 00174 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON); 00175 00176 /* 1st calibration - N */ 00177 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL); 00178 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL); 00179 00180 /* Enable the selected opamp */ 00181 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00182 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00183 00184 /* Init trimming counter */ 00185 /* Medium value */ 00186 trimmingvaluen1 = 16; 00187 trimmingvaluen2 = 16; 00188 delta = 8; 00189 00190 while (delta != 0) 00191 { 00192 /* Set candidate trimming */ 00193 /* OPAMP_POWERMODE_NORMAL */ 00194 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1); 00195 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2); 00196 00197 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00198 /* Offset trim time: during calibration, minimum time needed between */ 00199 /* two steps to have 1 mV accuracy */ 00200 HAL_Delay(OPAMP_TRIMMING_DELAY); 00201 00202 if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00203 { 00204 /* OPAMP_CSR_CALOUT is HIGH try lower trimming */ 00205 trimmingvaluen1 -= delta; 00206 } 00207 else 00208 { 00209 /* OPAMP_CSR_CALOUT is LOW try higher trimming */ 00210 trimmingvaluen1 += delta; 00211 } 00212 00213 if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00214 { 00215 /* OPAMP_CSR_CALOUT is HIGH try lower trimming */ 00216 trimmingvaluen2 -= delta; 00217 } 00218 else 00219 { 00220 /* OPAMP_CSR_CALOUT is LOW try higher trimming */ 00221 trimmingvaluen2 += delta; 00222 } 00223 /* Divide range by 2 to continue dichotomy sweep */ 00224 delta >>= 1; 00225 } 00226 00227 /* Still need to check if right calibration is current value or one step below */ 00228 /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */ 00229 /* Set candidate trimming */ 00230 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1); 00231 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2); 00232 00233 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00234 /* Offset trim time: during calibration, minimum time needed between */ 00235 /* two steps to have 1 mV accuracy */ 00236 HAL_Delay(OPAMP_TRIMMING_DELAY); 00237 00238 if ((READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)) == 0) 00239 { 00240 /* Trimming value is actually one value more */ 00241 trimmingvaluen1++; 00242 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1); 00243 } 00244 00245 if ((READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)) == 0) 00246 { 00247 /* Trimming value is actually one value more */ 00248 trimmingvaluen2++; 00249 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2); 00250 } 00251 00252 /* 2nd calibration - P */ 00253 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL); 00254 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL); 00255 00256 /* Init trimming counter */ 00257 /* Medium value */ 00258 trimmingvaluep1 = 16; 00259 trimmingvaluep2 = 16; 00260 delta = 8; 00261 00262 while (delta != 0) 00263 { 00264 /* Set candidate trimming */ 00265 /* OPAMP_POWERMODE_NORMAL */ 00266 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING)); 00267 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING)); 00268 00269 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00270 /* Offset trim time: during calibration, minimum time needed between */ 00271 /* two steps to have 1 mV accuracy */ 00272 HAL_Delay(OPAMP_TRIMMING_DELAY); 00273 00274 if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00275 { 00276 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00277 trimmingvaluep1 += delta; 00278 } 00279 else 00280 { 00281 /* OPAMP_CSR_CALOUT is HIGH try lower trimming */ 00282 trimmingvaluep1 -= delta; 00283 } 00284 00285 if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00286 { 00287 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */ 00288 trimmingvaluep2 += delta; 00289 } 00290 else 00291 { 00292 /* OPAMP_CSR_CALOUT is LOW try lower trimming */ 00293 trimmingvaluep2 -= delta; 00294 } 00295 /* Divide range by 2 to continue dichotomy sweep */ 00296 delta >>= 1; 00297 } 00298 00299 /* Still need to check if right calibration is current value or one step below */ 00300 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */ 00301 /* Set candidate trimming */ 00302 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING)); 00303 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING)); 00304 00305 /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */ 00306 /* Offset trim time: during calibration, minimum time needed between */ 00307 /* two steps to have 1 mV accuracy */ 00308 HAL_Delay(OPAMP_TRIMMING_DELAY); 00309 00310 if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00311 { 00312 /* Trimming value is actually one value more */ 00313 trimmingvaluep1++; 00314 MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING)); 00315 } 00316 00317 if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != RESET) 00318 { 00319 /* Trimming value is actually one value more */ 00320 trimmingvaluep2++; 00321 MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING)); 00322 } 00323 00324 /* Disable the OPAMPs */ 00325 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00326 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN); 00327 00328 /* Disable calibration & set normal mode (operating mode) */ 00329 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON); 00330 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON); 00331 00332 /* Self calibration is successful */ 00333 /* Store calibration (user trimming) results in init structure. */ 00334 00335 /* Set user trimming mode */ 00336 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER; 00337 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER; 00338 00339 /* Affect calibration parameters depending on mode normal/low power */ 00340 if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER) 00341 { 00342 /* Write calibration result N */ 00343 hopamp1->Init.TrimmingValueN = trimmingvaluen1; 00344 /* Write calibration result P */ 00345 hopamp1->Init.TrimmingValueP = trimmingvaluep1; 00346 } 00347 else 00348 { 00349 /* Write calibration result N */ 00350 hopamp1->Init.TrimmingValueNLowPower = trimmingvaluen1; 00351 /* Write calibration result P */ 00352 hopamp1->Init.TrimmingValuePLowPower = trimmingvaluep1; 00353 } 00354 00355 if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER) 00356 { 00357 /* Write calibration result N */ 00358 hopamp2->Init.TrimmingValueN = trimmingvaluen2; 00359 /* Write calibration result P */ 00360 hopamp2->Init.TrimmingValueP = trimmingvaluep2; 00361 } 00362 else 00363 { 00364 /* Write calibration result N */ 00365 hopamp2->Init.TrimmingValueNLowPower = trimmingvaluen2; 00366 /* Write calibration result P */ 00367 hopamp2->Init.TrimmingValuePLowPower = trimmingvaluep2; 00368 } 00369 00370 /* Update OPAMP state */ 00371 hopamp1->State = HAL_OPAMP_STATE_READY; 00372 hopamp2->State = HAL_OPAMP_STATE_READY; 00373 00374 /* Restore OPAMP mode after calibration */ 00375 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode1); 00376 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode2); 00377 } 00378 else 00379 { 00380 /* At least one OPAMP can not be calibrated */ 00381 status = HAL_ERROR; 00382 } 00383 } 00384 return status; 00385 } 00386 00387 /** 00388 * @} 00389 */ 00390 00391 #endif 00392 00393 /** @defgroup OPAMPEx_Exported_Functions_Group2 Peripheral Control functions 00394 * @brief Peripheral Control functions 00395 * 00396 @verbatim 00397 =============================================================================== 00398 ##### Peripheral Control functions ##### 00399 =============================================================================== 00400 [..] 00401 (+) OPAMP unlock. 00402 00403 @endverbatim 00404 * @{ 00405 */ 00406 00407 /** 00408 * @brief Unlock the selected OPAMP configuration. 00409 * @note This function must be called only when OPAMP is in state "locked". 00410 * @param hopamp: OPAMP handle 00411 * @retval HAL status 00412 */ 00413 HAL_StatusTypeDef HAL_OPAMPEx_Unlock(OPAMP_HandleTypeDef* hopamp) 00414 { 00415 HAL_StatusTypeDef status = HAL_OK; 00416 00417 /* Check the OPAMP handle allocation */ 00418 /* Check if OPAMP locked */ 00419 if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) 00420 || (hopamp->State == HAL_OPAMP_STATE_READY) 00421 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) 00422 || (hopamp->State == HAL_OPAMP_STATE_BUSY)) 00423 00424 { 00425 status = HAL_ERROR; 00426 } 00427 else 00428 { 00429 /* Check the parameter */ 00430 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance)); 00431 00432 /* OPAMP state changed to locked */ 00433 hopamp->State = HAL_OPAMP_STATE_BUSY; 00434 } 00435 return status; 00436 } 00437 00438 /** 00439 * @} 00440 */ 00441 00442 /** 00443 * @} 00444 */ 00445 00446 #endif /* HAL_OPAMP_MODULE_ENABLED */ 00447 /** 00448 * @} 00449 */ 00450 00451 /** 00452 * @} 00453 */ 00454 00455 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 17:38:49 by
