stm32l4xx_hal_opamp.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. /**
  2. ******************************************************************************
  3. * @file stm32l4xx_hal_opamp.c
  4. * @author MCD Application Team
  5. * @version V1.7.2
  6. * @date 16-June-2017
  7. * @brief OPAMP HAL module driver.
  8. * This file provides firmware functions to manage the following
  9. * functionalities of the operational amplifier(s) peripheral:
  10. * + OPAMP configuration
  11. * + OPAMP calibration
  12. * Thanks to
  13. * + Initialization and de-initialization functions
  14. * + IO operation functions
  15. * + Peripheral Control functions
  16. * + Peripheral State functions
  17. *
  18. @verbatim
  19. ================================================================================
  20. ##### OPAMP Peripheral Features #####
  21. ================================================================================
  22. [..] The device integrates 1 or 2 operational amplifiers OPAMP1 & OPAMP2
  23. (#) The OPAMP(s) provide(s) several exclusive running modes.
  24. (++) 1 OPAMP: STM32L431xx STM32L432xx STM32L433xx STM32L442xx STM32L443xx
  25. (++) 2 OPAMP: STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx
  26. (#) The OPAMP(s) provide(s) several exclusive running modes.
  27. (++) Standalone mode
  28. (++) Programmable Gain Amplifier (PGA) mode (Resistor feedback output)
  29. (++) Follower mode
  30. (#) All OPAMP (same for all OPAMPs) can operate in
  31. (++) Either Low range (VDDA < 2.4V) power supply
  32. (++) Or High range (VDDA > 2.4V) power supply
  33. (#) Each OPAMP(s) can be configured in normal and low power mode.
  34. (#) The OPAMP(s) provide(s) calibration capabilities.
  35. (++) Calibration aims at correcting some offset for running mode.
  36. (++) The OPAMP uses either factory calibration settings OR user defined
  37. calibration (trimming) settings (i.e. trimming mode).
  38. (++) The user defined settings can be figured out using self calibration
  39. handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
  40. (++) HAL_OPAMP_SelfCalibrate:
  41. (+++) Runs automatically the calibration.
  42. (+++) Enables the user trimming mode
  43. (+++) Updates the init structure with trimming values with fresh calibration
  44. results.
  45. The user may store the calibration results for larger
  46. (ex monitoring the trimming as a function of temperature
  47. for instance)
  48. (+++) HAL_OPAMPEx_SelfCalibrateAll
  49. runs calibration of all OPAMPs in parallel to save search time.
  50. (#) Running mode: Standalone mode
  51. (++) Gain is set externally (gain depends on external loads).
  52. (++) Follower mode also possible externally by connecting the inverting input to
  53. the output.
  54. (#) Running mode: Follower mode
  55. (++) No Inverting Input is connected.
  56. (#) Running mode: Programmable Gain Amplifier (PGA) mode
  57. (Resistor feedback output)
  58. (++) The OPAMP(s) output(s) can be internally connected to resistor feedback
  59. output.
  60. (++) OPAMP gain is either 2, 4, 8 or 16.
  61. (#) The OPAMPs inverting input can be selected according to the Reference Manual
  62. "OPAMP function description" chapter.
  63. (#) The OPAMPs non inverting input can be selected according to the Reference Manual
  64. "OPAMP function description" chapter.
  65. ##### How to use this driver #####
  66. ================================================================================
  67. [..]
  68. *** Power supply range ***
  69. ============================================
  70. [..] To run in low power mode:
  71. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  72. (++) Select OPAMP_POWERSUPPLY_LOW (VDDA lower than 2.4V)
  73. (++) Otherwise select OPAMP_POWERSUPPLY_HIGH (VDDA higher than 2.4V)
  74. *** Low / normal power mode ***
  75. ============================================
  76. [..] To run in low power mode:
  77. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  78. (++) Select OPAMP_POWERMODE_LOWPOWER
  79. (++) Otherwise select OPAMP_POWERMODE_NORMAL
  80. *** Calibration ***
  81. ============================================
  82. [..] To run the OPAMP calibration self calibration:
  83. (#) Start calibration using HAL_OPAMP_SelfCalibrate.
  84. Store the calibration results.
  85. *** Running mode ***
  86. ============================================
  87. [..] To use the OPAMP, perform the following steps:
  88. (#) Fill in the HAL_OPAMP_MspInit() to
  89. (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
  90. (++) Configure the OPAMP input AND output in analog mode using
  91. HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
  92. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  93. (++) Select the mode
  94. (++) Select the inverting input
  95. (++) Select the non-inverting input
  96. (++) If PGA mode is enabled, Select if inverting input is connected.
  97. (++) Select either factory or user defined trimming mode.
  98. (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
  99. (typically values set by HAL_OPAMP_SelfCalibrate function).
  100. (#) Enable the OPAMP using HAL_OPAMP_Start() function.
  101. (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
  102. (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
  103. Caution: On STM32L4, HAL OPAMP lock is software lock only (not
  104. hardware lock as on some other STM32 devices)
  105. (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
  106. *** Running mode: change of configuration while OPAMP ON ***
  107. ============================================
  108. [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
  109. (#) If needed, fill in the HAL_OPAMP_MspInit()
  110. (++) This is the case for instance if you wish to use new OPAMP I/O
  111. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  112. (++) As in configure case, select first the parameters you wish to modify.
  113. (#) Change from low power mode to normal power mode (& vice versa) requires
  114. first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
  115. In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
  116. alone.
  117. @endverbatim
  118. ******************************************************************************
  119. Table 1. OPAMPs inverting/non-inverting inputs for the STM32L4 devices:
  120. +------------------------------------------------------------------------|
  121. | | | OPAMP1 | OPAMP2 |
  122. |-----------------|---------|----------------------|---------------------|
  123. | Inverting Input | VM_SEL | | |
  124. | | | IO0-> PA1 | IO0-> PA7 |
  125. | | | LOW LEAKAGE IO (2) | LOW LEAKAGE IO (2) |
  126. | | | Not connected | Not connected |
  127. | (1) | | PGA mode only | PGA mode only |
  128. |-----------------|---------|----------------------|---------------------|
  129. | Non Inverting | VP_SEL | | |
  130. | | | IO0-> PA0 (GPIO) | IO0-> PA6 (GPIO) |
  131. | Input | | DAC1_OUT1 internal | DAC1_OUT2 internal |
  132. +------------------------------------------------------------------------|
  133. (1): NA in follower mode.
  134. (2): Available on some package only (ex. BGA132).
  135. Table 2. OPAMPs outputs for the STM32L4 devices:
  136. +-------------------------------------------------------------------------
  137. | | | OPAMP1 | OPAMP2 |
  138. |-----------------|--------|-----------------------|---------------------|
  139. | Output | VOUT | PA3 | PB0 |
  140. | | | & (1) ADC12_IN if | & (1) ADC12_IN if |
  141. | | | connected internally | connected internally|
  142. |-----------------|--------|-----------------------|---------------------|
  143. (1): ADC1 or ADC2 shall select IN15.
  144. ******************************************************************************
  145. * @attention
  146. *
  147. * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  148. *
  149. * Redistribution and use in source and binary forms, with or without modification,
  150. * are permitted provided that the following conditions are met:
  151. * 1. Redistributions of source code must retain the above copyright notice,
  152. * this list of conditions and the following disclaimer.
  153. * 2. Redistributions in binary form must reproduce the above copyright notice,
  154. * this list of conditions and the following disclaimer in the documentation
  155. * and/or other materials provided with the distribution.
  156. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  157. * may be used to endorse or promote products derived from this software
  158. * without specific prior written permission.
  159. *
  160. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  161. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  162. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  163. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  164. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  165. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  166. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  167. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  168. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  169. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  170. *
  171. ******************************************************************************
  172. */
  173. /* Includes ------------------------------------------------------------------*/
  174. #include "stm32l4xx_hal.h"
  175. /** @addtogroup STM32L4xx_HAL_Driver
  176. * @{
  177. */
  178. /** @defgroup OPAMP OPAMP
  179. * @brief OPAMP module driver
  180. * @{
  181. */
  182. #ifdef HAL_OPAMP_MODULE_ENABLED
  183. /* Private types -------------------------------------------------------------*/
  184. /* Private variables ---------------------------------------------------------*/
  185. /* Private constants ---------------------------------------------------------*/
  186. /** @addtogroup OPAMP_Private_Constants
  187. * @{
  188. */
  189. /* CSR register reset value */
  190. #define OPAMP_CSR_RESET_VALUE ((uint32_t)0x00000000)
  191. #define OPAMP_CSR_RESET_BITS (OPAMP_CSR_OPAMPxEN | OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE \
  192. | OPAMP_CSR_PGGAIN | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
  193. | OPAMP_CSR_CALON | OPAMP_CSR_USERTRIM)
  194. /* CSR Init masks */
  195. #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_PGGAIN \
  196. | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
  197. #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_VPSEL \
  198. | OPAMP_CSR_USERTRIM)
  199. #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPALPM | OPAMP_CSR_OPAMODE| OPAMP_CSR_VPSEL \
  200. | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
  201. /**
  202. * @}
  203. */
  204. /* Private macros ------------------------------------------------------------*/
  205. /* Private functions ---------------------------------------------------------*/
  206. /* Exported functions --------------------------------------------------------*/
  207. /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
  208. * @{
  209. */
  210. /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
  211. * @brief Initialization and Configuration functions
  212. *
  213. @verbatim
  214. ==============================================================================
  215. ##### Initialization and de-initialization functions #####
  216. ==============================================================================
  217. @endverbatim
  218. * @{
  219. */
  220. /**
  221. * @brief Initializes the OPAMP according to the specified
  222. * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
  223. * @note If the selected opamp is locked, initialization can't be performed.
  224. * To unlock the configuration, perform a system reset.
  225. * @param hopamp: OPAMP handle
  226. * @retval HAL status
  227. */
  228. HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
  229. {
  230. HAL_StatusTypeDef status = HAL_OK;
  231. uint32_t updateotrlpotr = 0;
  232. /* Check the OPAMP handle allocation and lock status */
  233. /* Init not allowed if calibration is ongoing */
  234. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  235. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
  236. {
  237. return HAL_ERROR;
  238. }
  239. else
  240. {
  241. /* Check the parameter */
  242. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  243. /* Set OPAMP parameters */
  244. assert_param(IS_OPAMP_POWER_SUPPLY_RANGE(hopamp->Init.PowerSupplyRange));
  245. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  246. assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
  247. assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
  248. if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
  249. {
  250. assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
  251. }
  252. if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
  253. {
  254. assert_param(IS_OPAMP_INVERTING_INPUT_PGA(hopamp->Init.InvertingInput));
  255. }
  256. if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
  257. {
  258. assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
  259. }
  260. assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
  261. if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
  262. {
  263. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  264. {
  265. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
  266. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
  267. }
  268. else
  269. {
  270. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePLowPower));
  271. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNLowPower));
  272. }
  273. }
  274. if(hopamp->State == HAL_OPAMP_STATE_RESET)
  275. {
  276. /* Allocate lock resource and initialize it */
  277. hopamp->Lock = HAL_UNLOCKED;
  278. }
  279. /* Call MSP init function */
  280. HAL_OPAMP_MspInit(hopamp);
  281. /* Set operating mode */
  282. CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
  283. if (hopamp->Init.Mode == OPAMP_PGA_MODE)
  284. {
  285. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \
  286. hopamp->Init.PowerMode | \
  287. hopamp->Init.Mode | \
  288. hopamp->Init.PgaGain | \
  289. hopamp->Init.InvertingInput | \
  290. hopamp->Init.NonInvertingInput | \
  291. hopamp->Init.UserTrimming);
  292. }
  293. if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
  294. {
  295. /* In Follower mode InvertingInput is Not Applicable */
  296. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \
  297. hopamp->Init.PowerMode | \
  298. hopamp->Init.Mode | \
  299. hopamp->Init.NonInvertingInput | \
  300. hopamp->Init.UserTrimming);
  301. }
  302. if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
  303. {
  304. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \
  305. hopamp->Init.PowerMode | \
  306. hopamp->Init.Mode | \
  307. hopamp->Init.InvertingInput | \
  308. hopamp->Init.NonInvertingInput | \
  309. hopamp->Init.UserTrimming);
  310. }
  311. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  312. {
  313. /* Set power mode and associated calibration parameters */
  314. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  315. {
  316. /* OPAMP_POWERMODE_NORMAL */
  317. /* Set calibration mode (factory or user) and values for */
  318. /* transistors differential pair high (PMOS) and low (NMOS) for */
  319. /* normal mode. */
  320. updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \
  321. | (hopamp->Init.TrimmingValueN));
  322. MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
  323. }
  324. else
  325. {
  326. /* OPAMP_POWERMODE_LOWPOWER */
  327. /* transistors differential pair high (PMOS) and low (NMOS) for */
  328. /* low power mode. */
  329. updateotrlpotr = (((hopamp->Init.TrimmingValuePLowPower) << (OPAMP_INPUT_NONINVERTING)) \
  330. | (hopamp->Init.TrimmingValueNLowPower));
  331. MODIFY_REG(hopamp->Instance->LPOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
  332. }
  333. }
  334. /* Configure the power supply range */
  335. /* The OPAMP_CSR_OPARANGE is common configuration for all OPAMPs */
  336. /* bit OPAMP1_CSR_OPARANGE is used for both OPAMPs */
  337. MODIFY_REG(OPAMP1->CSR, OPAMP1_CSR_OPARANGE, hopamp->Init.PowerSupplyRange);
  338. /* Update the OPAMP state*/
  339. if (hopamp->State == HAL_OPAMP_STATE_RESET)
  340. {
  341. /* From RESET state to READY State */
  342. hopamp->State = HAL_OPAMP_STATE_READY;
  343. }
  344. /* else: remain in READY or BUSY state (no update) */
  345. return status;
  346. }
  347. }
  348. /**
  349. * @brief DeInitialize the OPAMP peripheral.
  350. * @note Deinitialization can be performed if the OPAMP configuration is locked.
  351. * (the lock is SW in L4)
  352. * @param hopamp: OPAMP handle
  353. * @retval HAL status
  354. */
  355. HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
  356. {
  357. HAL_StatusTypeDef status = HAL_OK;
  358. /* Check the OPAMP handle allocation */
  359. /* DeInit not allowed if calibration is ongoing */
  360. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
  361. {
  362. status = HAL_ERROR;
  363. }
  364. else
  365. {
  366. /* Check the parameter */
  367. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  368. /* Set OPAMP_CSR register to reset value */
  369. /* Mind that OPAMP1_CSR_OPARANGE of CSR of OPAMP1 remains unchanged (applies to both OPAMPs) */
  370. /* OPAMP shall be disabled first separately */
  371. CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  372. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_BITS, OPAMP_CSR_RESET_VALUE);
  373. /* DeInit the low level hardware: GPIO, CLOCK and NVIC */
  374. HAL_OPAMP_MspDeInit(hopamp);
  375. /* Update the OPAMP state*/
  376. hopamp->State = HAL_OPAMP_STATE_RESET;
  377. /* Process unlocked */
  378. __HAL_UNLOCK(hopamp);
  379. }
  380. return status;
  381. }
  382. /**
  383. * @brief Initialize the OPAMP MSP.
  384. * @param hopamp: OPAMP handle
  385. * @retval None
  386. */
  387. __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
  388. {
  389. /* Prevent unused argument(s) compilation warning */
  390. UNUSED(hopamp);
  391. /* NOTE : This function should not be modified, when the callback is needed,
  392. the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
  393. */
  394. }
  395. /**
  396. * @brief DeInitialize OPAMP MSP.
  397. * @param hopamp: OPAMP handle
  398. * @retval None
  399. */
  400. __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
  401. {
  402. /* Prevent unused argument(s) compilation warning */
  403. UNUSED(hopamp);
  404. /* NOTE : This function should not be modified, when the callback is needed,
  405. the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
  406. */
  407. }
  408. /**
  409. * @}
  410. */
  411. /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
  412. * @brief IO operation functions
  413. *
  414. @verbatim
  415. ===============================================================================
  416. ##### IO operation functions #####
  417. ===============================================================================
  418. [..]
  419. This subsection provides a set of functions allowing to manage the OPAMP
  420. start, stop and calibration actions.
  421. @endverbatim
  422. * @{
  423. */
  424. /**
  425. * @brief Start the OPAMP.
  426. * @param hopamp: OPAMP handle
  427. * @retval HAL status
  428. */
  429. HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
  430. {
  431. HAL_StatusTypeDef status = HAL_OK;
  432. /* Check the OPAMP handle allocation */
  433. /* Check if OPAMP locked */
  434. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  435. {
  436. status = HAL_ERROR;
  437. }
  438. else
  439. {
  440. /* Check the parameter */
  441. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  442. if(hopamp->State == HAL_OPAMP_STATE_READY)
  443. {
  444. /* Enable the selected opamp */
  445. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  446. /* Update the OPAMP state*/
  447. /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
  448. hopamp->State = HAL_OPAMP_STATE_BUSY;
  449. }
  450. else
  451. {
  452. status = HAL_ERROR;
  453. }
  454. }
  455. return status;
  456. }
  457. /**
  458. * @brief Stop the OPAMP.
  459. * @param hopamp: OPAMP handle
  460. * @retval HAL status
  461. */
  462. HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
  463. {
  464. HAL_StatusTypeDef status = HAL_OK;
  465. /* Check the OPAMP handle allocation */
  466. /* Check if OPAMP locked */
  467. /* Check if OPAMP calibration ongoing */
  468. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
  469. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
  470. {
  471. status = HAL_ERROR;
  472. }
  473. else
  474. {
  475. /* Check the parameter */
  476. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  477. if(hopamp->State == HAL_OPAMP_STATE_BUSY)
  478. {
  479. /* Disable the selected opamp */
  480. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  481. /* Update the OPAMP state*/
  482. /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
  483. hopamp->State = HAL_OPAMP_STATE_READY;
  484. }
  485. else
  486. {
  487. status = HAL_ERROR;
  488. }
  489. }
  490. return status;
  491. }
  492. /**
  493. * @brief Run the self calibration of one OPAMP.
  494. * @note Calibration is performed in the mode specified in OPAMP init
  495. * structure (mode normal or low-power). To perform calibration for
  496. * both modes, repeat this function twice after OPAMP init structure
  497. * accordingly updated.
  498. * @note Calibration runs about 10 ms.
  499. * @param hopamp handle
  500. * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
  501. * @retval HAL status
  502. */
  503. HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
  504. {
  505. HAL_StatusTypeDef status = HAL_OK;
  506. uint32_t trimmingvaluen = 0;
  507. uint32_t trimmingvaluep = 0;
  508. uint32_t delta;
  509. uint32_t opampmode;
  510. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  511. /* Check the OPAMP handle allocation */
  512. /* Check if OPAMP locked */
  513. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  514. {
  515. status = HAL_ERROR;
  516. }
  517. else
  518. {
  519. /* Check if OPAMP in calibration mode and calibration not yet enable */
  520. if(hopamp->State == HAL_OPAMP_STATE_READY)
  521. {
  522. /* Check the parameter */
  523. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  524. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  525. /* Save OPAMP mode as in */
  526. /* STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx */
  527. /* the calibration is not working in PGA mode */
  528. opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_OPAMODE);
  529. /* Use of standalone mode */
  530. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE);
  531. /* user trimming values are used for offset calibration */
  532. SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
  533. /* Select trimming settings depending on power mode */
  534. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  535. {
  536. tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
  537. }
  538. else
  539. {
  540. tmp_opamp_reg_trimming = &hopamp->Instance->LPOTR;
  541. }
  542. /* Enable calibration */
  543. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
  544. /* 1st calibration - N */
  545. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALSEL);
  546. /* Enable the selected opamp */
  547. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  548. /* Init trimming counter */
  549. /* Medium value */
  550. trimmingvaluen = 16;
  551. delta = 8;
  552. while (delta != 0)
  553. {
  554. /* Set candidate trimming */
  555. /* OPAMP_POWERMODE_NORMAL */
  556. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  557. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  558. /* Offset trim time: during calibration, minimum time needed between */
  559. /* two steps to have 1 mV accuracy */
  560. HAL_Delay(OPAMP_TRIMMING_DELAY);
  561. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET)
  562. {
  563. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  564. trimmingvaluen -= delta;
  565. }
  566. else
  567. {
  568. /* OPAMP_CSR_CALOUT is LOW try lower trimming */
  569. trimmingvaluen += delta;
  570. }
  571. /* Divide range by 2 to continue dichotomy sweep */
  572. delta >>= 1;
  573. }
  574. /* Still need to check if right calibration is current value or one step below */
  575. /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */
  576. /* Set candidate trimming */
  577. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  578. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  579. /* Offset trim time: during calibration, minimum time needed between */
  580. /* two steps to have 1 mV accuracy */
  581. HAL_Delay(OPAMP_TRIMMING_DELAY);
  582. if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) == 0)
  583. {
  584. /* Trimming value is actually one value more */
  585. trimmingvaluen++;
  586. /* Set right trimming */
  587. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  588. }
  589. /* 2nd calibration - P */
  590. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALSEL);
  591. /* Init trimming counter */
  592. /* Medium value */
  593. trimmingvaluep = 16;
  594. delta = 8;
  595. while (delta != 0)
  596. {
  597. /* Set candidate trimming */
  598. /* OPAMP_POWERMODE_NORMAL */
  599. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  600. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  601. /* Offset trim time: during calibration, minimum time needed between */
  602. /* two steps to have 1 mV accuracy */
  603. HAL_Delay(OPAMP_TRIMMING_DELAY);
  604. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET)
  605. {
  606. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  607. trimmingvaluep += delta;
  608. }
  609. else
  610. {
  611. /* OPAMP_CSR_CALOUT is LOW try lower trimming */
  612. trimmingvaluep -= delta;
  613. }
  614. /* Divide range by 2 to continue dichotomy sweep */
  615. delta >>= 1;
  616. }
  617. /* Still need to check if right calibration is current value or one step below */
  618. /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
  619. /* Set candidate trimming */
  620. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  621. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  622. /* Offset trim time: during calibration, minimum time needed between */
  623. /* two steps to have 1 mV accuracy */
  624. HAL_Delay(OPAMP_TRIMMING_DELAY);
  625. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != RESET)
  626. {
  627. /* Trimming value is actually one value more */
  628. trimmingvaluep++;
  629. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  630. }
  631. /* Disable the OPAMP */
  632. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  633. /* Disable calibration & set normal mode (operating mode) */
  634. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
  635. /* Self calibration is successful */
  636. /* Store calibration(user trimming) results in init structure. */
  637. /* Set user trimming mode */
  638. hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
  639. /* Affect calibration parameters depending on mode normal/low power */
  640. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  641. {
  642. /* Write calibration result N */
  643. hopamp->Init.TrimmingValueN = trimmingvaluen;
  644. /* Write calibration result P */
  645. hopamp->Init.TrimmingValueP = trimmingvaluep;
  646. }
  647. else
  648. {
  649. /* Write calibration result N */
  650. hopamp->Init.TrimmingValueNLowPower = trimmingvaluen;
  651. /* Write calibration result P */
  652. hopamp->Init.TrimmingValuePLowPower = trimmingvaluep;
  653. }
  654. /* Restore OPAMP mode after calibration */
  655. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode);
  656. }
  657. else
  658. {
  659. /* OPAMP can not be calibrated from this mode */
  660. status = HAL_ERROR;
  661. }
  662. }
  663. return status;
  664. }
  665. /**
  666. * @}
  667. */
  668. /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
  669. * @brief Peripheral Control functions
  670. *
  671. @verbatim
  672. ===============================================================================
  673. ##### Peripheral Control functions #####
  674. ===============================================================================
  675. [..]
  676. This subsection provides a set of functions allowing to control the OPAMP data
  677. transfers.
  678. @endverbatim
  679. * @{
  680. */
  681. /**
  682. * @brief Lock the selected OPAMP configuration.
  683. * @note On STM32L4, HAL OPAMP lock is software lock only (in
  684. * contrast of hardware lock available on some other STM32
  685. * devices).
  686. * @param hopamp: OPAMP handle
  687. * @retval HAL status
  688. */
  689. HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
  690. {
  691. HAL_StatusTypeDef status = HAL_OK;
  692. /* Check the OPAMP handle allocation */
  693. /* Check if OPAMP locked */
  694. /* OPAMP can be locked when enabled and running in normal mode */
  695. /* It is meaningless otherwise */
  696. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
  697. || (hopamp->State == HAL_OPAMP_STATE_READY) \
  698. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
  699. || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  700. {
  701. status = HAL_ERROR;
  702. }
  703. else
  704. {
  705. /* Check the parameter */
  706. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  707. /* OPAMP state changed to locked */
  708. hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
  709. }
  710. return status;
  711. }
  712. /**
  713. * @brief Return the OPAMP factory trimming value.
  714. * @note On STM32L4 OPAMP, user can retrieve factory trimming if
  715. * OPAMP has never been set to user trimming before.
  716. * Therefore, this function must be called when OPAMP init
  717. * parameter "UserTrimming" is set to trimming factory,
  718. * and before OPAMP calibration (function
  719. * "HAL_OPAMP_SelfCalibrate()").
  720. * Otherwise, factory trimming value cannot be retrieved and
  721. * error status is returned.
  722. * @param hopamp : OPAMP handle
  723. * @param trimmingoffset : Trimming offset (P or N)
  724. * This parameter must be a value of @ref OPAMP_FactoryTrimming
  725. * @note Calibration parameter retrieved is corresponding to the mode
  726. * specified in OPAMP init structure (mode normal or low-power).
  727. * To retrieve calibration parameters for both modes, repeat this
  728. * function after OPAMP init structure accordingly updated.
  729. * @retval Trimming value (P or N): range: 0->31
  730. * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
  731. *
  732. */
  733. HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
  734. {
  735. HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
  736. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  737. /* Check the OPAMP handle allocation */
  738. /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
  739. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
  740. || (hopamp->State == HAL_OPAMP_STATE_BUSY) \
  741. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
  742. || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  743. {
  744. return OPAMP_FACTORYTRIMMING_DUMMY;
  745. }
  746. else
  747. {
  748. /* Check the parameter */
  749. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  750. assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
  751. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  752. /* Check the trimming mode */
  753. if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM) != RESET)
  754. {
  755. /* This function must called when OPAMP init parameter "UserTrimming" */
  756. /* is set to trimming factory, and before OPAMP calibration (function */
  757. /* "HAL_OPAMP_SelfCalibrate()"). */
  758. /* Otherwise, factory trimming value cannot be retrieved and error */
  759. /* status is returned. */
  760. trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
  761. }
  762. else
  763. {
  764. /* Select trimming settings depending on power mode */
  765. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  766. {
  767. tmp_opamp_reg_trimming = &OPAMP->OTR;
  768. }
  769. else
  770. {
  771. tmp_opamp_reg_trimming = &OPAMP->LPOTR;
  772. }
  773. /* Get factory trimming */
  774. if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
  775. {
  776. /* OPAMP_FACTORYTRIMMING_P */
  777. trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
  778. }
  779. else
  780. {
  781. /* OPAMP_FACTORYTRIMMING_N */
  782. trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
  783. }
  784. }
  785. }
  786. return trimmingvalue;
  787. }
  788. /**
  789. * @}
  790. */
  791. /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
  792. * @brief Peripheral State functions
  793. *
  794. @verbatim
  795. ===============================================================================
  796. ##### Peripheral State functions #####
  797. ===============================================================================
  798. [..]
  799. This subsection permits to get in run-time the status of the peripheral.
  800. @endverbatim
  801. * @{
  802. */
  803. /**
  804. * @brief Return the OPAMP handle state.
  805. * @param hopamp : OPAMP handle
  806. * @retval HAL state
  807. */
  808. HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
  809. {
  810. /* Check the OPAMP handle allocation */
  811. if(hopamp == NULL)
  812. {
  813. return HAL_OPAMP_STATE_RESET;
  814. }
  815. /* Check the parameter */
  816. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  817. /* Return OPAMP handle state */
  818. return hopamp->State;
  819. }
  820. /**
  821. * @}
  822. */
  823. /**
  824. * @}
  825. */
  826. /**
  827. * @}
  828. */
  829. #endif /* HAL_OPAMP_MODULE_ENABLED */
  830. /**
  831. * @}
  832. */
  833. /**
  834. * @}
  835. */
  836. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/