1 /**
2 ******************************************************************************
3 * @file stm32f3xx_hal_opamp.c
4 * @author MCD Application Team
5 * @brief OPAMP HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the operational amplifiers peripheral:
8 * + Initialization/de-initialization functions
9 * + I/O operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2016 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ================================================================================
26 ##### OPAMP Peripheral Features #####
27 ================================================================================
28
29 [..] The device integrates up to 4 operational amplifiers OPAMP1, OPAMP2,
30 OPAMP3 and OPAMP4:
31
32 (#) The OPAMP(s) provides several exclusive running modes.
33 (++) Standalone mode
34 (++) Programmable Gain Amplifier (PGA) mode (Resistor feedback output)
35 (++) Follower mode
36
37 (#) The OPAMP(s) provide(s) calibration capabilities.
38 (++) Calibration aims at correcting some offset for running mode.
39 (++) The OPAMP uses either factory calibration settings OR user defined
40 calibration (trimming) settings (i.e. trimming mode).
41 (++) The user defined settings can be figured out using self calibration
42 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
43 (++) HAL_OPAMP_SelfCalibrate:
44 (++) Runs automatically the calibration in 2 steps.
45 (90U% of VDDA for NMOS transistors, 10U% of VDDA for PMOS transistors).
46 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
47 appropriate and enough in most cases).
48 (++) Enables the user trimming mode
49 (++) Updates the init structure with trimming values with fresh calibration
50 results.
51 The user may store the calibration results for larger
52 (ex monitoring the trimming as a function of temperature
53 for instance)
54 (++) for STM32F3 devices having 2 or 4 OPAMPs
55 HAL_OPAMPEx_SelfCalibrateAll
56 runs calibration of 2 or 4 OPAMPs in parallel.
57
58 (#) For any running mode, an additional Timer-controlled Mux (multiplexer)
59 mode can be set on top.
60 (++) Timer-controlled Mux mode allows Automatic switching between inverting
61 and non-inverting input.
62 (++) Hence on top of defaults (primary) inverting and non-inverting inputs,
63 the user shall select secondary inverting and non inverting inputs.
64 (++) TIM1 CC6 provides the alternate switching tempo between defaults
65 (primary) and secondary inputs.
66
67 (#) Running mode: Standalone mode
68 (++) Gain is set externally (gain depends on external loads).
69 (++) Follower mode also possible externally by connecting the inverting input to
70 the output.
71
72 (#) Running mode: Follower mode
73 (++) No Inverting Input is connected.
74
75 (#) Running mode: Programmable Gain Amplifier (PGA) mode
76 (Resistor feedback output)
77 (++) The OPAMP(s) output(s) can be internally connected to resistor feedback
78 output.
79 (++) OPAMP gain is either 2U, 4U, 8 or 16.
80
81
82 ##### How to use this driver #####
83 ================================================================================
84 [..]
85 *** Calibration ***
86 ============================================
87 [..]
88 To run the opamp calibration self calibration:
89
90 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
91 Store the calibration results.
92
93 *** Running mode ***
94 ============================================
95 [..]
96 To use the opamp, perform the following steps:
97
98 (#) Fill in the HAL_OPAMP_MspInit() to
99 (++) Configure the opamp input AND output in analog mode using
100 HAL_GPIO_Init() to map the opamp output to the GPIO pin.
101
102 (#) Registrate Callbacks
103 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
104 allows the user to configure dynamically the driver callbacks.
105
106 (++) Use Functions HAL_OPAMP_RegisterCallback() to register a user callback,
107 it allows to register following callbacks:
108 (+++) MspInitCallback : OPAMP MspInit.
109 (+++) MspDeInitCallback : OPAMP MspFeInit.
110 This function takes as parameters the HAL peripheral handle, the Callback ID
111 and a pointer to the user callback function.
112
113 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
114 weak (surcharged) function. It allows to reset following callbacks:
115 (+++) MspInitCallback : OPAMP MspInit.
116 (+++) MspDeInitCallback : OPAMP MspdeInit.
117 (+++) All Callbacks
118
119 (#) Configure the opamp using HAL_OPAMP_Init() function:
120 (++) Select the mode
121 (++) Select the inverting input
122 (++) Select the non-inverting input
123 (++) Select if the Timer controlled Mux mode is enabled/disabled
124 (++) If the Timer controlled Mux mode is enabled, select the secondary inverting input
125 (++) If the Timer controlled Mux mode is enabled, Select the secondary non-inverting input
126 (++) If PGA mode is enabled, Select if inverting input is connected.
127 (++) Select either factory or user defined trimming mode.
128 (++) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values
129 (typ. settings returned by HAL_OPAMP_SelfCalibrate function).
130
131 (#) Enable the opamp using HAL_OPAMP_Start() function.
132
133 (#) Disable the opamp using HAL_OPAMP_Stop() function.
134
135 (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function. From then The configuration
136 can be modified
137 (++) After HW reset
138 (++) OR thanks to HAL_OPAMP_MspDeInit called (user defined) from HAL_OPAMP_DeInit.
139
140 *** Running mode: change of configuration while OPAMP ON ***
141 ============================================
142 [..]
143 To Re-configure OPAMP when OPAMP is ON (change on the fly)
144 (#) If needed, Fill in the HAL_OPAMP_MspInit()
145 (++) This is the case for instance if you wish to use new OPAMP I/O
146
147 (#) Configure the opamp using HAL_OPAMP_Init() function:
148 (++) As in configure case, selects first the parameters you wish to modify.
149
150 @endverbatim
151 ******************************************************************************
152 */
153
154 /*
155 Additional Tables:
156 The OPAMPs non inverting input (both default and secondary) can be
157 selected among the list shown by table below.
158
159 The OPAMPs non inverting input (both default and secondary) can be
160 selected among the list shown by table below.
161
162 Table 1. OPAMPs inverting/non-inverting inputs for the STM32F3 devices:
163 +--------------------------------------------------------------+
164 | | | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 |
165 |-----------------|--------|--------|--------|--------|--------|
166 | | No conn| X | X | X | X |
167 | Inverting Input | VM0 | PC5 | PC5 | PB10 | PB10 |
168 | (1) | VM1 | PA3 | PA5 | PB2 | PD8 |
169 |-----------------|--------|--------|--------|--------|--------|
170 | | VP0 | PA1 | PA7 | PB0 | PB13 |
171 | Non Inverting | VP1 | PA7 | PD14 | PB13 | PD11 |
172 | Input | VP2 | PA3 | PB0 | PA1 | PA4 |
173 | | VP3 | PA5 | PB14 | PA5 | PB11 |
174 +--------------------------------------------------------------+
175 (1): NA in follower mode.
176
177 Table 2. OPAMPs outputs for the STM32F3 devices:
178 +--------------------------------------------------------------+
179 | | | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 |
180 |-----------------|--------|--------|--------|--------|--------|
181 | Output | | PA2 | PA6 | PB1 | PB12 |
182 |-----------------|--------|--------|--------|--------|--------|
183
184 */
185
186 /* Includes ------------------------------------------------------------------*/
187 #include "stm32f3xx_hal.h"
188
189 /** @addtogroup STM32F3xx_HAL_Driver
190 * @{
191 */
192
193 #ifdef HAL_OPAMP_MODULE_ENABLED
194
195 #if defined (OPAMP1) || defined (OPAMP2) || defined (OPAMP3) || defined (OPAMP4)
196
197 /** @defgroup OPAMP OPAMP
198 * @brief OPAMP HAL module driver
199 * @{
200 */
201
202 /* Private typedef -----------------------------------------------------------*/
203 /* Private define ------------------------------------------------------------*/
204 /** @defgroup OPAMP_Private_Define OPAMP Private Define
205 * @{
206 */
207 /* CSR register reset value */
208 #define OPAMP_CSR_RESET_VALUE (0x00000000U)
209 /**
210 * @}
211 */
212
213 /* Private macro -------------------------------------------------------------*/
214 /* Private variables ---------------------------------------------------------*/
215 /* Private function prototypes -----------------------------------------------*/
216 /* Exported functions ---------------------------------------------------------*/
217
218 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
219 * @{
220 */
221
222 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
223 * @brief Initialization and Configuration functions
224 *
225 @verbatim
226 ===============================================================================
227 ##### Initialization and de-initialization functions #####
228 ===============================================================================
229 [..] This section provides functions allowing to:
230
231 @endverbatim
232 * @{
233 */
234
235 /**
236 * @brief Initializes the OPAMP according to the specified
237 * parameters in the OPAMP_InitTypeDef and create the associated handle.
238 * @note If the selected opamp is locked, initialization can't be performed.
239 * To unlock the configuration, perform a system reset.
240 * @param hopamp OPAMP handle
241 * @retval HAL status
242 */
HAL_OPAMP_Init(OPAMP_HandleTypeDef * hopamp)243 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
244
245 {
246 HAL_StatusTypeDef status = HAL_OK;
247
248 /* Check the OPAMP handle allocation and lock status */
249 /* Init not allowed if calibration is ongoing */
250 if (hopamp == NULL)
251 {
252 return HAL_ERROR;
253 }
254 else if (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
255 {
256 return HAL_ERROR;
257 }
258 else if (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
259 {
260 return HAL_ERROR;
261 }
262 else
263 {
264
265 /* Check the parameter */
266 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
267
268 /* Set OPAMP parameters */
269 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
270 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
271
272 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
273 if (hopamp->State == HAL_OPAMP_STATE_RESET)
274 {
275 if (hopamp->MspInitCallback == NULL)
276 {
277 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
278 }
279 }
280 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
281
282 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
283 {
284 assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput));
285 }
286
287 assert_param(IS_OPAMP_TIMERCONTROLLED_MUXMODE(hopamp->Init.TimerControlledMuxmode));
288
289 if ((hopamp->Init.TimerControlledMuxmode) == OPAMP_TIMERCONTROLLEDMUXMODE_ENABLE)
290 {
291 assert_param(IS_OPAMP_SEC_NONINVERTINGINPUT(hopamp->Init.NonInvertingInputSecondary));
292 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
293 {
294 assert_param(IS_OPAMP_SEC_INVERTINGINPUT(hopamp->Init.InvertingInputSecondary));
295 }
296 }
297
298 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
299 {
300 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
301 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
302 }
303
304 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
305 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
306 {
307 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
308 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
309 }
310
311 /* Init SYSCFG and the low level hardware to access opamp */
312 __HAL_RCC_SYSCFG_CLK_ENABLE();
313
314 if (hopamp->State == HAL_OPAMP_STATE_RESET)
315 {
316 /* Allocate lock resource and initialize it */
317 hopamp->Lock = HAL_UNLOCKED;
318 }
319
320 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
321 hopamp->MspInitCallback(hopamp);
322 #else
323 /* Call MSP init function */
324 HAL_OPAMP_MspInit(hopamp);
325 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
326
327 /* Set OPAMP parameters */
328 /* Set bits according to hopamp->hopamp->Init.Mode value */
329 /* Set bits according to hopamp->hopamp->Init.InvertingInput value */
330 /* Set bits according to hopamp->hopamp->Init.NonInvertingInput value */
331 /* Set bits according to hopamp->hopamp->Init.TimerControlledMuxmode value */
332 /* Set bits according to hopamp->hopamp->Init.InvertingInputSecondary value */
333 /* Set bits according to hopamp->hopamp->Init.NonInvertingInputSecondary value */
334 /* Set bits according to hopamp->hopamp->Init.PgaConnect value */
335 /* Set bits according to hopamp->hopamp->Init.PgaGain value */
336 /* Set bits according to hopamp->hopamp->Init.UserTrimming value */
337 /* Set bits according to hopamp->hopamp->Init.TrimmingValueP value */
338 /* Set bits according to hopamp->hopamp->Init.TrimmingValueN value */
339
340
341 /* check if OPAMP_PGA_MODE & in Follower mode */
342 /* - InvertingInput */
343 /* - InvertingInputSecondary */
344 /* are Not Applicable */
345
346 if ((hopamp->Init.Mode == OPAMP_PGA_MODE) || (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE))
347 {
348 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \
349 hopamp->Init.Mode | \
350 hopamp->Init.NonInvertingInput | \
351 hopamp->Init.TimerControlledMuxmode | \
352 hopamp->Init.NonInvertingInputSecondary | \
353 hopamp->Init.PgaConnect | \
354 hopamp->Init.PgaGain | \
355 hopamp->Init.UserTrimming | \
356 (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \
357 (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING));
358
359 }
360 else /* OPAMP_STANDALONE_MODE */
361 {
362 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \
363 hopamp->Init.Mode | \
364 hopamp->Init.InvertingInput | \
365 hopamp->Init.NonInvertingInput | \
366 hopamp->Init.TimerControlledMuxmode | \
367 hopamp->Init.InvertingInputSecondary | \
368 hopamp->Init.NonInvertingInputSecondary | \
369 hopamp->Init.PgaConnect | \
370 hopamp->Init.PgaGain | \
371 hopamp->Init.UserTrimming | \
372 (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \
373 (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING));
374 }
375
376 /* Update the OPAMP state*/
377 if (hopamp->State == HAL_OPAMP_STATE_RESET)
378 {
379 /* From RESET state to READY State */
380 hopamp->State = HAL_OPAMP_STATE_READY;
381 }
382 /* else: remain in READY or BUSY state (no update) */
383
384 return status;
385 }
386 }
387
388
389 /**
390 * @brief DeInitializes the OPAMP peripheral
391 * @note Deinitialization can't be performed if the OPAMP configuration is locked.
392 * To unlock the configuration, perform a system reset.
393 * @param hopamp OPAMP handle
394 * @retval HAL status
395 */
HAL_OPAMP_DeInit(OPAMP_HandleTypeDef * hopamp)396 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
397 {
398 HAL_StatusTypeDef status = HAL_OK;
399
400 /* Check the OPAMP handle allocation */
401 /* DeInit not allowed if calibration is ongoing */
402 if (hopamp == NULL)
403 {
404 status = HAL_ERROR;
405 }
406 else if (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
415 /* Set OPAMP_CSR register to reset value */
416 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
417
418 /* DeInit the low level hardware: GPIO, CLOCK and NVIC */
419 /* When OPAMP is locked, unlocking can be achieved thanks to */
420 /* __HAL_RCC_SYSCFG_CLK_DISABLE() call within HAL_OPAMP_MspDeInit */
421 /* Note that __HAL_RCC_SYSCFG_CLK_DISABLE() also disables comparator */
422
423 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
424 if (hopamp->MspDeInitCallback == NULL)
425 {
426 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
427 }
428 /* DeInit the low level hardware */
429 hopamp->MspDeInitCallback(hopamp);
430 #else
431 /* DeInit the low level hardware: GPIO, CLOCK and NVIC */
432 HAL_OPAMP_MspDeInit(hopamp);
433 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
434
435 if (OPAMP_CSR_RESET_VALUE == hopamp->Instance->CSR)
436 {
437 /* Update the OPAMP state */
438 hopamp->State = HAL_OPAMP_STATE_RESET;
439 }
440 else /* RESET STATE */
441 {
442 /* DeInit not complete */
443 /* It can be the case if OPAMP was formerly locked */
444 status = HAL_ERROR;
445
446 /* The OPAMP state is NOT updated */
447 }
448
449 /* Process unlocked */
450 __HAL_UNLOCK(hopamp);
451 }
452
453 return status;
454 }
455
456 /**
457 * @brief Initializes the OPAMP MSP.
458 * @param hopamp OPAMP handle
459 * @retval None
460 */
HAL_OPAMP_MspInit(OPAMP_HandleTypeDef * hopamp)461 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
462 {
463 /* Prevent unused argument(s) compilation warning */
464 UNUSED(hopamp);
465
466 /* NOTE : This function should not be modified, when the callback is needed,
467 the HAL_OPAMP_MspInit could be implemented in the user file
468 */
469
470 /* Example */
471 }
472
473 /**
474 * @brief DeInitializes OPAMP MSP.
475 * @param hopamp OPAMP handle
476 * @retval None
477 */
HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef * hopamp)478 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
479 {
480 /* Prevent unused argument(s) compilation warning */
481 UNUSED(hopamp);
482
483 /* NOTE : This function should not be modified, when the callback is needed,
484 the HAL_OPAMP_MspDeInit could be implemented in the user file
485 */
486
487 }
488
489 /**
490 * @}
491 */
492
493
494 /** @defgroup OPAMP_Exported_Functions_Group2 Input and Output operation functions
495 * @brief Data transfers functions
496 *
497 @verbatim
498 ===============================================================================
499 ##### IO operation functions #####
500 ===============================================================================
501 [..]
502 This subsection provides a set of functions allowing to manage the OPAMP data
503 transfers.
504
505 @endverbatim
506 * @{
507 */
508
509 /**
510 * @brief Start the opamp
511 * @param hopamp OPAMP handle
512 * @retval HAL status
513 */
514
HAL_OPAMP_Start(OPAMP_HandleTypeDef * hopamp)515 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
516 {
517 HAL_StatusTypeDef status = HAL_OK;
518
519 /* Check the OPAMP handle allocation */
520 /* Check if OPAMP locked */
521 if (hopamp == NULL)
522 {
523 status = HAL_ERROR;
524 }
525 else if (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
526
527 {
528 status = HAL_ERROR;
529 }
530 else
531 {
532 /* Check the parameter */
533 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
534
535 if (hopamp->State == HAL_OPAMP_STATE_READY)
536 {
537 /* Enable the selected opamp */
538 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
539
540 /* Update the OPAMP state*/
541 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
542 hopamp->State = HAL_OPAMP_STATE_BUSY;
543 }
544 else
545 {
546 status = HAL_ERROR;
547 }
548 }
549 return status;
550 }
551
552 /**
553 * @brief Stop the opamp
554 * @param hopamp OPAMP handle
555 * @retval HAL status
556 */
HAL_OPAMP_Stop(OPAMP_HandleTypeDef * hopamp)557 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
558 {
559 HAL_StatusTypeDef status = HAL_OK;
560
561 /* Check the OPAMP handle allocation */
562 /* Check if OPAMP locked */
563 /* Check if OPAMP calibration ongoing */
564 if (hopamp == NULL)
565 {
566 status = HAL_ERROR;
567 }
568 else if (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
569 {
570 status = HAL_ERROR;
571 }
572 else if (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
573 {
574 status = HAL_ERROR;
575 }
576 else
577 {
578 /* Check the parameter */
579 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
580
581 if (hopamp->State == HAL_OPAMP_STATE_BUSY)
582 {
583 /* Disable the selected opamp */
584 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
585
586 /* Update the OPAMP state*/
587 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
588 hopamp->State = HAL_OPAMP_STATE_READY;
589 }
590 else
591 {
592 status = HAL_ERROR;
593 }
594 }
595 return status;
596 }
597
598 /**
599 * @brief Run the self calibration of one OPAMP
600 * @param hopamp handle
601 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
602 * @retval HAL status
603 * @note Calibration runs about 25 ms.
604 */
605
HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef * hopamp)606 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
607 {
608
609 HAL_StatusTypeDef status = HAL_OK;
610
611 uint32_t trimmingvaluen;
612 uint32_t trimmingvaluep;
613 uint32_t delta;
614
615 /* Check the OPAMP handle allocation */
616 /* Check if OPAMP locked */
617 if (hopamp == NULL)
618 {
619 status = HAL_ERROR;
620 }
621 else if (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
622 {
623 status = HAL_ERROR;
624 }
625 else
626 {
627
628 /* Check if OPAMP in calibration mode and calibration not yet enable */
629 if (hopamp->State == HAL_OPAMP_STATE_READY)
630 {
631 /* Check the parameter */
632 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
633
634 /* Set Calibration mode */
635 /* Non-inverting input connected to calibration reference voltage. */
636 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
637
638 /* user trimming values are used for offset calibration */
639 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
640
641 /* Enable calibration */
642 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
643
644 /* 1st calibration - N */
645 /* Select 90U% VREF */
646 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
647
648 /* Enable the selected opamp */
649 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
650
651 /* Init trimming counter */
652 /* Medium value */
653 trimmingvaluen = 16U;
654 delta = 8U;
655
656 while (delta != 0U)
657 {
658 /* Set candidate trimming */
659 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen << OPAMP_INPUT_INVERTING);
660
661 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
662 /* Offset trim time: during calibration, minimum time needed between */
663 /* two steps to have 1 mV accuracy */
664 HAL_Delay(2U);
665
666 if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
667 {
668 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
669 trimmingvaluen += delta;
670 }
671 else
672 {
673 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
674 trimmingvaluen -= delta;
675 }
676
677 delta >>= 1U;
678 }
679
680 /* Still need to check if right calibration is current value or un step below */
681 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
682 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen << OPAMP_INPUT_INVERTING);
683
684 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
685 /* Offset trim time: during calibration, minimum time needed between */
686 /* two steps to have 1 mV accuracy */
687 HAL_Delay(2U);
688
689 if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
690 {
691 /* OPAMP_CSR_OUTCAL is actually one value more */
692 trimmingvaluen++;
693 /* Set right trimming */
694 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen << OPAMP_INPUT_INVERTING);
695 }
696
697 /* 2nd calibration - P */
698 /* Select 10U% VREF */
699 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
700
701 /* Init trimming counter */
702 /* Medium value */
703 trimmingvaluep = 16U;
704 delta = 8U;
705
706 while (delta != 0U)
707 {
708 /* Set candidate trimming */
709 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep << OPAMP_INPUT_NONINVERTING);
710
711 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
712 /* Offset trim time: during calibration, minimum time needed between */
713 /* two steps to have 1 mV accuracy */
714 HAL_Delay(2U);
715
716 if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
717 {
718 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
719 trimmingvaluep += delta;
720 }
721 else
722 {
723 trimmingvaluep -= delta;
724 }
725
726 delta >>= 1U;
727 }
728
729 /* Still need to check if right calibration is current value or un step below */
730 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0U */
731 /* Set candidate trimming */
732 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep << OPAMP_INPUT_NONINVERTING);
733
734 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
735 /* Offset trim time: during calibration, minimum time needed between */
736 /* two steps to have 1 mV accuracy */
737 HAL_Delay(2U);
738
739 if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
740 {
741 /* OPAMP_CSR_OUTCAL is actually one value more */
742 trimmingvaluep++;
743 /* Set right trimming */
744 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep << OPAMP_INPUT_NONINVERTING);
745 }
746
747 /* Disable calibration */
748 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
749
750 /* Disable the OPAMP */
751 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
752
753 /* Set operating mode */
754 /* Non-inverting input connected to calibration reference voltage. */
755 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
756
757 /* Self calibration is successful */
758 /* Store calibration(user trimming) results in init structure. */
759
760 /* Write calibration result N */
761 hopamp->Init.TrimmingValueN = trimmingvaluen;
762
763 /* Write calibration result P */
764 hopamp->Init.TrimmingValueP = trimmingvaluep;
765
766 /* Select user trimming mode */
767 /* And updated with calibrated settings */
768 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
769 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep << OPAMP_INPUT_NONINVERTING);
770 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen << OPAMP_INPUT_INVERTING);
771 }
772
773 else
774 {
775 /* OPAMP can not be calibrated from this mode */
776 status = HAL_ERROR;
777 }
778 }
779 return status;
780 }
781
782 /**
783 * @}
784 */
785
786 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
787 * @brief management functions
788 *
789 @verbatim
790 ===============================================================================
791 ##### Peripheral Control functions #####
792 ===============================================================================
793 [..]
794 This subsection provides a set of functions allowing to control the OPAMP data
795 transfers.
796
797
798
799 @endverbatim
800 * @{
801 */
802
803 /**
804 * @brief Lock the selected opamp configuration.
805 * @param hopamp OPAMP handle
806 * @retval HAL status
807 */
HAL_OPAMP_Lock(OPAMP_HandleTypeDef * hopamp)808 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
809 {
810 HAL_StatusTypeDef status = HAL_OK;
811
812 /* Check the OPAMP handle allocation */
813 /* Check if OPAMP locked */
814 /* OPAMP can be locked when enabled and running in normal mode */
815 /* It is meaningless otherwise */
816 if (hopamp == NULL)
817 {
818 status = HAL_ERROR;
819 }
820 else if (hopamp->State == HAL_OPAMP_STATE_BUSY)
821 {
822 /* Check the parameter */
823 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
824
825 /* Lock OPAMP */
826 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_LOCK);
827
828 /* OPAMP state changed to locked */
829 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
830 }
831 else
832 {
833 status = HAL_ERROR;
834 }
835 return status;
836 }
837
838 /**
839 * @}
840 */
841
842 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
843 * @brief Peripheral State functions
844 *
845 @verbatim
846 ===============================================================================
847 ##### Peripheral State functions #####
848 ===============================================================================
849 [..]
850 This subsection permit to get in run-time the status of the peripheral
851 and the data flow.
852
853 @endverbatim
854 * @{
855 */
856
857 /**
858 * @brief Return the OPAMP state
859 * @param hopamp OPAMP handle
860 * @retval HAL state
861 */
HAL_OPAMP_GetState(OPAMP_HandleTypeDef * hopamp)862 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
863 {
864 /* Check the OPAMP handle allocation */
865 if (hopamp == NULL)
866 {
867 return HAL_OPAMP_STATE_RESET;
868 }
869
870 /* Check the parameter */
871 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
872
873 return hopamp->State;
874 }
875
876 /**
877 * @brief Return the OPAMP factory trimming value
878 * @param hopamp OPAMP handle
879 * @param trimmingoffset Trimming offset (P or N)
880 * @retval Trimming value (P or N): range: 0->31
881 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
882 */
883
HAL_OPAMP_GetTrimOffset(OPAMP_HandleTypeDef * hopamp,uint32_t trimmingoffset)884 OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset(OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
885 {
886 uint32_t oldusertrimming = 0U;
887 OPAMP_TrimmingValueTypeDef oldtrimmingvaluep = 0U, oldtrimmingvaluen = 0U, trimmingvalue = 0U;
888
889 /* Check the OPAMP handle allocation */
890 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
891 if (hopamp == NULL)
892 {
893 return OPAMP_FACTORYTRIMMING_DUMMY;
894 }
895
896 /* Check the OPAMP handle allocation */
897 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
898 if (hopamp->State == HAL_OPAMP_STATE_READY)
899 {
900 /* Check the parameter */
901 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
902 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
903
904 /* Check the trimming mode */
905 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM)) != RESET)
906 {
907 /* User trimming is used */
908 oldusertrimming = OPAMP_TRIMMING_USER;
909 /* Store the TrimmingValueP & TrimmingValueN */
910 oldtrimmingvaluep = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
911 oldtrimmingvaluen = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING;
912 }
913
914 /* Set factory trimming mode */
915 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
916
917 /* Get factory trimming */
918 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
919 {
920 /* Return TrimOffsetP */
921 trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING);
922 }
923 else
924 {
925 /* Return TrimOffsetN */
926 trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING);
927 }
928
929 /* Restore user trimming configuration if it was formerly set */
930 /* Check if user trimming was used */
931 if (oldusertrimming == OPAMP_TRIMMING_USER)
932 {
933 /* Restore user trimming */
934 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
935 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, oldtrimmingvaluep << OPAMP_INPUT_NONINVERTING);
936 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, oldtrimmingvaluen << OPAMP_INPUT_INVERTING);
937 }
938 }
939 else
940 {
941 return OPAMP_FACTORYTRIMMING_DUMMY;
942 }
943 return trimmingvalue;
944 }
945 /**
946 * @}
947 */
948
949 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
950 /**
951 * @brief Register a User OPAMP Callback
952 * To be used instead of the weak (surcharged) predefined callback
953 * @param hopamp : OPAMP handle
954 * @param CallbackId : ID of the callback to be registered
955 * This parameter can be one of the following values:
956 * @arg @ref HAL_OPAMP_MSP_INIT_CB_ID OPAMP MspInit callback ID
957 * @arg @ref HAL_OPAMP_MSP_DEINIT_CB_ID OPAMP MspDeInit callback ID
958 * @param pCallback : pointer to the Callback function
959 * @retval status
960 */
HAL_OPAMP_RegisterCallback(OPAMP_HandleTypeDef * hopamp,HAL_OPAMP_CallbackIDTypeDef CallbackId,pOPAMP_CallbackTypeDef pCallback)961 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback(OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
962 {
963 HAL_StatusTypeDef status = HAL_OK;
964
965 if (pCallback == NULL)
966 {
967 return HAL_ERROR;
968 }
969
970 /* Process locked */
971 __HAL_LOCK(hopamp);
972
973 if (hopamp->State == HAL_OPAMP_STATE_READY)
974 {
975 switch (CallbackId)
976 {
977 case HAL_OPAMP_MSP_INIT_CB_ID :
978 hopamp->MspInitCallback = pCallback;
979 break;
980 case HAL_OPAMP_MSP_DEINIT_CB_ID :
981 hopamp->MspDeInitCallback = pCallback;
982 break;
983 default :
984 /* update return status */
985 status = HAL_ERROR;
986 break;
987 }
988 }
989 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
990 {
991 switch (CallbackId)
992 {
993 case HAL_OPAMP_MSP_INIT_CB_ID :
994 hopamp->MspInitCallback = pCallback;
995 break;
996 case HAL_OPAMP_MSP_DEINIT_CB_ID :
997 hopamp->MspDeInitCallback = pCallback;
998 break;
999 default :
1000 /* update return status */
1001 status = HAL_ERROR;
1002 break;
1003 }
1004 }
1005 else
1006 {
1007 /* update return status */
1008 status = HAL_ERROR;
1009 }
1010
1011 /* Release Lock */
1012 __HAL_UNLOCK(hopamp);
1013 return status;
1014 }
1015
1016 /**
1017 * @brief Unregister a User OPAMP Callback
1018 * OPAMP Callback is redirected to the weak (surcharged) predefined callback
1019 * @param hopamp : OPAMP handle
1020 * @param CallbackId : ID of the callback to be unregistered
1021 * This parameter can be one of the following values:
1022 * @arg @ref HAL_OPAMP_MSP_INIT_CB_ID OPAMP MSP Init Callback ID
1023 * @arg @ref HAL_OPAMP_MSP_DEINIT_CB_ID OPAMP MSP DeInit Callback ID
1024 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
1025 * @retval status
1026 */
1027
HAL_OPAMP_UnRegisterCallback(OPAMP_HandleTypeDef * hopamp,HAL_OPAMP_CallbackIDTypeDef CallbackId)1028 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback(OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
1029 {
1030 HAL_StatusTypeDef status = HAL_OK;
1031
1032 /* Process locked */
1033 __HAL_LOCK(hopamp);
1034
1035 if (hopamp->State == HAL_OPAMP_STATE_READY)
1036 {
1037 switch (CallbackId)
1038 {
1039 case HAL_OPAMP_MSP_INIT_CB_ID :
1040 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1041 break;
1042 case HAL_OPAMP_MSP_DEINIT_CB_ID :
1043 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1044 break;
1045 case HAL_OPAMP_ALL_CB_ID :
1046 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1047 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1048 break;
1049 default :
1050 /* update return status */
1051 status = HAL_ERROR;
1052 break;
1053 }
1054 }
1055 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1056 {
1057 switch (CallbackId)
1058 {
1059 case HAL_OPAMP_MSP_INIT_CB_ID :
1060 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1061 break;
1062 case HAL_OPAMP_MSP_DEINIT_CB_ID :
1063 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1064 break;
1065 default :
1066 /* update return status */
1067 status = HAL_ERROR;
1068 break;
1069 }
1070 }
1071 else
1072 {
1073 /* update return status */
1074 status = HAL_ERROR;
1075 }
1076
1077 /* Release Lock */
1078 __HAL_UNLOCK(hopamp);
1079 return status;
1080 }
1081
1082 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1083
1084 /**
1085 * @}
1086 */
1087
1088 /**
1089 * @}
1090 */
1091
1092 #endif /* OPAMP1 || OPAMP2 || OPAMP3 || OPAMP4 */
1093
1094 #endif /* HAL_OPAMP_MODULE_ENABLED */
1095 /**
1096 * @}
1097 */
1098
1099
1100