stm32l4xx_hal_opamp.c 37 KB

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