Industrial I/O (IIO) 深度解析Linux 内核的传感器框架一、IIO 是什么Industrial I/O (IIO) 是 Linux 内核中一个专门用于传感器和转换器的子系统框架。它提供了一套标准化的接口用于连接和管理各类工业级传感器包括但不限于运动传感器加速度计、陀螺仪、磁力计环境传感器温度、湿度、气压、光照化学传感器气体检测、pH值传感器生物传感器心率监测、血氧饱和度转换器ADC模数转换器、DAC数模转换器IIO 的设计目标是解决嵌入式系统中传感器集成碎片化的问题。在 IIO 出现之前传感器驱动分散在内核各处input、hwmon、misc等导致用户空间访问接口不统一驱动程序重复开发缺乏高级功能支持如硬件缓冲、事件处理二、IIO 架构设计内核空间架构内核空间物理传感器IIO 设备驱动IIO 核心层IIO 子系统接口用户空间硬件中断硬件触发缓冲区管理事件处理通道管理核心组件IIO 设备驱动与物理硬件交互IIO 核心提供注册、缓冲区、事件等基础设施IIO 触发器控制数据采集时机IIO 缓冲区批量数据存储IIO 通道传感器数据通道抽象三、IIO 用户空间接口IIO 通过多种方式向用户空间提供访问接口1. Sysfs 接口路径/sys/bus/iio/devices//sys/bus/iio/devices/ ├── iio:device0 │├── name │├── in_accel_x_raw │├── in_accel_y_raw │├── in_accel_z_raw │├── in_accel_scale │├── in_temp_raw │├── in_temp_offset │└── triggers └── iio_sysfs_trigger └── trigger0常用属性*_raw原始传感器数据*_scale比例因子将原始值转换为工程单位*_offset校准偏移量sampling_frequency采样频率2. 字符设备接口路径/dev/iio:deviceX用于高效读取缓冲数据支持 poll/select 异步通知直接访问原始二进制数据3. Debugfs 接口路径/sys/kernel/debug/iio/提供调试信息显示设备注册状态查看缓冲区使用情况四、IIO 核心概念详解1. 通道Channels通道是 IIO 的基本数据单元代表传感器的单个测量值。每个通道有以下属性属性描述示例类型测量类型accel, gyro, temp索引通道索引x, y, z 或 0,1,2修饰符附加信息ambient, ir, processed通道类型示例代码staticconststructiio_chan_specbme280_channels[]{{.typeIIO_TEMP,.info_mask_separateBIT(IIO_CHAN_INFO_RAW)|BIT(IIO_CHAN_INFO_SCALE),.scan_index0,.scan_type{.signs,.realbits14,.storagebits16,.shift2,},},{.typeIIO_PRESSURE,.info_mask_separateBIT(IIO_CHAN_INFO_RAW)|BIT(IIO_CHAN_INFO_SCALE),.scan_index1,// ...},// ...};2. 触发器Triggers触发器决定数据采集的时机触发类型描述典型应用软件触发按需采集用户空间控制硬件触发外部事件触发中断驱动采集定时触发周期性采集连续监测创建硬件触发示例staticirqreturn_tsensor_trigger_handler(intirq,void*p){structiio_poll_func*pfp;structiio_dev*indio_devpf-indio_dev;// 读取传感器数据read_sensor_data();// 通知 IIO 核心iio_push_to_buffers(indio_dev,sensor_data);returnIRQ_HANDLED;}3. 缓冲区Buffers用于高效处理批量数据硬件内核用户空间硬件内核用户空间loop[数据采集]打开 /dev/iio:deviceX设置缓冲区大小启用通道启动缓冲区硬件中断读取传感器数据填充缓冲区数据可用通知读取数据五、IIO 设备驱动开发1. 设备注册流程staticintsensor_probe(structplatform_device*pdev){structiio_dev*indio_dev;structsensor_data*data;// 分配 IIO 设备indio_devdevm_iio_device_alloc(pdev-dev,sizeof(*data));if(!indio_dev)return-ENOMEM;dataiio_priv(indio_dev);// 初始化设备indio_dev-namemy-sensor;indio_dev-infosensor_info;indio_dev-channelssensor_channels;indio_dev-num_channelsARRAY_SIZE(sensor_channels);indio_dev-modesINDIO_DIRECT_MODE|INDIO_BUFFER_TRIGGERED;// 配置硬件sensor_hw_init(data);// 注册设备returndevm_iio_device_register(pdev-dev,indio_dev);}2. 核心数据结构iio_info 结构体staticconststructiio_infosensor_info{.read_rawsensor_read_raw,.write_rawsensor_write_raw,.read_event_configsensor_read_event_config,.write_event_configsensor_write_event_config,.validate_triggersensor_validate_trigger,};iio_dev 结构体structiio_dev{conststructiio_info*info;// 操作函数集structiio_buffer*buffer;// 数据缓冲区structlist_headtrig_list;// 触发器列表conststructiio_chan_spec*channels;// 通道定义intnum_channels;// 通道数量unsignedlongmodes;// 工作模式// ...};六、IIO 用户空间编程1. 使用 sysfs 读取数据# 查看可用设备$ls/sys/bus/iio/devices/ iio:device0iio:device1trigger0# 读取温度值$cat/sys/bus/iio/devices/iio:device0/in_temp_raw24560$cat/sys/bus/iio/devices/iio:device0/in_temp_scale0.03125# 计算实际温度24560 * 0.03125 767.5 m°C2. 使用 libiio 库编程#includeiio.hintmain(){// 创建上下文structiio_context*ctxiio_create_default_context();// 查找设备structiio_device*deviio_context_find_device(ctx,bme280);// 查找通道structiio_channel*temp_chaniio_device_find_channel(dev,temp,false);// 读取数据floattemp;iio_channel_attr_read_float(temp_chan,raw,temp);// 应用校准floatscale,offset;iio_channel_attr_read_float(temp_chan,scale,scale);iio_channel_attr_read_float(temp_chan,offset,offset);floatcalibratedtemp*scaleoffset;printf(Temperature: %.2f°C\n,calibrated);iio_context_destroy(ctx);return0;}3. 高级特性缓冲数据采集// 设置缓冲区structiio_buffer*bufiio_device_create_buffer(dev,1024,false);// 启用通道iio_channel_enable(temp_chan);iio_channel_enable(humidity_chan);// 开始采集iio_buffer_refill(buf);// 阻塞等待数据// 处理数据void*start,*end;ptrdiff_tstep;iio_buffer_step(buf,step);iio_buffer_start(buf,start);iio_buffer_end(buf,end);for(void*ptrstart;ptrend;ptrstep){int16_t*dataptr;floattempdata[0]*0.03125;floathumiditydata[1]*0.001;// ...}七、IIO 高级功能1. 事件检测支持阈值、运动检测等事件// 设置阈值事件echo1000/sys/bus/iio/devices/iio:device0/events/in_accel_x_thresh_rising_value// 监听事件structiio_event_dataevent;while(read(event_fd,event,sizeof(event))0){if(event.idIIO_EV_CODE_ACCEL_X_THRESH){printf(X-axis threshold exceeded!\n);}}2. 硬件滤波配置传感器内置滤波器# 查看可用滤波器$cat/sys/bus/iio/devices/iio:device0/filter_low_pass_3db_frequency_available0.1131030100# 设置滤波器echo10/sys/bus/iio/devices/iio:device0/filter_low_pass_3db_frequency3. 多设备同步使用硬件触发器同步多个传感器# 创建触发器echo100/sys/bus/iio/devices/trigger0/sampling_frequency# 绑定设备到触发器echotrigger0/sys/bus/iio/devices/iio:device0/trigger/current_triggerechotrigger0/sys/bus/iio/devices/iio:device1/trigger/current_trigger八、IIO 工具集工具名称功能描述示例用法iio_info查看设备信息iio_info -u local:iio_readdev读取设备数据iio_readdev -b 1024 iio:device0iio_writedev写入设备数据iio_writedev -s 0.5 iio:device0 voltage0iio_attr操作设备属性iio_attr -c iio:device0 in_accel_x scaleiio_event_monitor监视 IIO 事件iio_event_monitor -n iio:device0九、IIO 在嵌入式系统中的应用案例1. 无人机飞行控制器IIOIIOIIOIMU 传感器Flight Controller气压计GPS飞行控制算法电机控制器传感器配置加速度计200Hz 采样率陀螺仪8kHz 采样率使用硬件触发器同步采样2. 工业环境监测// 创建多传感器监测系统structiio_context*ctxnetwork_context_create(192.168.1.100);// 分布式传感器列表constchar*sensors[]{floor1-temp,floor1-humidity,floor2-temp,floor2-humidity,outside-temp,outside-pressure};// 批量读取数据for(inti0;iARRAY_SIZE(sensors);i){structiio_device*deviio_context_find_device(ctx,sensors[i]);// 读取并处理数据}十、IIO 最佳实践通道设计原则每个物理量使用独立通道提供原始数据和工程单位转换明确定义数据精度和范围性能优化使用 DMA 缓冲区减少 CPU 开销启用传感器硬件滤波合理设置采样率平衡功耗与性能电源管理// 实现挂起/恢复回调staticconststructdev_pm_opssensor_pm_ops{.suspendsensor_suspend,.resumesensor_resume,};调试技巧# 启用 IIO 调试echo1/sys/module/iio/parameters/debug# 查看内核日志dmesg|grepiio总结IIO 子系统为 Linux 生态系统提供了强大的传感器集成能力统一框架标准化各类传感器接口灵活架构支持从简单数据读取到高速流处理丰富工具提供完整的用户空间工具链跨平台从微控制器到服务器级系统均可使用“IIO 是 Linux 传感器领域的通用语言它将硬件多样性与软件统一性完美结合。掌握 IIO意味着你能让任何传感器在 Linux 系统中‘开口说话’。” —— Jonathan Cameron, IIO 维护者通过本文您已全面了解IIO 架构与核心概念驱动开发与用户空间编程高级特性与优化技巧实际应用场景与最佳实践这些知识将帮助您在嵌入式系统和物联网项目中高效集成各类传感器设备。