基于Linux IIO接口的波形采集

        我们在《Linux IIO接口的低成本8通道AD》这篇文章中,已经介绍了如何通过程序对IIO设备进行单次读取,接下来我们就介绍波形的实现,关于IIO子系统的详细说明可以参考资料Linux Industrial I/O Subsystem

        本次测试采用的平台是ESM6800a主板加上ESMARC通用评估底板,波形采集要求AD能够进行等时的连续采样,在IIO子系统的部分需要有较多的设置,所以推荐直接使用ADI公司提供的libiio库,这个库文件抽象了和硬件相关的底层细节,并提供了简单而完整的编程接口,可以省去很多和硬件相关的设置,英创公司已经将libiio移植到了ESM7200主板上。

        ESM6800A主板的AD是CPU内部自带的资源,在硬件上只能够支持单通道的连续采集,并且最高的速率能够达到58kSPS。在ESM6800A主板中,提供了8路AD资源,用户可以指定任意一路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_raw6支持
E9AIN_CH8/sys/bus/iio/devices/iio:device0/ in_voltage9_raw7支持

表1

        同时因为受到CPU内部时钟分频的限制,所以ESM6800A连续采样的速率只能够支持几个特定的值,可参考下表:

支持频率(KHz)5809829676150007541

表2        

关于ESM6800A主板和ESMARC通用评估底板的管脚定义介绍,请参考文章《Linux IIO接口的低成本8通道AD》中的表1和表2。

        整个程序的基本流程如下:

        下面就是具体的代码,首先是获取IIO设备,代码如下:

static struct iio_context *ctx;  
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;  
} 

        在IIO子系统中,在连续采样时,会分配一个可自定义长度的环形缓冲区,这个缓冲区需要一个触发(trigger)才能够使用。这里我们可以通过软件模拟创建一个trigger,通过下面的命令就可以创建一个软件模拟的trigger:

echo 1 > /sys/bus/iio/devices/iio_sysfs_trigger/add_trigger

        在ESM6800A主板启动后,输入一次这个命令即可,可以通过英创公司提供的自启动脚本来执行。

        创建好trigger后,就可以在程序中为IIO设备指定这个trigger了,libiio提供的API可以获取创建的trigger并设置到对应的IIO设备中:

static const char *trigger_name = "sysfstrig1";  
struct iio_device *trigger;  
  
/* 获取trigger并设置 */  
if (trigger_name) {  
    struct iio_device *trigger = iio_context_find_device(  
        ctx, trigger_name);  
    if (!trigger) {  
        fprintf(stderr, "Trigger %s not found\n", trigger_name);  
        iio_context_destroy(ctx);  
        return EXIT_FAILURE;  
}  
  
    if (!iio_device_is_trigger(trigger)) {  
        fprintf(stderr, "Specified device is not a trigger\n");  
        iio_context_destroy(ctx);  
        return EXIT_FAILURE;  
    }  
  
    ret = iio_device_set_trigger(dev, trigger);  
    if (ret < 0) {  
        char buf[256];  
        iio_strerror(-(int)ret, buf, sizeof(buf));  
        fprintf(stderr, "set trigger failed : %s\n", buf);  
    }  
} 

        然后就需要获取我们要采集的通道(channel),并使能连续采集。因为ESM6800A主板只支持单通道的连续采集,所以这里我们只选择一路来使能:

struct iio_channel *ch;  
  
/* 使能对应的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;  
}  
iio_channel_enable(ch); 

        设置采样的速率,ESM6800A主板上只能够设置几种固定的频率,可参考表2:

int sample_freq[4] = {58098, 29676, 15000, 7541};  
  
/* 设置采样频率,因为分频的原因,只能提供几组固定的采样频率 
 * 可以参考sample_freq变量 
 * */  
freq = malloc(10);  
sprintf(freq, "%d", sample_freq[0]);  
ret = iio_channel_attr_write(ch, attr, freq);  
if (ret <= 0) {  
    printf("ERROR: while writing '%s' with '%s'\n",  
        attr, freq);  
} 

        创建一个环形缓冲区用于存储连续采集的数据,环形缓冲区的大小根据实际情况自行修改,测试代码中设置为1024:

unsigned int buffer_size = 1024;  
  
