Linux下国产CH343驱动实战:从编译到自启动的完整指南

张开发
2026/4/18 20:09:36 15 分钟阅读

分享文章

Linux下国产CH343驱动实战:从编译到自启动的完整指南
1. 初识CH343为什么选择这款国产USB转串口芯片第一次接触CH343是在去年做工业网关项目的时候。当时我们需要在嵌入式板卡上扩展4个高速串口市面上常见的CP210x、FT232这些进口芯片要么价格翻倍要么交期长达半年。偶然看到沁恒微电子的CH343芯片实测下来发现这真是个宝藏国产芯片——波特率支持到6Mbps外围电路只需要两个电容最重要的是价格只有进口芯片的三分之一。CH343本质上是一个USB转高速串口的桥接芯片和常见的CH340系列算是同门师兄弟。但它的性能提升非常明显最高波特率从CH340的2Mbps提升到6Mbps内置的128字节FIFO缓冲区也让大数据量传输更稳定。我在做Modbus RTU转TCP网关时用CH343连接电力仪表115200波特率下连续工作72小时没有出现任何数据丢失。2. 驱动获取与编译手把手教你适配内核2.1 驱动源码获取的正确姿势官方驱动仓库在GitHub上维护得挺勤快建议直接克隆最新版本git clone https://github.com/WCHSoftGroup/ch343ser_linux.git这里有个坑要注意不同内核版本可能需要特定分支的驱动。比如我们项目用的4.19内核直接编译main分支会报错。后来发现要切换到legacy-kernel4.x分支才适配。建议先git branch -a查看所有分支选择最接近你内核版本的。2.2 编译前的内核准备编译驱动最头疼的就是内核头文件匹配问题。我建议直接用当前运行中的内核源码来编译KERNELDIR/lib/modules/$(uname -r)/build如果遇到Module.symvers not found错误说明你的系统可能没装内核开发包。在Ubuntu上可以这样解决sudo apt install linux-headers-$(uname -r)2.3 Makefile的定制化修改官方Makefile默认配置可能不适合你的环境这几个参数建议检查# 修改为你实际的内核路径 KERNELDIR ? /home/yourname/linux-5.10 # 交叉编译时需要指定架构和工具链 ARCH ? arm CROSS_COMPILE ? arm-linux-gnueabihf-特别提醒在嵌入式环境编译时一定要确认KERNELDIR指向的是配套的内核源码树而不是主机上的内核。我有次不小心用x86的内核编译arm驱动浪费了半天时间排查。3. 驱动加载的两种实战方案3.1 动态加载快速验证的利器编译成功后你会得到ch343.ko文件测试加载最安全的方式是sudo insmod ch343.ko dmesg | tail -20 # 查看内核日志确认加载情况如果看到ch343: USB Serial support registered就说明成功了。不过这里有个隐藏知识点现代Linux内核默认会优先加载CDC-ACM驱动导致CH343可能无法独占设备。解决方法是在加载前先卸载冲突驱动sudo modprobe -r cdc_acm3.2 静态编译生产环境的稳妥选择对于量产设备我更推荐把驱动编译进内核。具体步骤将驱动源码复制到内核的drivers/usb/serial/目录修改同目录下的Kconfig添加config USB_SERIAL_CH343 tristate CH343 USB to serial converter depends on USB_SERIAL help Say Y here if you want to use the CH343 USB serial adapter.在Menuconfig中启用该选项make menuconfig # 找到 Device Drivers - USB support - USB Serial Converter support - CH343 USB to serial converter4. 开机自启动的完整解决方案4.1 传统方法/etc/modules的局限很多教程会告诉你在/etc/modules里添加模块名像这样echo ch343 | sudo tee -a /etc/modules但实际在嵌入式系统中这个方法有两个问题模块加载顺序不可控CDC驱动可能还是优先加载某些精简版系统可能没有这个文件4.2 更可靠的systemd方案我推荐用systemd服务来确保加载顺序# /etc/systemd/system/ch343-driver.service [Unit] DescriptionLoad CH343 Driver Beforeserial-gettyttyUSB0.service Aftersyslog.target [Service] Typeoneshot ExecStart/sbin/modprobe ch343 ExecStartPost/bin/sleep 1 # 给设备枚举留出时间 [Install] WantedBymulti-user.target然后启用服务sudo systemctl enable ch343-driver.service这个方案的优点是能精确控制加载时机还能配合udev规则自动创建设备节点。5. 实际应用中的排坑指南5.1 设备节点权限问题新插入的CH343设备通常会是/dev/ttyUSBx但普通用户可能没权限访问。永久解决方案是创建udev规则# /etc/udev/rules.d/99-ch343.rules SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}55d4, MODE0666更新规则后记得重新加载sudo udevadm control --reload-rules sudo udevadm trigger5.2 高速传输的缓冲区优化当波特率超过1Mbps时建议调整内核缓冲区参数sudo stty -F /dev/ttyUSB0 6000000 sudo sysctl -w net.core.rmem_max4194304 sudo sysctl -w net.core.wmem_max4194304在代码中也需要相应设置struct serial_struct serinfo; ioctl(fd, TIOCGSERIAL, serinfo); serinfo.flags | ASYNC_LOW_LATENCY; ioctl(fd, TIOCSSERIAL, serinfo);5.3 多设备同时工作的技巧当连接多个CH343设备时可以通过绑定物理端口来固定设备名。首先查看设备路径udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)然后创建基于端口号的规则# /etc/udev/rules.d/98-ch343-by-port.rules SUBSYSTEMtty, KERNELS1-1.2:1.0, SYMLINKttyCH343_0 SUBSYSTEMtty, KERNELS1-1.3:1.0, SYMLINKttyCH343_16. 进阶应用GPIO和硬件流控虽然CH343主打串口功能但它其实还支持GPIO控制。通过ioctl可以操作这些引脚#define CH343_GPIO_NUM 4 // CH343有4个GPIO // 获取GPIO状态 ioctl(fd, CH343_IOCTL_GET_GPIO, gpio_state); // 设置GPIO方向为输出 gpio_config.direction CH343_GPIO_OUT; ioctl(fd, CH343_IOCTL_SET_GPIO_DIR, gpio_config); // 输出高电平 gpio_value.index 0; // GPIO0 gpio_value.value 1; ioctl(fd, CH343_IOCTL_SET_GPIO_VALUE, gpio_value);硬件流控的配置也很重要特别是在工业环境中struct termios options; tcgetattr(fd, options); options.c_cflag | CRTSCTS; // 启用RTS/CTS流控 tcsetattr(fd, TCSANOW, options);最近在做一个光伏逆变器监控项目就是靠CH343的硬件流控功能稳定实现了115200波特率下7x24小时不间断通信。相比之前用过的某进口芯片国产CH343在长线传输时的抗干扰表现反而更出色。

更多文章