ESM7200主板是英创公司推出的带有8路单端3.3V/12-bit AD的低成本主板。主板上提供了8路AD,能够支持多个通道单次采样,或者单个通道连续采集。经过测试在保证数据准确性和系统读取的情况下,连续采样速率最高约为58kSPS。由于这8路AD都是CPU自带的资源,性能上和专门的AD芯片还是有一定差距,所以主要面向的是需要单次采集或者单通道连续采集的应用场景。
如果应用只是定时读取一次AD的采样值,那么使用ESM7200主板上提供的8路AD是可以满足要求的。如果需要高速采集,ESM7200主板可以提供一路最高58kSPS采样率的通道,还需要到达更高的要求的话,就可以参考英创公司推出的专门的高速AD扩展方案,比如:《ESM7000异构CPU实时应用之三 8路并行数采应用程序》。
Linux系统中,AD功能都是基于IIO(Industrial I/O)子系统提供的,这是一个专门用于传感器,ADC或DAC的子系统,具体的介绍可以参考资料Linux Industrial I/O Subsystem。在ESM7200主板中,8路AD对应的设备如下表:
管脚 | AD通道 | 对应设备名称 | 索引号 |
E2 | AIN_CH1 | /sys/bus/iio/devices/iio:device0/ in_voltage0_raw | 0 |
E3 | AIN_CH2 | /sys/bus/iio/devices/iio:device0/ in_voltage1_raw | 1 |
E4 | AIN_CH3 | /sys/bus/iio/devices/iio:device0/ in_voltage2_raw | 2 |
E5 | AIN_CH4 | /sys/bus/iio/devices/iio:device0/ in_voltage3_raw | 3 |
E6 | AIN_CH5 | /sys/bus/iio/devices/iio:device0/ in_voltage4_raw | 4 |
E7 | AIN_CH6 | /sys/bus/iio/devices/iio:device0/ in_voltage5_raw | 5 |
E8 | AIN_CH7 | /sys/bus/iio/devices/iio:device0/ in_voltage8_raw | 8 |
E9 | AIN_CH8 | /sys/bus/iio/devices/iio:device0/ in_voltage9_raw | 9 |
可以看到每一路AD都对应一个IIO设备节点,当要读取AD的值的时候,就需要使用这些设备节点。我们首先介绍单次采样的读取方法。
本次测试使用的是ESM7200主板加上ESMARC系列通用评估底板,在评估底板上8路AD信号被引到了CN25(ISA)的端子上,因为ESMARC系列部分主板型号是支持ISA总线的,而ESM7200没有ISA总线,取而代之的是8路AD,具体的定义可参考下表:
信号名称及简要描述 | CN25 | 信号名称及简要描述 | |
PIN# | PIN# | ||
1 | 2 | ||
AIN_CH1 | 3 | 4 | AIN_CH5 |
AIN_CH2 | 5 | 6 | AIN_CH6 |
AIN_CH3 | 7 | 8 | AIN_CH7 |
AIN_CH4 | 9 | 10 | AIN_CH8 |
11 | 12 | ||
13 | 14 | ||
15 | 16 | ||
17 | 18 | ||
19 | 20 | GND,模拟地 |
客户如果考虑自己设计底板,可以参考表1查询每一路AD在主板上对应的管脚。如果是使用ESMARC评估底板进行测试和评估,可以参考表2连接外部模拟信号进行测试。
为了方便客户操作IIO子系统提供的各种功能,我们移植了ADI公司提供的libiio,这个库文件抽象了和硬件相关的底层细节,并提供了简单而完整的编程接口,可用于高级项目的编程。下面我们就基于libiio实现单次读取操作。
首先是获取IIO设备,这部分代码在ESMARC系统主板上是固定的,用户可以直接使用。
struct iio_device *dev; /* 获取IIO设备 */ ctx = iio_create_context_from_uri("local:"); dev = iio_context_get_device(ctx, 0); if (!dev) { fprintf(stderr, "Device not found\n"); iio_context_destroy(ctx); return EXIT_FAILURE; }
然后是指定对应的通道,这里填入AD通道对应的index号(参考表1),根据实际使用的通道填写就行了。
/* 获取对应的IIO通道,可以根据实际情况修改成需要的通道 */ ch = iio_device_get_channel(dev, 9); if (!iio_channel_is_scan_element(ch) || iio_channel_is_output(ch)) { printf("Can not get channel %d\n", ch); return -1; }
获取到对应的通道后,就可以直接读取通道的原始值了,注意读取来的数据是字符串。
const char *attr = "raw"; char *val[10]; /* 读取channel的原始值 */ ret = iio_channel_attr_read(ch, attr, &val, 10); if (ret <= 0) { printf("ERROR: while reading '%s': %d\n", attr, ret); } /* 数据处理,这里将数据直接打印出来 * 用户可以根据实际的情况进行处理,比如写入到记录文件中 * */ printf("raw value: %s\n", val);
通过libiio很简单就能够将对应通道的值读取出来,单次读取的方式还可以采用标准的文件读取方式(Linux系统中所有设备都是文件),在之前的文章中我们已经介绍过了《英创公司Linux主板低成本AD方案介绍》,用户可以根据自己的习惯选择。
感兴趣的客户可以联系英创的工程师索要例程的代码。在后续的文章中,我们将介绍低成本方案中如何实现单路的连续采样。
成都英创信息技术有限公司 028-8618 0660