Linux通过shell命令读取ADC电压
Linux的ADC在应用层上可以直接操作/sys/bus/iio/devices/iio:\device0/目录的文件,而对于Linux的ADC操作有两种模式,一种是单次读取模式,第二种是多次读取模式。
一、单次读取
对于Linux系统上的ADC读取,在m3352上支持4路ADC输入,系统提供/sys文件系统接口操作,
在/sys/bus/iio/devices/iio:\device0/目录下有in_voltage4_raw~in_voltage7_raw这四个文件,
分别读取这4个文件,可获得对应的ADC值。
cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw 2782
二、多次读取
官方直接写一个C的程序去实现的,可能水平不够,没太看懂这样做的意义。直接用shell写个脚本多执行几次上面的命令不就成多次读取了吗,等以后回来来看看两者的利弊
我写的shell
#!/bin/bash
for a in {1..10}
do
cat /sys/bus/iio/devices/iio\:device0/in_voltage$1_raw
sleep 1
done
官方给的就复杂了
1.定义两个API函数 int find_type_by_name(const char name, const char type) 获取设备,其中name为需要打开的文件名
int build_channel_array(const char device_dir, struct iio_channel_info **ci_array, int counter) 根据ADC文件获取相应的ADC
2.程序源码
dev_num = find_type_by_name(device_name, "iio:device");
if (dev_num < 0) {
printf("Failed to find the %s\n", device_name);
ret = -ENODEV;
goto error_ret;
}
asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
if (ret) {
printf("Problem reading scan element information\n");
printf("diag %s\n", dev_dir_name);
goto error_ret;
}
ret = asprintf(&buf_dir_name, "%siio:device%d/buffer", iio_dir, dev_num);
if (ret < 0) {
ret = -ENOMEM;
goto error_ret;
}
ret = write_sysfs_int("length", buf_dir_name, buf_len);
if (ret < 0)
goto error_free_buf_dir_name;
ret = write_sysfs_int("enable", buf_dir_name, 1);
if (ret < 0)
goto error_free_buf_dir_name;
ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_buf_dir_name;
}
fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
if (fp == -1) {
printf("Failed to open %s\n", buffer_access);
ret = -errno;
goto error_free_buf_dir_name;
}
scan_size = size_from_channelarray(infoarray, num_channels);
data = malloc(scan_size*buf_len);
if (!data) {
ret = -ENOMEM;
goto error_close_buffer_access;
}
for (j = 0; j < num_loops; j++) {
usleep(timedelay);
read_size = read(fp, data, buf_len*scan_size);
if (read_size == -EAGAIN) {
printf("nothing available\n");
continue;
}
for (i = 0; i < read_size/4; i++, data+=4)
printf("ADC Value: %d\n", *(long*)data);
}
ret = write_sysfs_int("enable", buf_dir_name, 0);
if (ret < 0)
goto error_close_buffer_access;
值得注意的是,ADC的多次读取模式中,每次只能开启一个通道,若要切换通道必须先关闭已打开的ADC通道。
(1)创建设备节点 创建/dev/iio:device0设备节点,节点信息,参考/sys/bus/iio/devices/iio:device0/dev文件: #cat /sys/bus/iio/devices/iio:device0/dev 251:0 设备节点主次设备号是251,0。创建命令:
(2)设置continuos模式 [root@M3352 ~]# echo continuous > /sys/bus/iio/devices/iio\:device0/mode
(3)使能通道4 [root@M3352 ~]# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_volta4_en
(4)运行范例程序
[root@M3352 ~]# ./generic_buffer -n tiadc -l 16 -c 5
ADC Value: 2199
ADC Value: 2199
ADC Value: 2199
ADC Value: 2200
ADC Value: 2202
其中,l和c参数,请参考generic_buffer.c源码。 (5)切换通道 切换通道时,则需要先关闭通道4,打开需要的通道,如通道5:
[root@M3352 ~]# echo 0 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_volta4_en
[root@M3352 ~]# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_volta5_en
然后继续读取即可。
|