/* 创建一个和指定IIO设备关联的数据缓冲区 */  
buffer = iio_device_create_buffer(dev, buffer_size, false);  
if (!buffer) {  
    char buf[256];  
    iio_strerror(errno, buf, sizeof(buf));  
    fprintf(stderr, "Unable to allocate buffer: %s\n", buf);  
    iio_context_destroy(ctx);  
    return EXIT_FAILURE;  
} 

        在读取数据之前,我们需要先确定需要读取的通道的样本大小,以方便我们来判断缓冲区内的数据,是否均为需要的样本数据:

/* 获取IIO设备中当前样本长度,因为AD的精度为12位,获取到的值应该为2(byte) */  
sample_size = iio_device_get_sample_size(dev);  
/* Zero isn't normally an error code, but in this case it is an error */  
if (sample_size == 0) {  
    fprintf(stderr, "Unable to get sample size, returned 0\n");  
    iio_context_destroy(ctx);  
    return EXIT_FAILURE;  
} else if (sample_size < 0) {  
    char buf[256];  
    iio_strerror(errno, buf, sizeof(buf));  
    fprintf(stderr, "Unable to get sample size : %s\n", buf);  
    iio_context_destroy(ctx);  
    return EXIT_FAILURE;  
} 

        接下来就可以开始读取数据了,读取的时候可以指定需要读取的数据长度。读取的数据可以根据实际的需求进行处理,比如保存到文件中,例子中是直接通过fwrite将数据写到stdout中,其实就是直接打印到串口终端中:

