stm32l1xx_hal_opamp.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. /**
  2. ******************************************************************************
  3. * @file stm32l1xx_hal_opamp.c
  4. * @author MCD Application Team
  5. * @version V1.0.0
  6. * @date 5-September-2014
  7. * @brief OPAMP HAL module driver.
  8. *
  9. * This file provides firmware functions to manage the following
  10. * functionalities of the operational amplifiers (OPAMP1 ,... ,OPAMP3)
  11. * peripheral:
  12. * + OPAMP configuration
  13. * + OPAMP calibration
  14. *
  15. * Thanks to
  16. * + Initialization and de-initialization functions
  17. * + IO operation functions
  18. * + Peripheral Control functions
  19. * + Peripheral State functions
  20. *
  21. @verbatim
  22. ================================================================================
  23. ##### OPAMP Peripheral Features #####
  24. ================================================================================
  25. [..] The device integrates up to 3 operational amplifiers OPAMP1, OPAMP2,
  26. OPAMP3 (OPAMP3 availability depends on device category)
  27. (#) The OPAMP(s) provides several exclusive running modes.
  28. (+) Standalone mode
  29. (+) Follower mode
  30. (#) The OPAMP(s) provide(s) calibration capabilities.
  31. (+) Calibration aims at correcting some offset for running mode.
  32. (+) The OPAMP uses either factory calibration settings OR user defined
  33. calibration (trimming) settings (i.e. trimming mode).
  34. (+) The user defined settings can be figured out using self calibration
  35. handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
  36. (+) HAL_OPAMP_SelfCalibrate:
  37. (++) Runs automatically the calibration in 2 steps: for transistors
  38. differential pair high (PMOS) or low (NMOS)
  39. (++) Enables the user trimming mode
  40. (++) Updates the init structure with trimming values with fresh calibration
  41. results.
  42. The user may store the calibration results for larger
  43. (ex monitoring the trimming as a function of temperature
  44. for instance)
  45. (++) for devices having several OPAMPs, HAL_OPAMPEx_SelfCalibrateAll
  46. runs calibration of all OPAMPs in parallel to save trimming search
  47. wait 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. (+) The OPAMP(s) output(s) are internally connected to inverting input
  55. (#) The OPAMPs inverting input can be selected among the list shown
  56. in table below.
  57. (#) The OPAMPs non inverting input can be selected among the list shown
  58. in table below.
  59. [..] Table 1. OPAMPs inverting/non-inverting inputs for STM32L1 devices:
  60. +--------------------------------------------------------------------------+
  61. | | HAL param | OPAMP1 | OPAMP2 | OPAMP3(4) |
  62. | | name | | | |
  63. |----------------|------------|--------------|--------------|--------------|
  64. | Inverting | VM0 | PA2 | PA7 | PC2 |
  65. | input (1) | VM1 | VINM pin (2) | VINM pin (2) | VINM pin (2) |
  66. |----------------|------------|--------------|--------------|--------------|
  67. | Non Inverting | VP0 | PA1 | PA6 | PC1 |
  68. | input | DAC_CH1 (3)| DAC_CH1 | DAC_CH1 | --- |
  69. | | DAC_CH2 (3)| --- | DAC_CH2 | DAC_CH2 |
  70. +--------------------------------------------------------------------------+
  71. (1): NA in follower mode.
  72. (2): OPAMP input OPAMPx_VINM are dedicated OPAMP pins, their availability
  73. depends on device package.
  74. (3): DAC channels 1 and 2 are connected internally to OPAMP. Nevertheless,
  75. I/O pins connected to DAC can still be used as DAC output (pins PA4
  76. and PA5).
  77. (4): OPAMP3 availability depends on device category.
  78. [..] Table 2. OPAMPs outputs for STM32L1 devices:
  79. +--------------------------------------------------------+
  80. | | OPAMP1 | OPAMP2 | OPAMP3(4) |
  81. |-----------------|------------|------------|------------|
  82. | Output | PA3 | PB0 | PC3 |
  83. +--------------------------------------------------------+
  84. (4) : OPAMP3 availability depends on device category
  85. ##### How to use this driver #####
  86. ================================================================================
  87. [..]
  88. *** Calibration ***
  89. ============================================
  90. To run the opamp calibration self calibration:
  91. (#) Start calibration using HAL_OPAMP_SelfCalibrate.
  92. Store the calibration results.
  93. *** Running mode ***
  94. ============================================
  95. To use the opamp, perform the following steps:
  96. (#) Fill in the HAL_OPAMP_MspInit() to
  97. (+) Enable the OPAMP Peripheral clock using macro "__OPAMP_CLK_ENABLE()"
  98. (++) Configure the opamp input AND output in analog mode using
  99. HAL_GPIO_Init() to map the opamp output to the GPIO pin.
  100. (#) Configure the opamp using HAL_OPAMP_Init() function:
  101. (+) Select the mode
  102. (+) Select the inverting input
  103. (+) Select the non-inverting input
  104. (+) Select either factory or user defined trimming mode.
  105. (+) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values
  106. (typ. settings returned by HAL_OPAMP_SelfCalibrate function).
  107. (#) Enable the opamp using HAL_OPAMP_Start() function.
  108. (#) Disable the opamp using HAL_OPAMP_Stop() function.
  109. (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function.
  110. Caution: On STM32L1, HAL OPAMP lock is software lock only (not
  111. hardware lock as on some other STM32 devices)
  112. (#) If needed, unlock the opamp using HAL_OPAMPEx_Unlock() function.
  113. *** Running mode: change of configuration while OPAMP ON ***
  114. ============================================
  115. To Re-configure OPAMP when OPAMP is ON (change on the fly)
  116. (#) If needed, Fill in the HAL_OPAMP_MspInit()
  117. (+) This is the case for instance if you wish to use new OPAMP I/O
  118. (#) Configure the opamp using HAL_OPAMP_Init() function:
  119. (+) As in configure case, selects first the parameters you wish to modify.
  120. @endverbatim
  121. ******************************************************************************
  122. * @attention
  123. *
  124. * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
  125. *
  126. * Redistribution and use in source and binary forms, with or without modification,
  127. * are permitted provided that the following conditions are met:
  128. * 1. Redistributions of source code must retain the above copyright notice,
  129. * this list of conditions and the following disclaimer.
  130. * 2. Redistributions in binary form must reproduce the above copyright notice,
  131. * this list of conditions and the following disclaimer in the documentation
  132. * and/or other materials provided with the distribution.
  133. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  134. * may be used to endorse or promote products derived from this software
  135. * without specific prior written permission.
  136. *
  137. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  138. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  139. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  140. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  141. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  142. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  143. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  144. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  145. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  146. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  147. *
  148. ******************************************************************************
  149. */
  150. /* Includes ------------------------------------------------------------------*/
  151. #include "stm32l1xx_hal.h"
  152. /** @addtogroup STM32L1xx_HAL_Driver
  153. * @{
  154. */
  155. /** @defgroup OPAMP OPAMP
  156. * @brief OPAMP HAL module driver
  157. * @{
  158. */
  159. #ifdef HAL_OPAMP_MODULE_ENABLED
  160. #if defined (STM32L151xCA) || defined (STM32L151xD) || defined (STM32L152xCA) || defined (STM32L152xD) || defined (STM32L162xCA) || defined (STM32L162xD) || defined (STM32L151xE) || defined (STM32L152xE) || defined (STM32L162xE) || defined (STM32L162xC) || defined (STM32L152xC) || defined (STM32L151xC)
  161. /* Private typedef -----------------------------------------------------------*/
  162. /* Private define ------------------------------------------------------------*/
  163. /* Private macro -------------------------------------------------------------*/
  164. /* Private variables ---------------------------------------------------------*/
  165. /* Private function prototypes -----------------------------------------------*/
  166. /* Private functions ---------------------------------------------------------*/
  167. /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
  168. * @{
  169. */
  170. /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
  171. * @brief Initialization and Configuration functions
  172. *
  173. @verbatim
  174. ===============================================================================
  175. ##### Initialization and de-initialization functions #####
  176. ===============================================================================
  177. [..] This section provides functions allowing to:
  178. @endverbatim
  179. * @{
  180. */
  181. /**
  182. * @brief Initializes the OPAMP according to the specified
  183. * parameters in the OPAMP_InitTypeDef and create the associated handle.
  184. * @note If the selected opamp is locked, initialization can't be performed.
  185. * To unlock the configuration, perform a system reset.
  186. * @param hopamp: OPAMP handle
  187. * @retval HAL status
  188. */
  189. HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef* hopamp)
  190. {
  191. HAL_StatusTypeDef status = HAL_OK;
  192. uint32_t tmp_csr = 0; /* Temporary variable to update register CSR, except bits ANAWSSELx, S7SEL2, OPA_RANGE, OPAxCALOUT */
  193. /* Check the OPAMP handle allocation and lock status */
  194. /* Init not allowed if calibration is ongoing */
  195. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  196. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) )
  197. {
  198. status = HAL_ERROR;
  199. }
  200. else
  201. {
  202. /* Check the parameter */
  203. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  204. /* Set OPAMP parameters */
  205. assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
  206. assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
  207. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  208. assert_param(IS_OPAMP_POWER_SUPPLY_RANGE(hopamp->Init.PowerSupplyRange));
  209. assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
  210. if (hopamp->Init.Mode != OPAMP_FOLLOWER_MODE)
  211. {
  212. assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput));
  213. }
  214. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  215. {
  216. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  217. {
  218. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
  219. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
  220. }
  221. else
  222. {
  223. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePLowPower));
  224. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNLowPower));
  225. }
  226. }
  227. /* Call MSP init function */
  228. HAL_OPAMP_MspInit(hopamp);
  229. /* Set OPAMP parameters */
  230. /* - Set internal switches in function of: */
  231. /* - OPAMP selected mode: standalone or follower. */
  232. /* - Non-inverting input connection */
  233. /* - Inverting input connection */
  234. /* - Set power supply range */
  235. /* - Set power mode and associated calibration parameters */
  236. /* Get OPAMP CSR register into temporary variable */
  237. tmp_csr = OPAMP->CSR;
  238. /* Open all switches on non-inverting input, inverting input and output */
  239. /* feedback. */
  240. CLEAR_BIT(tmp_csr, __OPAMP_CSR_ALL_SWITCHES(hopamp));
  241. /* Set internal switches in function of OPAMP mode selected: standalone */
  242. /* or follower. */
  243. /* If follower mode is selected, feedback switch S3 is closed and */
  244. /* inverting inputs switches are let opened. */
  245. /* If standalone mode is selected, feedback switch S3 is let opened and */
  246. /* the selected inverting inputs switch is closed. */
  247. if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
  248. {
  249. /* Follower mode: Close switches S3 and SanB */
  250. SET_BIT(tmp_csr, __OPAMP_CSR_S3SELX(hopamp));
  251. }
  252. else
  253. {
  254. /* Set internal switches in function of inverting input selected: */
  255. /* Close switch to connect comparator inverting input to the selected */
  256. /* input: dedicated IO pin or alternative IO pin available on some */
  257. /* device packages. */
  258. if (hopamp->Init.InvertingInput == OPAMP_INVERTINGINPUT_VM0)
  259. {
  260. /* Close switch to connect comparator non-inverting input to */
  261. /* dedicated IO pin low-leakage. */
  262. SET_BIT(tmp_csr, __OPAMP_CSR_S4SELX(hopamp));
  263. }
  264. else
  265. {
  266. /* Close switch to connect comparator inverting input to alternative */
  267. /* IO pin available on some device packages. */
  268. SET_BIT(tmp_csr, __OPAMP_CSR_ANAWSELX(hopamp));
  269. }
  270. }
  271. /* Set internal switches in function of non-inverting input selected: */
  272. /* Close switch to connect comparator non-inverting input to the selected */
  273. /* input: dedicated IO pin or DAC channel. */
  274. if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_VP0)
  275. {
  276. /* Close switch to connect comparator non-inverting input to */
  277. /* dedicated IO pin low-leakage. */
  278. SET_BIT(tmp_csr, __OPAMP_CSR_S5SELX(hopamp));
  279. }
  280. else if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_DAC_CH1)
  281. {
  282. /* Particular case for connection to DAC channel 1: */
  283. /* OPAMP_NONINVERTINGINPUT_DAC_CH1 available on OPAMP1 and OPAMP2 only */
  284. /* (OPAMP3 availability depends on device category). */
  285. if ((hopamp->Instance == OPAMP1) || (hopamp->Instance == OPAMP2))
  286. {
  287. /* Close switch to connect comparator non-inverting input to */
  288. /* DAC channel 1. */
  289. SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
  290. }
  291. else
  292. {
  293. /* Set HAL status to error if another OPAMP instance as OPAMP1 or */
  294. /* OPAMP2 is intended to be connected to DAC channel 2. */
  295. status = HAL_ERROR;
  296. }
  297. }
  298. else /* if (hopamp->Init.NonInvertingInput == */
  299. /* OPAMP_NONINVERTINGINPUT_DAC_CH2 ) */
  300. {
  301. /* Particular case for connection to DAC channel 2: */
  302. /* OPAMP_NONINVERTINGINPUT_DAC_CH2 available on OPAMP2 and OPAMP3 only */
  303. /* (OPAMP3 availability depends on device category). */
  304. if (hopamp->Instance == OPAMP2)
  305. {
  306. /* Close switch to connect comparator non-inverting input to */
  307. /* DAC channel 2. */
  308. SET_BIT(tmp_csr, OPAMP_CSR_S7SEL2);
  309. }
  310. /* If OPAMP3 is selected (if available) */
  311. else if (hopamp->Instance != OPAMP1)
  312. {
  313. /* Close switch to connect comparator non-inverting input to */
  314. /* DAC channel 2. */
  315. SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
  316. }
  317. else
  318. {
  319. /* Set HAL status to error if another OPAMP instance as OPAMP2 or */
  320. /* OPAMP3 (if available) is intended to be connected to DAC channel 2.*/
  321. status = HAL_ERROR;
  322. }
  323. }
  324. /* Continue OPAMP configuration if settings of switches are correct */
  325. if (status != HAL_ERROR)
  326. {
  327. /* Set power mode and associated calibration parameters */
  328. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  329. {
  330. /* Set normal mode */
  331. CLEAR_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
  332. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  333. {
  334. /* Set calibration mode (factory or user) and values for */
  335. /* transistors differential pair high (PMOS) and low (NMOS) for */
  336. /* normal mode. */
  337. MODIFY_REG(OPAMP->OTR, OPAMP_OTR_OT_USER |
  338. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK) |
  339. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK) ,
  340. hopamp->Init.UserTrimming |
  341. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueN) |
  342. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValueP) );
  343. }
  344. else
  345. {
  346. /* Set calibration mode to factory */
  347. CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
  348. }
  349. }
  350. else
  351. {
  352. /* Set low power mode */
  353. SET_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
  354. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  355. {
  356. /* Set calibration mode to user trimming */
  357. SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
  358. /* Set values for transistors differential pair high (PMOS) and low */
  359. /* (NMOS) for low power mode. */
  360. MODIFY_REG(OPAMP->LPOTR, __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK) |
  361. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK) ,
  362. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueNLowPower) |
  363. __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValuePLowPower) );
  364. }
  365. else
  366. {
  367. /* Set calibration mode to factory trimming */
  368. CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
  369. }
  370. }
  371. /* Configure the power supply range */
  372. MODIFY_REG(tmp_csr, OPAMP_CSR_AOP_RANGE,
  373. hopamp->Init.PowerSupplyRange);
  374. /* Set OPAMP CSR register from temporary variable */
  375. /* This allows to apply all changes on one time, in case of update on */
  376. /* the fly with OPAMP previously set and running: */
  377. /* - to avoid hazardous transient switches settings (risk of short */
  378. /* circuit) */
  379. /* - to avoid interruption of input signal */
  380. OPAMP->CSR = tmp_csr;
  381. /* Update the OPAMP state */
  382. /* If coming from state reset: Update from state RESET to state READY */
  383. /* else: remain in state READY or BUSY (no update) */
  384. if (hopamp->State == HAL_OPAMP_STATE_RESET)
  385. {
  386. hopamp->State = HAL_OPAMP_STATE_READY;
  387. }
  388. }
  389. }
  390. return status;
  391. }
  392. /**
  393. * @brief DeInitializes the OPAMP peripheral
  394. * @note Deinitialization can't be performed if the OPAMP configuration is locked.
  395. * To unlock the configuration, perform a system reset.
  396. * @param hopamp: OPAMP handle
  397. * @retval HAL status
  398. */
  399. HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef* hopamp)
  400. {
  401. HAL_StatusTypeDef status = HAL_OK;
  402. /* Check the OPAMP handle allocation */
  403. /* Check if OPAMP locked */
  404. /* DeInit not allowed if calibration is ongoing */
  405. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
  406. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
  407. {
  408. status = HAL_ERROR;
  409. }
  410. else
  411. {
  412. /* Check the parameter */
  413. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  414. /* Open all switches on non-inverting input, inverting input and output */
  415. /* feedback. */
  416. CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
  417. /* DeInit the low level hardware */
  418. HAL_OPAMP_MspDeInit(hopamp);
  419. /* Update the OPAMP state*/
  420. hopamp->State = HAL_OPAMP_STATE_RESET;
  421. }
  422. /* Process unlocked */
  423. __HAL_UNLOCK(hopamp);
  424. return status;
  425. }
  426. /**
  427. * @brief Initializes the OPAMP MSP.
  428. * @param hopamp: OPAMP handle
  429. * @retval None
  430. */
  431. __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef* hopamp)
  432. {
  433. /* NOTE : This function Should not be modified, when the callback is needed,
  434. the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
  435. */
  436. }
  437. /**
  438. * @brief DeInitializes OPAMP MSP.
  439. * @param hopamp: OPAMP handle
  440. * @retval None
  441. */
  442. __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef* hopamp)
  443. {
  444. /* NOTE : This function Should not be modified, when the callback is needed,
  445. the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
  446. */
  447. }
  448. /**
  449. * @}
  450. */
  451. /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
  452. * @brief IO operation functions
  453. *
  454. @verbatim
  455. ===============================================================================
  456. ##### IO operation functions #####
  457. ===============================================================================
  458. [..]
  459. This subsection provides a set of functions allowing to manage the OPAMP
  460. start, stop and calibration actions.
  461. @endverbatim
  462. * @{
  463. */
  464. /**
  465. * @brief Start the opamp
  466. * @param hopamp: OPAMP handle
  467. * @retval HAL status
  468. */
  469. HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef* hopamp)
  470. {
  471. HAL_StatusTypeDef status = HAL_OK;
  472. /* Check the OPAMP handle allocation */
  473. /* Check if OPAMP locked */
  474. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  475. {
  476. status = HAL_ERROR;
  477. }
  478. else
  479. {
  480. /* Check the parameter */
  481. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  482. if(hopamp->State == HAL_OPAMP_STATE_READY)
  483. {
  484. /* Enable the selected opamp */
  485. CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
  486. /* Update the OPAMP state */
  487. /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
  488. hopamp->State = HAL_OPAMP_STATE_BUSY;
  489. }
  490. else
  491. {
  492. status = HAL_ERROR;
  493. }
  494. }
  495. return status;
  496. }
  497. /**
  498. * @brief Stop the opamp
  499. * @param hopamp: OPAMP handle
  500. * @retval HAL status
  501. */
  502. HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef* hopamp)
  503. {
  504. HAL_StatusTypeDef status = HAL_OK;
  505. /* Check the OPAMP handle allocation */
  506. /* Check if OPAMP locked */
  507. /* Check if OPAMP calibration ongoing */
  508. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
  509. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
  510. {
  511. status = HAL_ERROR;
  512. }
  513. else
  514. {
  515. /* Check the parameter */
  516. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  517. if(hopamp->State == HAL_OPAMP_STATE_BUSY)
  518. {
  519. /* Disable the selected opamp */
  520. SET_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
  521. /* Update the OPAMP state*/
  522. /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
  523. hopamp->State = HAL_OPAMP_STATE_READY;
  524. }
  525. else
  526. {
  527. status = HAL_ERROR;
  528. }
  529. }
  530. return status;
  531. }
  532. /**
  533. * @brief Run the self calibration of one OPAMP
  534. * @note Trimming values (PMOS & NMOS) are updated and user trimming is
  535. * enabled is calibration is succesful.
  536. * @note Calibration is performed in the mode specified in OPAMP init
  537. * structure (mode normal or low-power). To perform calibration for
  538. * both modes, repeat this function twice after OPAMP init structure
  539. * accordingly updated.
  540. * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
  541. * and N transistors: 10 steps with 1 ms for each step).
  542. * @param hopamp: handle
  543. * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
  544. * @retval HAL status
  545. */
  546. HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef* hopamp)
  547. {
  548. HAL_StatusTypeDef status = HAL_OK;
  549. uint32_t* opamp_trimmingvalue = 0;
  550. uint32_t opamp_trimmingvaluen = 0;
  551. uint32_t opamp_trimmingvaluep = 0;
  552. uint32_t trimming_diff_pair = 0; /* Selection of differential transistors pair high or low */
  553. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  554. uint32_t tmp_opamp_otr_otuser = 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
  555. uint32_t tmp_Opaxcalout_DefaultSate = 0; /* Bit OPAMP_CSR_OPAXCALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
  556. uint32_t tmp_OpaxSwitchesContextBackup = 0;
  557. uint8_t trimming_diff_pair_iteration_count = 0;
  558. uint8_t delta = 0;
  559. /* Check the OPAMP handle allocation */
  560. /* Check if OPAMP locked */
  561. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  562. {
  563. status = HAL_ERROR;
  564. }
  565. else
  566. {
  567. /* Check if OPAMP in calibration mode and calibration not yet enable */
  568. if(hopamp->State == HAL_OPAMP_STATE_READY)
  569. {
  570. /* Check the parameter */
  571. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  572. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  573. /* Update OPAMP state */
  574. hopamp->State = HAL_OPAMP_STATE_CALIBBUSY;
  575. /* Backup of switches configuration to restore it at the end of the */
  576. /* calibration. */
  577. tmp_OpaxSwitchesContextBackup = READ_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
  578. /* Open all switches on non-inverting input, inverting input and output */
  579. /* feedback. */
  580. CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
  581. /* Set calibration mode to user programmed trimming values */
  582. SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
  583. /* Select trimming settings depending on power mode */
  584. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  585. {
  586. tmp_opamp_otr_otuser = OPAMP_OTR_OT_USER;
  587. tmp_opamp_reg_trimming = &OPAMP->OTR;
  588. }
  589. else
  590. {
  591. tmp_opamp_otr_otuser = 0x00000000;
  592. tmp_opamp_reg_trimming = &OPAMP->LPOTR;
  593. }
  594. /* Enable the selected opamp */
  595. CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
  596. /* Perform trimming for both differential transistors pair high and low */
  597. for (trimming_diff_pair_iteration_count = 0; trimming_diff_pair_iteration_count <=1; trimming_diff_pair_iteration_count++)
  598. {
  599. if (trimming_diff_pair_iteration_count == 0)
  600. {
  601. /* Calibration of transistors differential pair high (NMOS) */
  602. trimming_diff_pair = OPAMP_FACTORYTRIMMING_N;
  603. opamp_trimmingvalue = &opamp_trimmingvaluen;
  604. /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
  605. /* is 00000b. Used to detect the bit toggling during trimming. */
  606. tmp_Opaxcalout_DefaultSate = RESET;
  607. /* Enable calibration for N differential pair */
  608. MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_L(hopamp),
  609. __OPAMP_CSR_OPAXCAL_H(hopamp) );
  610. }
  611. else /* (trimming_diff_pair_iteration_count == 1) */
  612. {
  613. /* Calibration of transistors differential pair low (PMOS) */
  614. trimming_diff_pair = OPAMP_FACTORYTRIMMING_P;
  615. opamp_trimmingvalue = &opamp_trimmingvaluep;
  616. /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
  617. /* is 00000b. Used to detect the bit toggling during trimming. */
  618. tmp_Opaxcalout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp);
  619. /* Enable calibration for P differential pair */
  620. MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_H(hopamp),
  621. __OPAMP_CSR_OPAXCAL_L(hopamp) );
  622. }
  623. /* Perform calibration parameter search by dichotomy sweep */
  624. /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
  625. /* initial range, then successive delta sweeps (8, 4, 2, 1). */
  626. /* can extend the search range to +/- 15 units. */
  627. /* - Trimming initial value 15: search range will go from 0 to 30 */
  628. /* (Trimming value 31 is forbidden). */
  629. *opamp_trimmingvalue = 15;
  630. delta = 16;
  631. while (delta != 0)
  632. {
  633. /* Set candidate trimming */
  634. MODIFY_REG(*tmp_opamp_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
  635. __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, *opamp_trimmingvalue) | tmp_opamp_otr_otuser);
  636. /* Offset trimming time: during calibration, minimum time needed */
  637. /* between two steps to have 1 mV accuracy. */
  638. HAL_Delay(OPAMP_TRIMMING_DELAY);
  639. /* Divide range by 2 to continue dichotomy sweep */
  640. delta >>= 1;
  641. /* Set trimming values for next iteration in function of trimming */
  642. /* result toggle (versus initial state). */
  643. if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp)) != tmp_Opaxcalout_DefaultSate)
  644. {
  645. /* If calibration output is has toggled, try lower trimming */
  646. *opamp_trimmingvalue -= delta;
  647. }
  648. else
  649. {
  650. /* If calibration output is has not toggled, try higher trimming */
  651. *opamp_trimmingvalue += delta;
  652. }
  653. }
  654. }
  655. /* Disable calibration for P and N differential pairs */
  656. /* Disable the selected opamp */
  657. CLEAR_BIT (OPAMP->CSR, (__OPAMP_CSR_OPAXCAL_H(hopamp) |
  658. __OPAMP_CSR_OPAXCAL_L(hopamp) |
  659. __OPAMP_CSR_OPAXPD(hopamp)) );
  660. /* Backup of switches configuration to restore it at the end of the */
  661. /* calibration. */
  662. SET_BIT(OPAMP->CSR, tmp_OpaxSwitchesContextBackup);
  663. /* Self calibration is successful */
  664. /* Store calibration (user trimming) results in init structure. */
  665. /* Set user trimming mode */
  666. hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
  667. /* Affect calibration parameters depending on mode normal/low power */
  668. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  669. {
  670. /* Write calibration result N */
  671. hopamp->Init.TrimmingValueN = opamp_trimmingvaluen;
  672. /* Write calibration result P */
  673. hopamp->Init.TrimmingValueP = opamp_trimmingvaluep;
  674. }
  675. else
  676. {
  677. /* Write calibration result N */
  678. hopamp->Init.TrimmingValueNLowPower = opamp_trimmingvaluen;
  679. /* Write calibration result P */
  680. hopamp->Init.TrimmingValuePLowPower = opamp_trimmingvaluep;
  681. }
  682. /* Update OPAMP state */
  683. hopamp->State = HAL_OPAMP_STATE_READY;
  684. }
  685. else
  686. {
  687. /* OPAMP can not be calibrated from this mode */
  688. status = HAL_ERROR;
  689. }
  690. }
  691. return status;
  692. }
  693. /**
  694. * @brief Return the OPAMP factory trimming value
  695. * Caution: On STM32L1 OPAMP, user can retrieve factory trimming if
  696. * OPAMP has never been set to user trimming before.
  697. * Therefore, this fonction must be called when OPAMP init
  698. * parameter "UserTrimming" is set to trimming factory,
  699. * and before OPAMP calibration (function
  700. * "HAL_OPAMP_SelfCalibrate()").
  701. * Otherwise, factory triming value cannot be retrieved and
  702. * error status is returned.
  703. * @param hopamp : OPAMP handle
  704. * @param trimmingoffset : Trimming offset (P or N)
  705. * This parameter must be a value of @ref OPAMP_FactoryTrimming
  706. * @note Calibration parameter retrieved is corresponding to the mode
  707. * specified in OPAMP init structure (mode normal or low-power).
  708. * To retrieve calibration parameters for both modes, repeat this
  709. * function after OPAMP init structure accordingly updated.
  710. * @retval Trimming value (P or N): range: 0->31
  711. * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
  712. * @{
  713. */
  714. OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
  715. {
  716. OPAMP_TrimmingValueTypeDef trimmingvalue;
  717. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  718. /* Check the OPAMP handle allocation */
  719. /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
  720. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET)
  721. || (hopamp->State == HAL_OPAMP_STATE_BUSY)
  722. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
  723. || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  724. {
  725. trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
  726. }
  727. else
  728. {
  729. /* Check the parameter */
  730. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  731. assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
  732. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  733. /* Check the trimming mode */
  734. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  735. {
  736. /* This fonction must called when OPAMP init parameter "UserTrimming" */
  737. /* is set to trimming factory, and before OPAMP calibration (function */
  738. /* "HAL_OPAMP_SelfCalibrate()"). */
  739. /* Otherwise, factory triming value cannot be retrieved and error */
  740. /* status is returned. */
  741. trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
  742. }
  743. else
  744. {
  745. /* Select trimming settings depending on power mode */
  746. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  747. {
  748. tmp_opamp_reg_trimming = &OPAMP->OTR;
  749. }
  750. else
  751. {
  752. tmp_opamp_reg_trimming = &OPAMP->LPOTR;
  753. }
  754. /* Get factory trimming */
  755. trimmingvalue = ((*tmp_opamp_reg_trimming >> __OPAMP_OFFSET_TRIM_BITSPOSITION(hopamp, trimmingoffset)) & OPAMP_TRIM_VALUE_MASK);
  756. }
  757. }
  758. return trimmingvalue;
  759. }
  760. /**
  761. * @}
  762. */
  763. /**
  764. * @}
  765. */
  766. /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
  767. * @brief Peripheral Control functions
  768. *
  769. @verbatim
  770. ===============================================================================
  771. ##### Peripheral Control functions #####
  772. ===============================================================================
  773. [..]
  774. @endverbatim
  775. * @{
  776. */
  777. /**
  778. * @brief Lock the selected opamp configuration.
  779. * Caution: On STM32L1, HAL OPAMP lock is software lock only (not
  780. * hardware lock as on some other STM32 devices)
  781. * @param hopamp: OPAMP handle
  782. * @retval HAL status
  783. */
  784. HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef* hopamp)
  785. {
  786. HAL_StatusTypeDef status = HAL_OK;
  787. /* Check the OPAMP handle allocation */
  788. /* Check if OPAMP locked */
  789. /* OPAMP can be locked when enabled and running in normal mode */
  790. /* It is meaningless otherwise */
  791. if((hopamp == NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
  792. || (hopamp->State == HAL_OPAMP_STATE_READY) \
  793. || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
  794. || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
  795. {
  796. status = HAL_ERROR;
  797. }
  798. else
  799. {
  800. /* Check the parameter */
  801. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  802. /* OPAMP state changed to locked */
  803. hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
  804. }
  805. return status;
  806. }
  807. /**
  808. * @}
  809. */
  810. /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
  811. * @brief Peripheral State functions
  812. *
  813. @verbatim
  814. ===============================================================================
  815. ##### Peripheral State functions #####
  816. ===============================================================================
  817. [..]
  818. This subsection permit to get in run-time the status of the peripheral.
  819. @endverbatim
  820. * @{
  821. */
  822. /**
  823. * @brief Return the OPAMP state
  824. * @param hopamp : OPAMP handle
  825. * @retval HAL state
  826. */
  827. HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef* hopamp)
  828. {
  829. /* Check the OPAMP handle allocation */
  830. if(hopamp == NULL)
  831. {
  832. return HAL_OPAMP_STATE_RESET;
  833. }
  834. /* Check the parameter */
  835. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  836. return hopamp->State;
  837. }
  838. /**
  839. * @}
  840. */
  841. /**
  842. * @}
  843. */
  844. #endif /* STM32L151xCA || STM32L151xD || STM32L152xCA || STM32L152xD || STM32L162xCA || STM32L162xD || STM32L151xE || STM32L152xE || STM32L162xE || STM32L162xC || STM32L152xC || STM32L151xC */
  845. #endif /* HAL_OPAMP_MODULE_ENABLED */
  846. /**
  847. * @}
  848. */
  849. /**
  850. * @}
  851. */
  852. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/