summaryrefslogtreecommitdiff
path: root/bsp/nxp/lpc/lpc408x/drivers/drv_adc.c
blob: 77d5c3c9d90b68d53e43ce2c39cb3897932f67a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-27     fzxhub       the first version
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_adc.h"

#ifdef RT_USING_ADC

#ifdef BSP_USING_ADC

struct lpc_adc
{
    LPC_ADC_TypeDef *ADC;
};
/*
* channel:0-7
*/
static rt_err_t lpc_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
    struct lpc_adc *adc;

    RT_ASSERT(device != RT_NULL);
    adc = (struct lpc_adc *)device->parent.user_data;

    //enabled ADC
    if(enabled == RT_FALSE) adc->ADC->CR &= ~(1<<21);
    else adc->ADC->CR |= (1<<21);

    //Select the channel
    adc->ADC->CR |= (1<<channel);

    return RT_EOK;
}

static rt_err_t lpc_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
    rt_uint32_t data;

    struct lpc_adc *adc;

    RT_ASSERT(device != RT_NULL);
    adc = (struct lpc_adc *)device->parent.user_data;

    adc->ADC->CR = (LPC_ADC->CR & 0x00FFFF00) | (1<<channel) | (1 << 24);
    while ((adc->ADC->GDR & 0x80000000) == 0);
    adc->ADC->CR = adc->ADC->CR | (1 << 24);
    while ((adc->ADC->GDR & 0x80000000) == 0);

    data = adc->ADC->GDR;
    data = (data >> 4) & 0xFFF;

    *value = data;

    return RT_EOK;
}

static const struct rt_adc_ops lpc_adc_ops =
{
    lpc_adc_enabled,
    lpc_adc_convert,
};

struct lpc_adc lpc_adc0 =
{
    LPC_ADC,
};

struct rt_adc_device adc0;

int rt_hw_adc_init(void)
{
    rt_err_t ret = RT_EOK;
    struct lpc_adc *adc;

    adc = &lpc_adc0;

    adc0.ops = &lpc_adc_ops;
    adc0.parent.user_data = adc;

    //ADC port
    LPC_IOCON->P0_23 = 0x01;     //ADC0[0]
    LPC_IOCON->P0_24 = 0x01;     //ADC0[1]
    LPC_IOCON->P0_25 = 0x01;     //ADC0[2]
    LPC_IOCON->P0_26 = 0x01;     //ADC0[3]
    LPC_IOCON->P1_30 = 0x03;     //ADC0[4]
    LPC_IOCON->P1_31 = 0x03;     //ADC0[5]
    LPC_IOCON->P0_12 = 0x03;     //ADC0[6]
    LPC_IOCON->P0_13 = 0x03;     //ADC0[7]


    //clock
    LPC_SC->PCONP |= (1U << 12);
    //config
    LPC_ADC->CR = 0;
    LPC_ADC->CR = (1 << 0)|      // SEL
                  ((PeripheralClock / 1000000 - 1) << 8) |    // CLKDIV = Fpclk / 1000000 - 1
                  (0 << 16)|     // BURST
                  (0 << 17)|     // CLKS
                  (1 << 21)|     // PDN
                  (0 << 22)|     // TEST1
                  (1 << 24)|     // START
                  (0 << 27);     // EDGE
    //waiting
    while ((LPC_ADC->GDR & 0x80000000) == 0);

    ret = rt_hw_adc_register(&adc0,"adc0",&lpc_adc_ops,adc);

    return ret;
}

INIT_BOARD_EXPORT(rt_hw_adc_init);
#endif /* BSP_USING_ADC */

#endif /* RT_USING_ADC */