/* 主循环,读取数据和处理 */  
while(app_running) {  
    /*  获取通道更多样本 */  
    ret = iio_buffer_refill(buffer);  
    if (ret < 0) {  
        if (app_running) {  
            char buf[256];  
            iio_strerror(-(int)ret, buf, sizeof(buf));  
            fprintf(stderr, "Unable to refill buffer: %s\n", buf);  
            break;  
        }  
    }  
  
    /* 获取channel中两个sample之间的长度,并判断和IIO设备的sample_size是否相等 
     * 如果相等,说明全部是需要的样本,直接读取 
     * 如果不相等,说明存在其他数据,需要单独解析处理 
     * */  
    if (iio_buffer_step(buffer) == sample_size) {  
        /* 获取buffer中的起始地址和结束地址,并计算数据长度 */  
        void *start = iio_buffer_start(buffer);  
        size_t read_len, len = (intptr_t) iio_buffer_end(buffer)  
        - (intptr_t) start;  
  
        if (num_samples && len > num_samples * sample_size)  
            len = num_samples * sample_size;  
  
        /* 数据处理,这里通过fwrite函数将数据直接输出到stdout中 
         * 用户可以根据实际的情况进行处理,比如写入到记录文件中 
         * */  
        for (read_len = len; len; ) {  
            size_t nb = fwrite(start, 1, len, stdout);  
            if (!nb)  
                goto err_destroy_buffer;  
  
            len -= nb;  
            start = (void *)((intptr_t) start + nb);  
        }  
  
        /* 读取了指定长度(num_samples)的数据后,释放资源并退出 */  
        if (num_samples) {  
            num_samples -= read_len / sample_size;  
        if (!num_samples)  
            quit_all(EXIT_SUCCESS);  
    }  
    else {  
        /* 如果channel存在其他数据,只能进行单独处理,一个一个样本的读取 
         * 并通过回调函数print_sample来处理,同样回调函数中也只是通过fwrite函数 
         * 将数据输出到sdtout中,用户可以根据自己的需求修改 
         * */  
        ret = iio_buffer_foreach_sample(buffer, print_sample, NULL);  
        if (ret < 0) {  
            char buf[256];  
            iio_strerror(-(int)ret, buf, sizeof(buf));  
            fprintf(stderr, "buffer processing failed : %s\n", buf);  
        }  
    }  
}    

        在实际测试中,我们接入了一个频率为1KHz,幅度为0-3.3V的正弦波,使用程序采样了1024个点存入了文件中,然后使用gnuplot软件绘制波形如下:

        多通道和单通道的连续采集在软件上是类似的,区别只在于使能的通道数量不一样。英创公司也即将推出支持基于IIO(Industrial I/O)子系统的多通道连续采样的主板,我们将在后续的文章中继续介绍。

        感兴趣的客户可以联系英创的工程师索要例程的代码。 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 全志Linux IIO(Industrial I/O)是全志科技公司为其系统-on-chip(SoC)芯片设计的一个功能丰富的子系统。它提供了一套用于处理从各种传感器设备读取和控制数据的框架和驱动程序。 IIO子系统的主要目的是使Linux系统能够与各种传感器进行交互。这些传感器可以是温度传感器、光传感器、加速度计、罗盘、湿度传感器等。IIO框架为传感器的数据读取、数据转换(如ADC和DAC)、数据传输和保存等提供了一致性接口和库。 全志的Linux IIO提供了一套强大和丰富的驱动程序集合,以支持其在不同SoC芯片上集成的各种传感器和输入/输出设备。这些驱动程序集合可以用于从这些传感器读取数据,控制设备参数和提供高性能数据流。 尽管全志的Linux IIO是为全志公司的特定芯片设计的,但它也兼容其他Linux平台,并且可以在其他SoC芯片上使用。这使得开发人员能够简化传感器驱动开发和移植,从而更快地将其应用于不同的嵌入式系统项目。 总之,全志Linux IIO是一个重要的子系统,使得开发人员能够轻松地与各种传感器设备进行通信和控制。它为传感器数据读取和设备参数控制提供了一个统一且可靠的接口,同时也为传感器驱动程序的开发和移植提供了便利。 ### 回答2: 全志Linux IIO是处理器芯片制造商全志科技公司发布的一套用于Linux系统的传感器支持框架。IIO全称为Industrial Input/Output子系统,是Linux内核的一个功能子系统,用于处理与外部硬件设备的数据输入和输出。 全志Linux IIO主要用于支持嵌入式系统中的传感器设备,如加速度计、陀螺仪、光学传感器等,以及一些特殊的外设设备,如电压电流传感器等。通过全志Linux IIO开发者可以很方便地将各种传感器设备连接到嵌入式系统中,并实现数据的输入和输出。 使用全志Linux IIO开发者可以通过一系列的API函数来配置和控制传感器设备。这些API函数包括设备的初始化、传感器数据采集、设备的校准、数据的处理和传输等。全志Linux IIO提供了一套统一的接口,使得开发者可以方便地操作各种不同类型的传感器设备。 全志Linux IIO的优势在于其兼容性和灵活性。它可以运行在多种不同的处理器架构上,并且支持多种不同的传感器设备。开发者可以根据具体需求选择合适的传感器设备,并根据自己的需求调整和配置设备参数。 总之,全志Linux IIO是一套用于Linux系统的传感器支持框架,它使得开发者可以方便地接入和控制各种传感器设备,实现数据采集和处理。它的灵活性和兼容性使得开发者可以根据具体需求选择合适的传感器设备,并进行相应的配置和控制。 ### 回答3: 全志Linux IIO是全志科技开发的一种用于嵌入式系统的开源软件平台。IIO代表了"Industry Input/Output",指的是从不同的物理量传感器(包括温度、压力、湿度等)获取数据,并将其传输到嵌入式系统中。 全志Linux IIO遵循Linux内核的架构,并提供一系列的驱动程序和库,使得开发者能够轻松地与各种传感器进行通信。它提供了一个统一的接口,使得开发者可以使用相同的API来读取多个不同类型的传感器的数据。这种模块化的设计让开发者能够快速添加、更新或替换传感器,且不需要对底层软件进行太多修改。 通过使用全志Linux IIO,嵌入式系统可以方便地监测和控制各种物理量,并将其应用于各种领域,例如工业自动化、智能家居、物联网等。开发者可以通过编写简单的程序来获取传感器数据,并根据需要进行进一步处理和分析。 此外,全志Linux IIO还支持一些高级功能,例如采样率控制、数据滤波和事件触发等。这些功能可以帮助开发者优化系统性能,并提高传感器数据的准确性和可靠性。 总而言之,全志Linux IIO是一个强大的开源软件平台,为开发者提供了丰富的工具和接口,使他们能够轻松地与各种传感器进行集成和交互。它为嵌入式系统的开发和应用带来了便利和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值