Linux IIO接口的低成本8通道AD

 2022-5-12     作者:黄志超     [nemail]    
[lablebox]

  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通道对应设备名称索引号
E2AIN_CH1/sys/bus/iio/devices/iio:device0/ in_voltage0_raw0
E3AIN_CH2/sys/bus/iio/devices/iio:device0/ in_voltage1_raw1
E4AIN_CH3/sys/bus/iio/devices/iio:device0/ in_voltage2_raw2
E5AIN_CH4/sys/bus/iio/devices/iio:device0/ in_voltage3_raw3
E6AIN_CH5/sys/bus/iio/devices/iio:device0/ in_voltage4_raw4
E7AIN_CH6/sys/bus/iio/devices/iio:device0/ in_voltage5_raw5
E8AIN_CH7/sys/bus/iio/devices/iio:device0/ in_voltage8_raw8
E9AIN_CH8/sys/bus/iio/devices/iio:device0/ in_voltage9_raw9


  可以看到每一路AD都对应一个IIO设备节点,当要读取AD的值的时候,就需要使用这些设备节点。我们首先介绍单次采样的读取方法。


  本次测试使用的是ESM7200主板加上ESMARC系列通用评估底板,在评估底板上8路AD信号被引到了CN25(ISA)的端子上,因为ESMARC系列部分主板型号是支持ISA总线的,而ESM7200没有ISA总线,取而代之的是8路AD,具体的定义可参考下表:


信号名称及简要描述CN25信号名称及简要描述
PIN#PIN#

12
AIN_CH134AIN_CH5
AIN_CH256AIN_CH6
AIN_CH378AIN_CH7
AIN_CH4910AIN_CH8

1112

1314

1516

1718

1920GND,模拟地


  客户如果考虑自己设计底板,可以参考表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方案介绍》,用户可以根据自己的习惯选择。


  感兴趣的客户可以联系英创的工程师索要例程的代码。在后续的文章中,我们将介绍低成本方案中如何实现单路的连续采样。

[lablebox]