1 /**************************************************************************//**
2 * @file lpadc.c
3 * @version V1.00
4 * @brief M2L31 series LPADC driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * Copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11 /** @addtogroup Standard_Driver Standard Driver
12 @{
13 */
14
15 /** @addtogroup LPADC_Driver LPADC Driver
16 @{
17 */
18
19 int32_t g_LPADC_i32ErrCode = 0; /*!< LPADC global error code */
20
21 /** @addtogroup LPADC_EXPORTED_FUNCTIONS LPADC Exported Functions
22 @{
23 */
24
25 /**
26 * @brief This API configures LPADC module to be ready for convert the input from selected channel
27 * @param[in] lpadc The pointer of the specified LPADC module
28 * @param[in] u32InputMode Decides the LPADC analog input mode. Valid values are:
29 * - \ref LPADC_ADCR_DIFFEN_SINGLE_END :Single-end input mode
30 * - \ref LPADC_ADCR_DIFFEN_DIFFERENTIAL :Differential input mode
31 * @param[in] u32OpMode Decides the LPADC operation mode. Valid values are:
32 * - \ref LPADC_ADCR_ADMD_SINGLE :Single mode.
33 * - \ref LPADC_ADCR_ADMD_BURST :Burst mode.
34 * - \ref LPADC_ADCR_ADMD_SINGLE_CYCLE :Single cycle scan mode.
35 * - \ref LPADC_ADCR_ADMD_CONTINUOUS :Continuous scan mode.
36 * @param[in] u32ChMask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1..., bit 15 is channel 15.
37 * @return None
38 * @note LPADC can only convert 1 channel at a time. If more than 1 channels are enabled, only channel
39 * with smallest number will be convert.
40 * @note This API does not turn on LPADC power nor does trigger LPADC conversion.
41 * @note This API will reset and calibrate LPADC if LPADC never be calibrated after chip power on.
42 * @note This function sets g_LPADC_i32ErrCode to LPADC_TIMEOUT_ERR if CALIF(LPADC_ADCALSTSR[0]) is not set to 1
43 */
LPADC_Open(LPADC_T * lpadc,uint32_t u32InputMode,uint32_t u32OpMode,uint32_t u32ChMask)44 void LPADC_Open(LPADC_T *lpadc,
45 uint32_t u32InputMode,
46 uint32_t u32OpMode,
47 uint32_t u32ChMask)
48 {
49 uint32_t u32Delay = SystemCoreClock; /* 1 second */
50
51 /* select LPADC0 as LPADC controller, not EADC0. */
52 SYS->IVSCTL |= SYS_IVSCTL_ADCCSEL_Msk;
53
54 g_LPADC_i32ErrCode = 0;
55
56 /*Wait the LPADC Power On Ready */
57 while (!(lpadc->ADSR0 & LPADC_ADSR0_ADPRDY_Msk))
58 {
59 if (--u32Delay == 0)
60 {
61 g_LPADC_i32ErrCode = LPADC_TIMEOUT_ERR;
62 break;
63 }
64 }
65
66 /* Do calibration for LPADC to decrease the effect of electrical random noise. */
67 if ((lpadc->ADCALSTS & LPADC_ADCALSTS_CALIF_Msk) == 0)
68 {
69 /* Must reset LPADC before LPADC calibration */
70 lpadc->ADCR |= LPADC_ADCR_RESET_Msk;
71 while((lpadc->ADCR & LPADC_ADCR_RESET_Msk) == LPADC_ADCR_RESET_Msk)
72 {
73 if (--u32Delay == 0)
74 {
75 g_LPADC_i32ErrCode = LPADC_TIMEOUT_ERR;
76 break;
77 }
78 }
79
80 lpadc->ADCALSTS |= LPADC_ADCALSTS_CALIF_Msk; /* Clear Calibration Finish Interrupt Flag */
81 lpadc->ADCAL |= LPADC_ADCAL_CALEN_Msk; /* Enable Calibration function */
82 LPADC_START_CONV(lpadc); /* Start to calibration */
83 u32Delay = SystemCoreClock;
84 while((lpadc->ADCALSTS & LPADC_ADCALSTS_CALIF_Msk) != LPADC_ADCALSTS_CALIF_Msk) /* Wait calibration finish */
85 {
86 if (--u32Delay == 0)
87 {
88 g_LPADC_i32ErrCode = LPADC_TIMEOUT_ERR;
89 break;
90 }
91 }
92 }
93
94 lpadc->ADCR = (lpadc->ADCR & (~(LPADC_ADCR_DIFFEN_Msk | LPADC_ADCR_ADMD_Msk))) |
95 (u32InputMode) | (u32OpMode);
96
97 lpadc->ADCHER = (lpadc->ADCHER & ~LPADC_ADCHER_CHEN_Msk) | (u32ChMask);
98
99 return;
100 }
101
102 /**
103 * @brief Disable LPADC module
104 * @param[in] lpadc The pointer of the specified LPADC module
105 * @return None
106 */
LPADC_Close(LPADC_T * lpadc)107 void LPADC_Close(LPADC_T *lpadc)
108 {
109 SYS_UnlockReg();
110 LPSCC->IPRST0 |= (LPSCC_IPRST0_LPADC0RST_Msk);
111 LPSCC->IPRST0 &= ~(LPSCC_IPRST0_LPADC0RST_Msk);
112 SYS_LockReg();
113 return;
114 }
115
116 /**
117 * @brief Configure the hardware trigger condition and enable hardware trigger
118 * @param[in] lpadc The pointer of the specified LPADC module
119 * @param[in] u32Source Decides the hardware trigger source. Valid values are:
120 * - \ref LPADC_ADCR_TRGS_STADC :A/D conversion is started by external STADC pin.
121 * - \ref LPADC_ADCR_TRGS_TIMER :A/D conversion is started by Timer.
122 * - \ref LPADC_ADCR_TRGS_PWM :A/D conversion is started by PWM.
123 * - \ref LPADC_ADCR_TRGS_EPWM :A/D conversion is started by EPWM.
124 * - \ref LPADC_ADCR_TRGS_ACMP0 :A/D conversion is started by ACMP0.
125 * - \ref LPADC_ADCR_TRGS_ACMP1 :A/D conversion is started by ACMP1.
126 * - \ref LPADC_ADCR_TRGS_ACMP2 :A/D conversion is started by ACMP2.
127 * @param[in] u32Param While LPADC trigger by external pin, this parameter is used to set trigger condition.
128 * Valid values are:
129 * - \ref LPADC_ADCR_TRGCOND_LOW_LEVEL :STADC Low level active
130 * - \ref LPADC_ADCR_TRGCOND_HIGH_LEVEL :STADC High level active
131 * - \ref LPADC_ADCR_TRGCOND_FALLING_EDGE :STADC Falling edge active
132 * - \ref LPADC_ADCR_TRGCOND_RISING_EDGE :STADC Rising edge active
133 * While LPADC trigger by other source, this parameter is unused.
134 * @return None
135 * @note Software should disable TRGEN and ADST before change TRGS.
136 */
LPADC_EnableHWTrigger(LPADC_T * lpadc,uint32_t u32Source,uint32_t u32Param)137 void LPADC_EnableHWTrigger(LPADC_T *lpadc,
138 uint32_t u32Source,
139 uint32_t u32Param)
140 {
141 /* Software should clear TRGEN bit and ADST bit before changing TRGS bits. */
142 lpadc->ADCR &= ~(LPADC_ADCR_TRGEN_Msk | LPADC_ADCR_ADST_Msk);
143
144 if(u32Source == LPADC_ADCR_TRGS_STADC)
145 {
146 lpadc->ADCR = (lpadc->ADCR & ~(LPADC_ADCR_TRGS_Msk | LPADC_ADCR_TRGCOND_Msk)) |
147 ((u32Source) | (u32Param) | LPADC_ADCR_TRGEN_Msk);
148 }
149 else
150 {
151 lpadc->ADCR = (lpadc->ADCR & ~(LPADC_ADCR_TRGS_Msk | LPADC_ADCR_TRGCOND_Msk)) |
152 ((u32Source) | LPADC_ADCR_TRGEN_Msk);
153 }
154 return;
155 }
156
157 /**
158 * @brief Disable hardware trigger LPADC function.
159 * @param[in] lpadc The pointer of the specified LPADC module
160 * @return None
161 */
LPADC_DisableHWTrigger(LPADC_T * lpadc)162 void LPADC_DisableHWTrigger(LPADC_T *lpadc)
163 {
164 /* Software should clear TRGEN bit and ADST bit before changing TRGS bits. */
165 lpadc->ADCR &= ~(LPADC_ADCR_TRGEN_Msk | LPADC_ADCR_ADST_Msk);
166 lpadc->ADCR &= ~(LPADC_ADCR_TRGS_Msk | LPADC_ADCR_TRGCOND_Msk);
167 return;
168 }
169
170 /**
171 * @brief Enable the interrupt(s) selected by u32Mask parameter.
172 * @param[in] lpadc The pointer of the specified LPADC module
173 * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
174 * corresponds to a interrupt status. This parameter decides which
175 * interrupts will be enabled.
176 * - \ref LPADC_ADF_INT :LPADC convert complete interrupt
177 * - \ref LPADC_CMP0_INT :LPADC comparator 0 interrupt
178 * - \ref LPADC_CMP1_INT :LPADC comparator 1 interrupt
179 * @return None
180 */
LPADC_EnableInt(LPADC_T * lpadc,uint32_t u32Mask)181 void LPADC_EnableInt(LPADC_T *lpadc, uint32_t u32Mask)
182 {
183 if((u32Mask) & LPADC_ADF_INT)
184 lpadc->ADCR |= LPADC_ADCR_ADIE_Msk;
185 if((u32Mask) & LPADC_CMP0_INT)
186 lpadc->ADCMPR[0] |= LPADC_ADCMPR_CMPIE_Msk;
187 if((u32Mask) & LPADC_CMP1_INT)
188 lpadc->ADCMPR[1] |= LPADC_ADCMPR_CMPIE_Msk;
189
190 return;
191 }
192
193 /**
194 * @brief Disable the interrupt(s) selected by u32Mask parameter.
195 * @param[in] lpadc The pointer of the specified LPADC module
196 * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
197 * corresponds to a interrupt status. This parameter decides which
198 * interrupts will be disabled.
199 * - \ref LPADC_ADF_INT :LPADC convert complete interrupt
200 * - \ref LPADC_CMP0_INT :LPADC comparator 0 interrupt
201 * - \ref LPADC_CMP1_INT :LPADC comparator 1 interrupt
202 * @return None
203 */
LPADC_DisableInt(LPADC_T * lpadc,uint32_t u32Mask)204 void LPADC_DisableInt(LPADC_T *lpadc, uint32_t u32Mask)
205 {
206 if((u32Mask) & LPADC_ADF_INT)
207 lpadc->ADCR &= ~LPADC_ADCR_ADIE_Msk;
208 if((u32Mask) & LPADC_CMP0_INT)
209 lpadc->ADCMPR[0] &= ~LPADC_ADCMPR_CMPIE_Msk;
210 if((u32Mask) & LPADC_CMP1_INT)
211 lpadc->ADCMPR[1] &= ~LPADC_ADCMPR_CMPIE_Msk;
212
213 return;
214 }
215
216 /**
217 * @brief Set LPADC extend sample time.
218 * @param[in] lpadc The pointer of the specified LPADC module.
219 * @param[in] u32ModuleNum Decides the sample module number, valid value are 0.
220 * @param[in] u32ExtendSampleTime Decides the extend sampling time, the range is from 0~255 LPADC clock. Valid value are from 0 to 0xFF.
221 * @return None
222 * @details When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy,
223 * user can extend A/D sampling time after trigger source is coming to get enough sampling time.
224 */
LPADC_SetExtendSampleTime(LPADC_T * lpadc,uint32_t u32ModuleNum,uint32_t u32ExtendSampleTime)225 void LPADC_SetExtendSampleTime(LPADC_T *lpadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime)
226 {
227 lpadc->ESMPCTL = (lpadc->ESMPCTL & ~LPADC_ESMPCTL_EXTSMPT_Msk) |
228 (u32ExtendSampleTime << LPADC_ESMPCTL_EXTSMPT_Pos);
229 }
230
231 /**
232 * @brief Select and configure Automatic Operation function
233 * @param[in] lpadc The pointer of the specified LPADC module
234 * @param[in] u32TrigSel The LPADC Automatic Operation Trigger Source:
235 * - \ref LPADC_AUTOCTL_TRIGSEL_SOFTWARE : Auto-operation Trigger Source from Software .
236 * - \ref LPADC_AUTOCTL_TRIGSEL_LPTMR0 : Auto-operation Trigger Source from LPTMR0.
237 * - \ref LPADC_AUTOCTL_TRIGSEL_LPTMR1 : Auto-operation Trigger Source from LPTMR1.
238 * - \ref LPADC_AUTOCTL_TRIGSEL_TTMR0 : Auto-operation Trigger Source from TTMR0.
239 * - \ref LPADC_AUTOCTL_TRIGSEL_TTMR1 : Auto-operation Trigger Source from TTMR1.
240 * - \ref LPADC_AUTOCTL_TRIGSEL_WKIOA0 : Auto-operation Trigger Source from WKIOA0.
241 * - \ref LPADC_AUTOCTL_TRIGSEL_WKIOB0 : Auto-operation Trigger Source from WKIOB0.
242 * - \ref LPADC_AUTOCTL_TRIGSEL_WKIOC0 : Auto-operation Trigger Source from WKIOC0.
243 * - \ref LPADC_AUTOCTL_TRIGSEL_WKIOD0 : Auto-operation Trigger Source from WKIOD0.
244 * - \ref LPADC_AUTOCTL_TRIGSEL_ACMP0 : Auto-operation Trigger Source from ACMP0.
245 * - \ref LPADC_AUTOCTL_TRIGSEL_ACMP1 : Auto-operation Trigger Source from ACMP1.
246 * - \ref LPADC_AUTOCTL_TRIGSEL_ACMP2 : Auto-operation Trigger Source from ACMP2.
247 * @return None
248 * @details The function is used to set Automatic Operation relative setting.
249 */
LPADC_SelectAutoOperationMode(LPADC_T * lpadc,uint32_t u32TrigSel)250 void LPADC_SelectAutoOperationMode(LPADC_T *lpadc, uint32_t u32TrigSel)
251 {
252 /* Automatic Operation Mode Disable */
253 lpadc->AUTOCTL &= ~(LPADC_AUTOCTL_AUTOEN_Msk);
254
255 if (u32TrigSel == LPADC_AUTOCTL_TRIGSEL_SOFTWARE)
256 lpadc->AUTOCTL = (lpadc->AUTOCTL & ~(LPADC_AUTOCTL_TRIGSEL_Msk | LPADC_AUTOCTL_TRIGEN_Msk));
257 else
258 lpadc->AUTOCTL = (lpadc->AUTOCTL & ~(LPADC_AUTOCTL_TRIGSEL_Msk | LPADC_AUTOCTL_TRIGEN_Msk)) |
259 (u32TrigSel | LPADC_AUTOCTL_TRIGEN_Msk);
260
261 /* Automatic Operation Mode Enable */
262 lpadc->AUTOCTL |= LPADC_AUTOCTL_AUTOEN_Msk;
263 }
264
265 /*@}*/ /* end of group LPADC_EXPORTED_FUNCTIONS */
266
267 /*@}*/ /* end of group LPADC_Driver */
268
269 /*@}*/ /* end of group Standard_Driver */
270
271 /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/
272