1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-09-27 fzxhub the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include "drv_adc.h"
15
16 #ifdef RT_USING_ADC
17
18 #ifdef BSP_USING_ADC
19
20 struct lpc_adc
21 {
22 LPC_ADC_TypeDef *ADC;
23 };
24 /*
25 * channel:0-7
26 */
lpc_adc_enabled(struct rt_adc_device * device,rt_uint32_t channel,rt_bool_t enabled)27 static rt_err_t lpc_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
28 {
29 struct lpc_adc *adc;
30
31 RT_ASSERT(device != RT_NULL);
32 adc = (struct lpc_adc *)device->parent.user_data;
33
34 //enabled ADC
35 if(enabled == RT_FALSE) adc->ADC->CR &= ~(1<<21);
36 else adc->ADC->CR |= (1<<21);
37
38 //Select the channel
39 adc->ADC->CR |= (1<<channel);
40
41 return RT_EOK;
42 }
43
lpc_adc_convert(struct rt_adc_device * device,rt_uint32_t channel,rt_uint32_t * value)44 static rt_err_t lpc_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
45 {
46 rt_uint32_t data;
47
48 struct lpc_adc *adc;
49
50 RT_ASSERT(device != RT_NULL);
51 adc = (struct lpc_adc *)device->parent.user_data;
52
53 adc->ADC->CR = (LPC_ADC->CR & 0x00FFFF00) | (1<<channel) | (1 << 24);
54 while ((adc->ADC->GDR & 0x80000000) == 0);
55 adc->ADC->CR = adc->ADC->CR | (1 << 24);
56 while ((adc->ADC->GDR & 0x80000000) == 0);
57
58 data = adc->ADC->GDR;
59 data = (data >> 4) & 0xFFF;
60
61 *value = data;
62
63 return RT_EOK;
64 }
65
66 static const struct rt_adc_ops lpc_adc_ops =
67 {
68 lpc_adc_enabled,
69 lpc_adc_convert,
70 };
71
72 struct lpc_adc lpc_adc0 =
73 {
74 LPC_ADC,
75 };
76
77 struct rt_adc_device adc0;
78
rt_hw_adc_init(void)79 int rt_hw_adc_init(void)
80 {
81 rt_err_t ret = RT_EOK;
82 struct lpc_adc *adc;
83
84 adc = &lpc_adc0;
85
86 adc0.ops = &lpc_adc_ops;
87 adc0.parent.user_data = adc;
88
89 //ADC port
90 LPC_IOCON->P0_23 = 0x01; //ADC0[0]
91 LPC_IOCON->P0_24 = 0x01; //ADC0[1]
92 LPC_IOCON->P0_25 = 0x01; //ADC0[2]
93 LPC_IOCON->P0_26 = 0x01; //ADC0[3]
94 LPC_IOCON->P1_30 = 0x03; //ADC0[4]
95 LPC_IOCON->P1_31 = 0x03; //ADC0[5]
96 LPC_IOCON->P0_12 = 0x03; //ADC0[6]
97 LPC_IOCON->P0_13 = 0x03; //ADC0[7]
98
99
100 //clock
101 LPC_SC->PCONP |= (1U << 12);
102 //config
103 LPC_ADC->CR = 0;
104 LPC_ADC->CR = (1 << 0)| // SEL
105 ((PeripheralClock / 1000000 - 1) << 8) | // CLKDIV = Fpclk / 1000000 - 1
106 (0 << 16)| // BURST
107 (0 << 17)| // CLKS
108 (1 << 21)| // PDN
109 (0 << 22)| // TEST1
110 (1 << 24)| // START
111 (0 << 27); // EDGE
112 //waiting
113 while ((LPC_ADC->GDR & 0x80000000) == 0);
114
115 ret = rt_hw_adc_register(&adc0,"adc0",&lpc_adc_ops,adc);
116
117 return ret;
118 }
119
120 INIT_BOARD_EXPORT(rt_hw_adc_init);
121 #endif /* BSP_USING_ADC */
122
123 #endif /* RT_USING_ADC */
124