1 /******************************************************************************************************************************************
2 * 文件名称: SWM341_adc.c
3 * 功能说明: SWM341单片机的ADC数模转换器功能驱动库
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.0.0 2016年1月30日
7 * 升级记录:
8 *******************************************************************************************************************************************
9 * @attention
10 *
11 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
12 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
13 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
14 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
15 * -ECTION WITH THEIR PRODUCTS.
16 *
17 * COPYRIGHT 2012 Synwit Technology
18 *******************************************************************************************************************************************/
19 #include "SWM341.h"
20 #include "SWM341_adc.h"
21
22
23 /******************************************************************************************************************************************
24 * 函数名称: ADC_Init()
25 * 功能说明: ADC模数转换器初始化
26 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
27 * ADC_InitStructure * initStruct 包含ADC各相关定值的结构体
28 * 输 出: 无
29 * 注意事项: 无
30 ******************************************************************************************************************************************/
ADC_Init(ADC_TypeDef * ADCx,ADC_InitStructure * initStruct)31 void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct)
32 {
33 uint32_t i;
34
35 switch((uint32_t)ADCx)
36 {
37 case ((uint32_t)ADC0):
38 SYS->CLKSEL &= ~(SYS_CLKSEL_AD0_Msk | SYS_CLKSEL_AD0DIV_Msk);
39 SYS->CLKSEL |= (initStruct->clk_src << SYS_CLKSEL_AD0_Pos);
40
41 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_ADC0_Pos);
42 break;
43
44 case ((uint32_t)ADC1):
45 SYS->CLKSEL &= ~(SYS_CLKSEL_AD1_Msk | SYS_CLKSEL_AD1DIV_Msk);
46 SYS->CLKSEL |= (initStruct->clk_src << SYS_CLKSEL_AD1_Pos);
47
48 SYS->CLKEN1 |= (0x01 << SYS_CLKEN1_ADC1_Pos);
49 break;
50 }
51
52 ADC_Close(ADCx); //一些关键寄存器只能在ADC关闭时设置
53
54 ADCx->CR |= (1 <<ADC_CR_RESET_Pos);
55 for(i = 0; i < 120*20; i++) __NOP(); //至少2个采样时钟周期
56 ADCx->CR &= ~(1 << ADC_CR_RESET_Pos);
57
58 ADCx->CR |= (0xF << ADC_CR_FFCLR_Pos);
59 ADCx->CR &= ~(0xF << ADC_CR_FFCLR_Pos);
60
61 ADCx->CR &= ~ADC_CR_AVG_Msk;
62 ADCx->CR |= (initStruct->samplAvg << ADC_CR_AVG_Pos);
63
64 ADCx->IE = 0;
65 ADCx->IF = 0x3F3F3F3F; //清除中断标志
66
67 ADCx->IE |= (((initStruct->EOC_IEn & ADC_SEQ0) ? 1 : 0) << ADC_IE_SEQ0EOC_Pos) |
68 (((initStruct->EOC_IEn & ADC_SEQ1) ? 1 : 0) << ADC_IE_SEQ1EOC_Pos) |
69 (((initStruct->EOC_IEn & ADC_SEQ2) ? 1 : 0) << ADC_IE_SEQ2EOC_Pos) |
70 (((initStruct->EOC_IEn & ADC_SEQ3) ? 1 : 0) << ADC_IE_SEQ3EOC_Pos);
71
72 ADCx->IE |= (((initStruct->HalfIEn & ADC_SEQ0) ? 1 : 0) << ADC_IE_SEQ0HALF_Pos) |
73 (((initStruct->HalfIEn & ADC_SEQ1) ? 1 : 0) << ADC_IE_SEQ1HALF_Pos) |
74 (((initStruct->HalfIEn & ADC_SEQ2) ? 1 : 0) << ADC_IE_SEQ2HALF_Pos) |
75 (((initStruct->HalfIEn & ADC_SEQ3) ? 1 : 0) << ADC_IE_SEQ3HALF_Pos);
76
77 switch((uint32_t)ADCx)
78 {
79 case ((uint32_t)ADC0):
80 if(initStruct->EOC_IEn | initStruct->HalfIEn) NVIC_EnableIRQ(ADC0_IRQn);
81 break;
82
83 case ((uint32_t)ADC1):
84 if(initStruct->EOC_IEn | initStruct->HalfIEn) NVIC_EnableIRQ(ADC1_IRQn);
85 break;
86 }
87 }
88
ADC_seq2pos(uint32_t seq)89 static uint32_t ADC_seq2pos(uint32_t seq)
90 {
91 uint32_t pos = 0;
92
93 switch(seq)
94 {
95 case ADC_SEQ0: pos = 0; break;
96 case ADC_SEQ1: pos = 8; break;
97 case ADC_SEQ2: pos = 16; break;
98 case ADC_SEQ3: pos = 24; break;
99 }
100
101 return pos;
102 }
103
104 /******************************************************************************************************************************************
105 * 函数名称: ADC_SEQ_Init()
106 * 功能说明: ADC序列初始化
107 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
108 * uint32_t seq 指定要设置的序列,有效值包括ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
109 * ADC_SEQ_InitStructure * initStruct 包含ADC序列设定定值的结构体
110 * 输 出: 无
111 * 注意事项: 无
112 ******************************************************************************************************************************************/
ADC_SEQ_Init(ADC_TypeDef * ADCx,uint32_t seq,ADC_SEQ_InitStructure * initStruct)113 void ADC_SEQ_Init(ADC_TypeDef * ADCx, uint32_t seq, ADC_SEQ_InitStructure * initStruct)
114 {
115 uint32_t pos = ADC_seq2pos(seq);
116
117 switch(seq)
118 {
119 case ADC_SEQ0:
120 case ADC_SEQ1:
121 ADCx->SEQCHN0 &= ~(0xFFFu << (pos * 2));
122 ADCx->SEQCHN0 |= (initStruct->channels << (pos * 2));
123 break;
124
125 case ADC_SEQ2:
126 case ADC_SEQ3:
127 ADCx->SEQCHN1 &= ~(0xFFFu << ((pos - 16) * 2));
128 ADCx->SEQCHN1 |= (initStruct->channels << ((pos - 16) * 2));
129 break;
130 }
131
132 ADCx->SEQTRG &= ~(0xFFu << pos);
133 ADCx->SEQTRG |= (initStruct->trig_src << pos);
134
135 ADCx->SEQCOV &= ~(0xFFu << pos);
136 ADCx->SEQCOV |= ((initStruct->conv_cnt ? initStruct->conv_cnt - 1 : 0) << pos);
137
138 ADCx->SEQSMP &= ~(0x0Fu << (pos >> 1));
139 ADCx->SEQSMP |= (initStruct->samp_tim << (pos >> 1));
140 }
141
142 /******************************************************************************************************************************************
143 * 函数名称: ADC_CMP_Init()
144 * 功能说明: ADC比较功能初始化
145 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
146 * uint32_t seq 指定要设置的序列,有效值包括ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
147 * ADC_CMP_InitStructure * initStruct 包含ADC比较功能设定定值的结构体
148 * 输 出: 无
149 * 注意事项: 无
150 ******************************************************************************************************************************************/
ADC_CMP_Init(ADC_TypeDef * ADCx,uint32_t seq,ADC_CMP_InitStructure * initStruct)151 void ADC_CMP_Init(ADC_TypeDef * ADCx, uint32_t seq, ADC_CMP_InitStructure * initStruct)
152 {
153 uint32_t idx;
154 uint32_t pos = ADC_seq2pos(seq);
155
156 idx = pos / 8;
157 ADCx->SEQ[idx].CMP = (initStruct->UpperLimit << ADC_CMP_MAX_Pos) |
158 (initStruct->LowerLimit << ADC_CMP_MIN_Pos);
159
160 if(initStruct->UpperLimitIEn) ADCx->IE |= (1 << (pos + 4));
161 else ADCx->IE &= ~(1 << (pos + 4));
162
163 if(initStruct->LowerLimitIEn) ADCx->IE |= (1 << (pos + 5));
164 else ADCx->IE &= ~(1 << (pos + 5));
165
166 if(initStruct->UpperLimitIEn || initStruct->LowerLimitIEn)
167 {
168 switch((uint32_t)ADCx)
169 {
170 case ((uint32_t)ADC0): NVIC_EnableIRQ(ADC0_IRQn); break;
171 case ((uint32_t)ADC1): NVIC_EnableIRQ(ADC1_IRQn); break;
172 }
173 }
174 }
175
176 /******************************************************************************************************************************************
177 * 函数名称: ADC_Open()
178 * 功能说明: ADC开启,可以软件启动、或硬件触发ADC转换
179 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
180 * 输 出: 无
181 * 注意事项: 无
182 ******************************************************************************************************************************************/
ADC_Open(ADC_TypeDef * ADCx)183 void ADC_Open(ADC_TypeDef * ADCx)
184 {
185 uint32_t i;
186
187 ADCx->CR2 |= (1 << ADC_CR2_ENLDO_Pos);
188 for(i = 0; i < 64*20; i++) __NOP();
189
190 ADCx->CR |= (0x01 << ADC_CR_EN_Pos);
191 }
192
193 /******************************************************************************************************************************************
194 * 函数名称: ADC_Calibrate()
195 * 功能说明: ADC校准
196 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
197 * 输 出: 无
198 * 注意事项: 无
199 ******************************************************************************************************************************************/
ADC_Calibrate(ADC_TypeDef * ADCx)200 void ADC_Calibrate(ADC_TypeDef * ADCx)
201 {
202 uint32_t i;
203
204 ADCx->CALIB |= (1 << ADC_CALIB_RESET_Pos);
205 for(i = 0; i < 120 * 20; i++) __NOP(); //2个采样时钟周期
206
207 ADCx->CALIB |= (1 << ADC_CALIB_START_Pos);
208 for(i = 0; i < 120 * 10; i++) __NOP();
209 ADCx->CALIB &=~(1 << ADC_CALIB_START_Pos);
210 while(ADCx->CALIB & ADC_CALIB_BUSY_Msk) __NOP();
211
212 ADCx->CALIB |= (1 << ADC_CALIB_LOAD_Pos);
213 }
214
215 /******************************************************************************************************************************************
216 * 函数名称: ADC_Close()
217 * 功能说明: ADC关闭,无法软件启动、或硬件触发ADC转换
218 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
219 * 输 出: 无
220 * 注意事项: 无
221 ******************************************************************************************************************************************/
ADC_Close(ADC_TypeDef * ADCx)222 void ADC_Close(ADC_TypeDef * ADCx)
223 {
224 ADCx->CR &= ~(0x01 << ADC_CR_EN_Pos);
225 }
226
227 /******************************************************************************************************************************************
228 * 函数名称: ADC_Start()
229 * 功能说明: 软件触发模式下启动ADC转换
230 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
231 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3及其组合(即“按位或”运算)
232 * 输 出: 无
233 * 注意事项: 无
234 ******************************************************************************************************************************************/
ADC_Start(ADC_TypeDef * ADCx,uint32_t seq)235 void ADC_Start(ADC_TypeDef * ADCx, uint32_t seq)
236 {
237 ADCx->GO |= (seq << ADC_GO_SEQ0_Pos);
238 }
239
240 /******************************************************************************************************************************************
241 * 函数名称: ADC_Stop()
242 * 功能说明: 软件触发模式下停止ADC转换
243 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
244 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3及其组合(即“按位或”运算)
245 * 输 出: 无
246 * 注意事项: 无
247 ******************************************************************************************************************************************/
ADC_Stop(ADC_TypeDef * ADCx,uint32_t seq)248 void ADC_Stop(ADC_TypeDef * ADCx, uint32_t seq)
249 {
250 ADCx->GO &= ~(seq << ADC_GO_SEQ0_Pos);
251 }
252
253 /******************************************************************************************************************************************
254 * 函数名称: ADC_Read()
255 * 功能说明: 从指定序列读取转换结果
256 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
257 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
258 * uint32_t *chn 转换结果来自哪个通道,ADC_CH0、ADC_CH1、... ...、ADC_CH10、ADC_CH11
259 * 输 出: uint32_t 读取到的转换结果
260 * 注意事项: 无
261 ******************************************************************************************************************************************/
ADC_Read(ADC_TypeDef * ADCx,uint32_t seq,uint32_t * chn)262 uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t seq, uint32_t *chn)
263 {
264 uint32_t idx = ADC_seq2pos(seq) / 8;
265
266 uint32_t reg = ADCx->SEQ[idx].DR;
267
268 *chn = 1 << ((reg & ADC_DR_CHNUM_Msk) >> ADC_DR_CHNUM_Pos);
269
270 return reg & ADC_DR_VALUE_Msk;
271 }
272
273 /******************************************************************************************************************************************
274 * 函数名称: ADC_DataAvailable()
275 * 功能说明: 指定序列是否有数据可读取
276 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
277 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
278 * 输 出: uint32_t 1 有数据可读取 0 无数据
279 * 注意事项: 无
280 ******************************************************************************************************************************************/
ADC_DataAvailable(ADC_TypeDef * ADCx,uint32_t seq)281 uint32_t ADC_DataAvailable(ADC_TypeDef * ADCx, uint32_t seq)
282 {
283 uint32_t idx = ADC_seq2pos(seq) / 8;
284
285 return (ADCx->SEQ[idx].SR & ADC_SR_EMPTY_Msk) ? 0 : 1;
286 }
287
288
289 /******************************************************************************************************************************************
290 * 函数名称: ADC_INTEn()
291 * 功能说明: 中断使能
292 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
293 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
294 * uint32_t it interrupt type,有效值包括ADC_IT_EOC、ADC_IT_FIFO_OVF、ADC_IT_FIFO_HALF、ADC_IT_FIFO_FULL、
295 * ADC_IT_CMP_MAX、ADC_IT_CMP_MIN 及其“或”
296 * 输 出: 无
297 * 注意事项: 无
298 ******************************************************************************************************************************************/
ADC_INTEn(ADC_TypeDef * ADCx,uint32_t seq,uint32_t it)299 void ADC_INTEn(ADC_TypeDef * ADCx, uint32_t seq, uint32_t it)
300 {
301 uint32_t pos = ADC_seq2pos(seq);
302
303 ADCx->IE |= (it << pos);
304 }
305
306 /******************************************************************************************************************************************
307 * 函数名称: ADC_INTDis()
308 * 功能说明: 中断禁止
309 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
310 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
311 * uint32_t it interrupt type,有效值包括ADC_IT_EOC、ADC_IT_FIFO_OVF、ADC_IT_FIFO_HALF、ADC_IT_FIFO_FULL、
312 * ADC_IT_CMP_MAX、ADC_IT_CMP_MIN 及其“或”
313 * 输 出: 无
314 * 注意事项: 无
315 ******************************************************************************************************************************************/
ADC_INTDis(ADC_TypeDef * ADCx,uint32_t seq,uint32_t it)316 void ADC_INTDis(ADC_TypeDef * ADCx, uint32_t seq, uint32_t it)
317 {
318 uint32_t pos = ADC_seq2pos(seq);
319
320 ADCx->IE &= ~(it << pos);
321 }
322
323 /******************************************************************************************************************************************
324 * 函数名称: ADC_INTClr()
325 * 功能说明: 中断标志清除
326 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
327 * uint32_t seq 指定要设置的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
328 * uint32_t it interrupt type,有效值包括ADC_IT_EOC、ADC_IT_FIFO_OVF、ADC_IT_FIFO_HALF、ADC_IT_FIFO_FULL、
329 * ADC_IT_CMP_MAX、ADC_IT_CMP_MIN 及其“或”
330 * 输 出: 无
331 * 注意事项: 无
332 ******************************************************************************************************************************************/
ADC_INTClr(ADC_TypeDef * ADCx,uint32_t seq,uint32_t it)333 void ADC_INTClr(ADC_TypeDef * ADCx, uint32_t seq, uint32_t it)
334 {
335 uint32_t pos = ADC_seq2pos(seq);
336
337 ADCx->IF = (it << pos);
338 }
339
340 /******************************************************************************************************************************************
341 * 函数名称: ADC_INTStat()
342 * 功能说明: 中断状态查询
343 * 输 入: ADC_TypeDef * ADCx 指定要设置的ADC,有效值包括ADC0、ADC1
344 * uint32_t seq 指定要查询的ADC序列,有效值为ADC_SEQ0、ADC_SEQ1、ADC_SEQ2、ADC_SEQ3
345 * uint32_t it interrupt type,有效值包括ADC_IT_EOC、ADC_IT_FIFO_OVF、ADC_IT_FIFO_HALF、ADC_IT_FIFO_FULL、
346 * ADC_IT_CMP_MAX、ADC_IT_CMP_MIN 及其“或”
347 * 输 出: uint32_t 1 中断发生 0 中断未发生
348 * 注意事项: 无
349 ******************************************************************************************************************************************/
ADC_INTStat(ADC_TypeDef * ADCx,uint32_t seq,uint32_t it)350 uint32_t ADC_INTStat(ADC_TypeDef * ADCx, uint32_t seq, uint32_t it)
351 {
352 uint32_t pos = ADC_seq2pos(seq);
353
354 return (ADCx->IF & (it << pos)) ? 1 : 0;
355 }
356