1 /*
2 * Copyright (c) 2023 STMicroelectronics
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/adc.h>
11 #include <zephyr/sys/printk.h>
12
13 #define SLEEP_TIME_MS 2000
14
15 #if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
16 !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
17 #error "No suitable devicetree overlay specified"
18 #endif
19
20 #define DT_SPEC_AND_COMMA(node_id, prop, idx) \
21 ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
22
23 /* Data of ADC io-channels specified in devicetree. */
24 static const struct adc_dt_spec adc_channels[] = {
25 DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
26 DT_SPEC_AND_COMMA)
27 };
28
main(void)29 int main(void)
30 {
31 int err;
32 uint32_t count = 0;
33 uint16_t buf;
34 struct adc_sequence sequence = {
35 .buffer = &buf,
36 /* buffer size in bytes, not number of samples */
37 .buffer_size = sizeof(buf),
38 };
39
40 /* Configure channels individually prior to sampling. */
41 for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
42 if (!adc_is_ready_dt(&adc_channels[i])) {
43 printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
44 return 0;
45 }
46
47 err = adc_channel_setup_dt(&adc_channels[i]);
48 if (err < 0) {
49 printk("Could not setup channel #%d (%d)\n", i, err);
50 return 0;
51 }
52 }
53
54 printk("Device ready\n");
55
56 while (true) {
57 printk("ADC reading[%u]:\n", count++);
58 for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
59 int32_t val_mv;
60
61 printk("- %s, channel %d: ",
62 adc_channels[i].dev->name,
63 adc_channels[i].channel_id);
64
65 (void)adc_sequence_init_dt(&adc_channels[i], &sequence);
66
67 err = adc_read_dt(&adc_channels[i], &sequence);
68 if (err < 0) {
69 printk("Could not read (%d)\n", err);
70 continue;
71 }
72
73 /*
74 * If using differential mode, the 16 bit value
75 * in the ADC sample buffer should be a signed 2's
76 * complement value.
77 */
78 if (adc_channels[i].channel_cfg.differential) {
79 val_mv = (int32_t)((int16_t)buf);
80 } else {
81 val_mv = (int32_t)buf;
82 }
83 printk("%"PRId32, val_mv);
84 err = adc_raw_to_millivolts_dt(&adc_channels[i],
85 &val_mv);
86 /* conversion to mV may not be supported, skip if not */
87 if (err < 0) {
88 printk(" (value in mV not available)\n");
89 } else {
90 printk(" = %"PRId32" mV\n", val_mv);
91 }
92 }
93
94 k_msleep(SLEEP_TIME_MS);
95 }
96 return 0;
97 }
98