当前位置:首页 > 嵌入式 > 嵌入式分享
[导读]在嵌入式Linux系统中,USB接口因其即插即用和高带宽特性,成为连接数据采集设备(如ADC模块、传感器阵列)的首选。然而,市面上的通用USB设备未必满足特定采集需求,此时就需要自行开发Linux内核驱动,将自定义USB设备映射为字符设备或输入子系统节点。本文以一款虚构的“8通道12位ADC采集棒”为例,展示从USB设备探测到数据读取的完整驱动开发流程。


在嵌入式Linux系统中,USB接口因其即插即用和高带宽特性,成为连接数据采集设备(如ADC模块、传感器阵列)的首选。然而,市面上的通用USB设备未必满足特定采集需求,此时就需要自行开发Linux内核驱动,将自定义USB设备映射为字符设备或输入子系统节点。本文以一款虚构的“8通道12位ADC采集棒”为例,展示从USB设备探测到数据读取的完整驱动开发流程。

USB设备驱动骨架

Linux内核中,USB驱动通过usb_driver结构体注册。核心函数是probe(设备插入时调用)和disconnect(拔出时调用)。驱动需要匹配设备的VID/PID或类代码。

static const struct usb_device_id adc_table[] = {

   { USB_DEVICE(0x1234, 0x5678) },  // 自定义VID/PID

   {} /* 终止 */

};

MODULE_DEVICE_TABLE(usb, adc_table);


static int adc_probe(struct usb_interface *interface,

                    const struct usb_device_id *id) {

   struct usb_device *dev = interface_to_usbdev(interface);

   struct usb_endpoint_descriptor *ep;

   // 查找批量输入端点

   ep = usb_find_bulk_in_endpoint(interface->cur_altsetting);

   if (!ep) return -ENODEV;

   // 保存端点地址、分配urb等

   return 0;

}


static void adc_disconnect(struct usb_interface *interface) {

   // 释放urb、注销设备

}


static struct usb_driver adc_driver = {

   .name = "adc_collector",

   .id_table = adc_table,

   .probe = adc_probe,

   .disconnect = adc_disconnect,

};

module_usb_driver(adc_driver);

数据采集:URB的生命周期

USB请求块(URB)是内核与USB设备交换数据的核心对象。对于批量传输的数据采集设备,通常采用“提交URB → 等待完成 → 处理数据 → 重新提交”的循环模式。

struct adc_dev {

   struct usb_device *udev;

   struct urb *urb;

   unsigned char *buffer;

   size_t buffer_size;

};


static void adc_urb_complete(struct urb *urb) {

   struct adc_dev *dev = urb->context;

   if (urb->status == 0) {

       // 成功接收数据,将buffer传递给用户空间

       // 例如通过wake_up_interruptible唤醒读取进程

       // 然后将数据拷贝到字符设备缓冲区

       process_adc_data(dev, urb->transfer_buffer, urb->actual_length);

   }

   // 重新提交URB以持续采集

   usb_submit_urb(urb, GFP_ATOMIC);

}


static int adc_start_collection(struct adc_dev *dev) {

   dev->urb = usb_alloc_urb(0, GFP_KERNEL);

   dev->buffer = kmalloc(MAX_PACKET_SIZE, GFP_KERNEL);

   usb_fill_bulk_urb(dev->urb, dev->udev,

                     usb_rcvbulkpipe(dev->udev, EP_IN),

                     dev->buffer, MAX_PACKET_SIZE,

                     adc_urb_complete, dev);

   return usb_submit_urb(dev->urb, GFP_KERNEL);

}

用户空间接口:字符设备

为了让应用程序读取采集数据,驱动需要注册一个字符设备,实现read、release等文件操作。

static int adc_open(struct inode *inode, struct file *file) {

   struct adc_dev *dev = container_of(inode->i_cdev, struct adc_dev, cdev);

   file->private_data = dev;

   return 0;

}


static ssize_t adc_read(struct file *file, char __user *user_buf,

                       size_t count, loff_t *ppos) {

   struct adc_dev *dev = file->private_data;

   // 等待URB完成,从环形缓冲区拷贝数据

   wait_event_interruptible(dev->read_wait, dev->data_ready);

   copy_to_user(user_buf, dev->ring_buffer, min(count, dev->data_len));

   dev->data_ready = 0;

   return min(count, dev->data_len);

}


static const struct file_operations adc_fops = {

   .owner = THIS_MODULE,

   .open = adc_open,

   .read = adc_read,

   .release = adc_release,

};

