stm32h7xx_hal_opamp.c 36 KB

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