stm32l4xx_hal_opamp_ex.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /**
  2. ******************************************************************************
  3. * @file stm32l4xx_hal_opamp_ex.c
  4. * @author MCD Application Team
  5. * @brief Extended OPAMP HAL module driver.
  6. * This file provides firmware functions to manage the following
  7. * functionalities of the operational amplifier(s) peripheral:
  8. * + Extended Initialization and de-initialization functions
  9. * + Extended Peripheral Control functions
  10. *
  11. @verbatim
  12. ******************************************************************************
  13. * @attention
  14. *
  15. * Copyright (c) 2017 STMicroelectronics.
  16. * All rights reserved.
  17. *
  18. * This software is licensed under terms that can be found in the LICENSE file
  19. * in the root directory of this software component.
  20. * If no LICENSE file comes with this software, it is provided AS-IS.
  21. *
  22. ******************************************************************************
  23. */
  24. /* Includes ------------------------------------------------------------------*/
  25. #include "stm32l4xx_hal.h"
  26. /** @addtogroup STM32L4xx_HAL_Driver
  27. * @{
  28. */
  29. /** @defgroup OPAMPEx OPAMPEx
  30. * @brief OPAMP Extended HAL module driver
  31. * @{
  32. */
  33. #ifdef HAL_OPAMP_MODULE_ENABLED
  34. /* Private typedef -----------------------------------------------------------*/
  35. /* Private define ------------------------------------------------------------*/
  36. /* Private macro -------------------------------------------------------------*/
  37. /* Private variables ---------------------------------------------------------*/
  38. /* Private function prototypes -----------------------------------------------*/
  39. /* Exported functions --------------------------------------------------------*/
  40. /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
  41. * @{
  42. */
  43. #if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
  44. defined (STM32L496xx) || defined (STM32L4A6xx) || \
  45. defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
  46. defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
  47. /** @addtogroup OPAMPEx_Exported_Functions_Group1
  48. * @brief Extended operation functions
  49. *
  50. @verbatim
  51. ===============================================================================
  52. ##### Extended IO operation functions #####
  53. ===============================================================================
  54. [..]
  55. (+) OPAMP Self calibration.
  56. @endverbatim
  57. * @{
  58. */
  59. /* 2 OPAMPS available */
  60. /* 2 OPAMPS can be calibrated in parallel */
  61. /* Not available on STM32L41x/STM32L42x/STM32L43x/STM32L44x where only one OPAMP available */
  62. /**
  63. * @brief Run the self calibration of the 2 OPAMPs in parallel.
  64. * @note Trimming values (PMOS & NMOS) are updated and user trimming is
  65. * enabled is calibration is successful.
  66. * @note Calibration is performed in the mode specified in OPAMP init
  67. * structure (mode normal or low-power). To perform calibration for
  68. * both modes, repeat this function twice after OPAMP init structure
  69. * accordingly updated.
  70. * @note Calibration runs about 10 ms (5 dichotomy steps, repeated for P
  71. * and N transistors: 10 steps with 1 ms for each step).
  72. * @param hopamp1 handle
  73. * @param hopamp2 handle
  74. * @retval HAL status
  75. */
  76. HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2)
  77. {
  78. HAL_StatusTypeDef status = HAL_OK;
  79. uint32_t trimmingvaluen1;
  80. uint32_t trimmingvaluep1;
  81. uint32_t trimmingvaluen2;
  82. uint32_t trimmingvaluep2;
  83. /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  84. __IO uint32_t* tmp_opamp1_reg_trimming;
  85. __IO uint32_t* tmp_opamp2_reg_trimming;
  86. uint32_t delta;
  87. uint32_t opampmode1;
  88. uint32_t opampmode2;
  89. if((hopamp1 == NULL) || (hopamp2 == NULL))
  90. {
  91. status = HAL_ERROR;
  92. }
  93. /* Check if OPAMP in calibration mode and calibration not yet enable */
  94. else if(hopamp1->State != HAL_OPAMP_STATE_READY)
  95. {
  96. status = HAL_ERROR;
  97. }
  98. else if(hopamp2->State != HAL_OPAMP_STATE_READY)
  99. {
  100. status = HAL_ERROR;
  101. }
  102. else
  103. {
  104. /* Check the parameter */
  105. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
  106. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
  107. assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode));
  108. assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode));
  109. /* Save OPAMP mode as in */
  110. /* STM32L471xx STM32L475xx STM32L476xx STM32L485xx STM32L486xx */
  111. /* the calibration is not working in PGA mode */
  112. opampmode1 = READ_BIT(hopamp1->Instance->CSR,OPAMP_CSR_OPAMODE);
  113. opampmode2 = READ_BIT(hopamp2->Instance->CSR,OPAMP_CSR_OPAMODE);
  114. /* Use of standalone mode */
  115. MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE);
  116. MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, OPAMP_STANDALONE_MODE);
  117. /* user trimming values are used for offset calibration */
  118. SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM);
  119. SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM);
  120. /* Select trimming settings depending on power mode */
  121. if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMALPOWER)
  122. {
  123. tmp_opamp1_reg_trimming = &OPAMP1->OTR;
  124. }
  125. else
  126. {
  127. tmp_opamp1_reg_trimming = &OPAMP1->LPOTR;
  128. }
  129. if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMALPOWER)
  130. {
  131. tmp_opamp2_reg_trimming = &OPAMP2->OTR;
  132. }
  133. else
  134. {
  135. tmp_opamp2_reg_trimming = &OPAMP2->LPOTR;
  136. }
  137. /* Enable calibration */
  138. SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
  139. SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
  140. /* 1st calibration - N */
  141. CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL);
  142. CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL);
  143. /* Enable the selected opamp */
  144. SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  145. SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  146. /* Init trimming counter */
  147. /* Medium value */
  148. trimmingvaluen1 = 16U;
  149. trimmingvaluen2 = 16U;
  150. delta = 8U;
  151. while (delta != 0U)
  152. {
  153. /* Set candidate trimming */
  154. /* OPAMP_POWERMODE_NORMALPOWER */
  155. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
  156. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
  157. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  158. /* Offset trim time: during calibration, minimum time needed between */
  159. /* two steps to have 1 mV accuracy */
  160. HAL_Delay(OPAMP_TRIMMING_DELAY);
  161. if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  162. {
  163. /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
  164. trimmingvaluen1 -= delta;
  165. }
  166. else
  167. {
  168. /* OPAMP_CSR_CALOUT is LOW try higher trimming */
  169. trimmingvaluen1 += delta;
  170. }
  171. if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  172. {
  173. /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
  174. trimmingvaluen2 -= delta;
  175. }
  176. else
  177. {
  178. /* OPAMP_CSR_CALOUT is LOW try higher trimming */
  179. trimmingvaluen2 += delta;
  180. }
  181. /* Divide range by 2 to continue dichotomy sweep */
  182. delta >>= 1U;
  183. }
  184. /* Still need to check if right calibration is current value or one step below */
  185. /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */
  186. /* Set candidate trimming */
  187. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
  188. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
  189. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  190. /* Offset trim time: during calibration, minimum time needed between */
  191. /* two steps to have 1 mV accuracy */
  192. HAL_Delay(OPAMP_TRIMMING_DELAY);
  193. if ((READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)) == 0U)
  194. {
  195. /* Trimming value is actually one value more */
  196. trimmingvaluen1++;
  197. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
  198. }
  199. if ((READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)) == 0U)
  200. {
  201. /* Trimming value is actually one value more */
  202. trimmingvaluen2++;
  203. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
  204. }
  205. /* 2nd calibration - P */
  206. SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALSEL);
  207. SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALSEL);
  208. /* Init trimming counter */
  209. /* Medium value */
  210. trimmingvaluep1 = 16U;
  211. trimmingvaluep2 = 16U;
  212. delta = 8U;
  213. while (delta != 0U)
  214. {
  215. /* Set candidate trimming */
  216. /* OPAMP_POWERMODE_NORMALPOWER */
  217. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
  218. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
  219. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  220. /* Offset trim time: during calibration, minimum time needed between */
  221. /* two steps to have 1 mV accuracy */
  222. HAL_Delay(OPAMP_TRIMMING_DELAY);
  223. if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  224. {
  225. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  226. trimmingvaluep1 += delta;
  227. }
  228. else
  229. {
  230. /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
  231. trimmingvaluep1 -= delta;
  232. }
  233. if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  234. {
  235. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  236. trimmingvaluep2 += delta;
  237. }
  238. else
  239. {
  240. /* OPAMP_CSR_CALOUT is LOW try lower trimming */
  241. trimmingvaluep2 -= delta;
  242. }
  243. /* Divide range by 2 to continue dichotomy sweep */
  244. delta >>= 1U;
  245. }
  246. /* Still need to check if right calibration is current value or one step below */
  247. /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
  248. /* Set candidate trimming */
  249. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
  250. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
  251. /* OFFTRIMmax delay 1 ms as per datasheet (electrical characteristics */
  252. /* Offset trim time: during calibration, minimum time needed between */
  253. /* two steps to have 1 mV accuracy */
  254. HAL_Delay(OPAMP_TRIMMING_DELAY);
  255. if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  256. {
  257. /* Trimming value is actually one value more */
  258. trimmingvaluep1++;
  259. MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
  260. }
  261. if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  262. {
  263. /* Trimming value is actually one value more */
  264. trimmingvaluep2++;
  265. MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
  266. }
  267. /* Disable the OPAMPs */
  268. CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  269. CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  270. /* Disable calibration & set normal mode (operating mode) */
  271. CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
  272. CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
  273. /* Self calibration is successful */
  274. /* Store calibration (user trimming) results in init structure. */
  275. /* Set user trimming mode */
  276. hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
  277. hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
  278. /* Affect calibration parameters depending on mode normal/low power */
  279. if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  280. {
  281. /* Write calibration result N */
  282. hopamp1->Init.TrimmingValueN = trimmingvaluen1;
  283. /* Write calibration result P */
  284. hopamp1->Init.TrimmingValueP = trimmingvaluep1;
  285. }
  286. else
  287. {
  288. /* Write calibration result N */
  289. hopamp1->Init.TrimmingValueNLowPower = trimmingvaluen1;
  290. /* Write calibration result P */
  291. hopamp1->Init.TrimmingValuePLowPower = trimmingvaluep1;
  292. }
  293. if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
  294. {
  295. /* Write calibration result N */
  296. hopamp2->Init.TrimmingValueN = trimmingvaluen2;
  297. /* Write calibration result P */
  298. hopamp2->Init.TrimmingValueP = trimmingvaluep2;
  299. }
  300. else
  301. {
  302. /* Write calibration result N */
  303. hopamp2->Init.TrimmingValueNLowPower = trimmingvaluen2;
  304. /* Write calibration result P */
  305. hopamp2->Init.TrimmingValuePLowPower = trimmingvaluep2;
  306. }
  307. /* Update OPAMP state */
  308. hopamp1->State = HAL_OPAMP_STATE_READY;
  309. hopamp2->State = HAL_OPAMP_STATE_READY;
  310. /* Restore OPAMP mode after calibration */
  311. MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode1);
  312. MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_OPAMODE, opampmode2);
  313. }
  314. return status;
  315. }
  316. /**
  317. * @}
  318. */
  319. #endif
  320. /** @defgroup OPAMPEx_Exported_Functions_Group2 Peripheral Control functions
  321. * @brief Peripheral Control functions
  322. *
  323. @verbatim
  324. ===============================================================================
  325. ##### Peripheral Control functions #####
  326. ===============================================================================
  327. [..]
  328. (+) OPAMP unlock.
  329. @endverbatim
  330. * @{
  331. */
  332. /**
  333. * @brief Unlock the selected OPAMP configuration.
  334. * @note This function must be called only when OPAMP is in state "locked".
  335. * @param hopamp OPAMP handle
  336. * @retval HAL status
  337. */
  338. HAL_StatusTypeDef HAL_OPAMPEx_Unlock(OPAMP_HandleTypeDef* hopamp)
  339. {
  340. HAL_StatusTypeDef status = HAL_OK;
  341. /* Check the OPAMP handle allocation */
  342. /* Check if OPAMP locked */
  343. if(hopamp == NULL)
  344. {
  345. status = HAL_ERROR;
  346. }
  347. /* Check the OPAMP handle allocation */
  348. /* Check if OPAMP locked */
  349. else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  350. {
  351. /* Check the parameter */
  352. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  353. /* OPAMP state changed to locked */
  354. hopamp->State = HAL_OPAMP_STATE_BUSY;
  355. }
  356. else
  357. {
  358. status = HAL_ERROR;
  359. }
  360. return status;
  361. }
  362. /**
  363. * @}
  364. */
  365. /**
  366. * @}
  367. */
  368. #endif /* HAL_OPAMP_MODULE_ENABLED */
  369. /**
  370. * @}
  371. */
  372. /**
  373. * @}
  374. */