在probe函数中调用cdev_init和cdev_add,并在disconnect中移除。

编译与测试

将驱动源码放入内核树drivers/usb/misc,修改Kconfig和Makefile。编译后加载模块:

insmod adc_collector.ko

lsusb -d 1234:5678  # 确认设备被识别

cat /dev/adc0 | hexdump  # 读取原始数据

使用usbmon或usbhid-dump调试USB事务:

modprobe usbmon

cat /sys/kernel/debug/usb/usbmon/0u | grep 1234:5678

写在最后

开发自定义USB数据采集设备驱动的核心流程可概括为:匹配设备 → 找到端点 → 分配URB → 提交批量传输 → 在完成回调中处理数据 → 通过字符设备交付用户空间。掌握了这套模式,你就可以将任意USB接口的传感器、采集卡无缝集成到嵌入式Linux系统中。当你的项目需要一个“即插即用”的高速数据通道时,内核USB驱动就是那把打开硬件之门的钥匙。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

高通道数的数据采集(DAQ)系统对性能、同步和可扩展性提出了严格要求。为应对此类挑战,日益需要半导体技术提供商与平台开发者加强合作。本文介绍一种基于Red Pitaya STEMlab平台的96通道高速DAQ系统,由AD...

关键字: 数据采集 DAQ系统 FPGA

数据采集(DAQ)系统广泛应用于工业测控、信号监测、设备测试等领域,系统内部包含 ADC、运算放大器、FPGA、微控制器、传感器等多种器件,不同子系统对电源轨、负载电流、纹波噪声有着差异化要求。电源的稳定性直接决定采集数...

关键字: 数据采集 分立电源 无源器件

在工业自动化转型升级的进程中,大量传统工业设备仅配备RS485、RS232等串口通信接口,这类设备通信距离短、组网能力弱、无法联网,长期存在数据孤岛问题,难以适配智能制造、远程运维、集中管控的生产需求。串口转发网关作为工...

关键字: 网关 串口 数据采集

在工业物联网、智能制造飞速落地的当下,数据是工业生产数字化转型的核心命脉,而稳定、高效、精准的数据采集与传输,是实现设备监控、智能运维、数据分析与决策的基础前提。传统工业数据传输模式多依赖有线光纤、宽带组网,存在布线繁琐...

关键字: 智能网关 数据采集 数据链路

当下人工智能、物联网、高频探测、工业高精度采集技术飞速迭代,社会与产业全面进入数据饥渴时代。各类电子系统不再满足于基础的数据采集与传输,而是追求海量、高速、高精度、高保真的原始数据。信号链作为电子系统的数据源头,承担着信...

关键字: 信号链 数据采集 噪声抑制

在本项目中,您将学习如何使用Arduino Uno和Python构建一个低成本的多通道数据采集(DAQ)系统。该系统可实时采集多个通道的传感器数据,并自动将测量结果保存到CSV(逗号分隔值)文件中,便于在电子表格软件或其...

关键字: 数据采集 Arduino LM35传感器

工业物联网(IIoT)传感器是智能制造、工业自动化、智慧工厂的数据采集终端,长期运行在高压干扰、电压波动、潮湿粉尘、电磁辐射复杂工况中。传感器作为精密弱电设备,对供电稳定性、安全性、抗干扰性要求极高,普通非隔离电源极易出...

关键字: 物联网 传感器 数据采集

在数字化转型全面推进的当下,物联网已深度渗透工业生产、智慧城市、智能家居、医疗监测等诸多领域,而数据采集作为物联网体系的核心入口,其真实性、安全性、实时性与完整性,直接决定了大数据分析、智能决策与自动化控制的最终成效。传...

关键字: 物联网 数据采集 数字化

在工业数字化、智能制造转型过程中,工业数据采集网关是设备联网、数据上云、远程运维的核心枢纽。网关的通信方式直接决定了数据传输的稳定性、实时性、部署成本与适用场景,目前主流的通信方案分为以太网、WIFI、4G、5G四种。很...

关键字: 数据采集 网关 通信

随着工业物联网、智慧家居、智慧城市等领域的快速迭代,各类智能终端、传感设备、工控设备得到大规模普及。不同品牌、不同类型的设备往往采用专属通信协议与数据格式,Modbus、CAN、OPC UA、HTTP、CoAP等数十种协...

关键字: 网关 数据采集 物联网
关闭