4. Windows/Linux USB驱动开发环境搭建
说实话,做USB开发这么多年,我踩过最多的坑就是环境搭建。明明代码逻辑没问题,结果因为驱动装不对、库版本不匹配,折腾一整天。今天咱们就把这事彻底理清楚。
这一章,我会带你搞定三件事:Windows上用WinUSB或libusb、Linux上用libusb、交叉编译工具链配置。最后咱们写一个USB设备枚举程序,验证环境是否OK。
4.1 Windows环境:WinUSB vs libusb
Windows下做USB开发,主流方案就两个:WinUSB和libusb。我个人习惯是这样选的——
| 对比项 | WinUSB | libusb |
|---|---|---|
| 安装方式 | 系统自带驱动,需修改INF | 需安装libusb驱动(Zadig工具) |
| API风格 | Win32 API,较底层 | 跨平台统一API,更友好 |
| 热成像场景 | 适合批量传输、控制传输 | 同样支持,且代码可移植到Linux |
| 我的推荐 | 产品级项目 | 原型验证、教学、跨平台 |
4.2 Windows下安装libusb(推荐方案)
步骤很简单,跟着走就行:
- 下载Zadig工具(zadig.akeo.ie)—— 这是装libusb驱动的神器
- 插入你的USB设备(比如热成像相机)
- 打开Zadig,在Options里勾选"List All Devices"
- 选择你的设备,在Driver栏选"libusb-win32"或"WinUSB"
- 点击Install Driver,等几秒就搞定
装好之后,用libusb的示例程序测试一下。代码我放在后面,先别急。
4.3 Linux环境:libusb原生支持
Linux下就省心多了。libusb是系统自带的,或者一行命令安装:
sudo apt-get install libusb-1.0-0-dev # Ubuntu/Debian
sudo yum install libusb-devel # CentOS/RHEL
然后记得给USB设备加权限。不然你运行程序时会报"permission denied"。
# 创建一个udev规则文件
sudo vim /etc/udev/rules.d/99-thermal-camera.rules
# 内容如下(根据你的设备VID/PID修改)
SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="7523", MODE="0666"
# 重新加载规则
sudo udevadm control --reload-rules
sudo udevadm trigger
嗯,这里要注意:VID和PID是你设备的厂商ID和产品ID。用lsusb命令就能看到。我那个热成像相机的VID是1a86,PID是7523,你换成自己的就行。
4.4 交叉编译工具链配置
如果你是在PC上开发,但最终要部署到ARM板(比如树莓派、RK3588)上,那就需要交叉编译。说白了就是:在x86电脑上编译出ARM能跑的程序。
我常用的配置流程:
- 下载交叉编译工具链:比如gcc-arm-linux-gnueabihf
- 设置环境变量:指定CC、CXX等
- 编译libusb:用交叉编译器重新编译libusb库
- 编译你的程序:链接交叉编译后的libusb
具体命令示例:
# 安装交叉编译工具链
sudo apt-get install gcc-arm-linux-gnueabihf
# 下载libusb源码
wget https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2
tar xvf libusb-1.0.26.tar.bz2
cd libusb-1.0.26
# 配置交叉编译
./configure --host=arm-linux-gnueabihf --prefix=/opt/libusb-arm
# 编译并安装
make
sudo make install
# 编译你的程序(假设源码是usb_enum.c)
arm-linux-gnueabihf-gcc -I/opt/libusb-arm/include -L/opt/libusb-arm/lib \
usb_enum.c -lusb-1.0 -o usb_enum_arm
file usb_enum_arm命令,看输出是不是"ARM"架构。
4.5 第一个USB设备枚举程序
好了,环境搭好了,咱们写个程序验证一下。这个程序会枚举所有USB设备,打印出VID、PID和厂商字符串。
#include <stdio.h>
#include <libusb-1.0/libusb.h>
int main() {
libusb_device **devs;
libusb_device_handle *handle = NULL;
ssize_t cnt;
int i, ret;
char str[256];
// 1. 初始化libusb
ret = libusb_init(NULL);
if (ret < 0) {
fprintf(stderr, "初始化失败: %s\n", libusb_error_name(ret));
return 1;
}
// 2. 获取设备列表
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0) {
fprintf(stderr, "获取设备列表失败\n");
return 1;
}
printf("找到 %zd 个USB设备:\n", cnt);
// 3. 遍历每个设备
for (i = 0; i < cnt; i++) {
struct libusb_device_descriptor desc;
ret = libusb_get_device_descriptor(devs[i], &desc);
if (ret < 0) continue;
printf("设备 %d: VID=0x%04X, PID=0x%04X, 类=0x%02X\n",
i, desc.idVendor, desc.idProduct, desc.bDeviceClass);
// 尝试打开设备获取字符串描述符
ret = libusb_open(devs[i], &handle);
if (ret == 0) {
if (desc.iManufacturer > 0) {
ret = libusb_get_string_descriptor_ascii(handle,
desc.iManufacturer, (unsigned char*)str, sizeof(str));
if (ret > 0)
printf(" 厂商: %s\n", str);
}
if (desc.iProduct > 0) {
ret = libusb_get_string_descriptor_ascii(handle,
desc.iProduct, (unsigned char*)str, sizeof(str));
if (ret > 0)
printf(" 产品: %s\n", str);
}
libusb_close(handle);
}
}
// 4. 清理
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}
编译命令:
# Windows (MinGW或MSVC)
gcc usb_enum.c -lusb-1.0 -o usb_enum.exe
# Linux
gcc usb_enum.c -lusb-1.0 -o usb_enum
# 交叉编译
arm-linux-gnueabihf-gcc usb_enum.c -I/opt/libusb-arm/include \
-L/opt/libusb-arm/lib -lusb-1.0 -o usb_enum_arm
运行后,你会看到类似这样的输出:
找到 5 个USB设备:
设备 0: VID=0x1D6B, PID=0x0002, 类=0x09
厂商: Linux Foundation
产品: xHCI Host Controller
设备 1: VID=0x1A86, PID=0x7523, 类=0xFF
厂商: QinHeng Electronics
产品: USB Serial
看到你的热成像相机了吗?如果能看到VID/PID,说明环境搭建成功,libusb能正常工作了。
lsusb(Linux)或设备管理器(Windows)确认系统是否识别了设备。我遇到过好几次,其实是USB线接触不良。
4.6 本章知识体系
下面这张图帮你理清整个环境搭建的脉络:
说白了,无论你用Windows还是Linux,最终都是通过libusb这套API来操作USB设备。交叉编译只是多了一步工具链配置,核心代码完全一样。
- Windows推荐用libusb + Zadig安装驱动
- Linux用apt安装libusb-dev,配置udev权限
- 交叉编译时注意指定--host和--prefix
- 枚举程序能跑通,说明环境OK
环境搭好了,下一章咱们就可以真正开始操作热成像相机的USB通信了。到时候你会看到,这些基础工作有多重要。
公众号:蓝海资料掘金营,微信deep3321