拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Ubuntu 22.04安装CH343驱动:从内核编译到DKMS自启完全指南

把USB转串口模块插进Ubuntu 22.04的电脑lsusb能看到设备但/dev下死活找不到ttyUSB0dmesg也一声不吭——如果你手里是CH343芯片这个场景我太熟悉了。Ubuntu 22.04默认内核5.15不带CH343的驱动而系统自带的ch341.ko只管CH340/CH341救不了CH343。这篇文章就是我折腾完这一整套流程后的完整记录照着操作从零到驱动加载、开机自启、免sudo访问全部搞定。熟练工做下来真的5分钟新手第一次按步骤走也就十来分钟。1. 插上没反应先弄清楚CH343在Ubuntu 22.04里的真实待遇很多人在Windows下用CH343的USB转串口线插上就识别一点感觉都没有。换到Ubuntu后问题就来了设备明明在lsusb里能看到1a86:55d3但/dev目录下就是没有ttyUSB0用dmesg看内核日志也毫无输出好像设备压根不存在一样。这个现象的本质是Linux内核的USB串口驱动匹配机制决定的。USB转串口芯片要工作必须有一个内核驱动注册对应的USB vendor ID和product ID驱动匹配上之后才会创建/dev/ttyUSBx或/dev/ttyACMx节点。Ubuntu 22.04自带的ch341.ko模块只注册了CH3401a86:7523和CH3411a86:5523这两个PID并没有CH343的1a86:55d3所以即便你手动modprobe ch341内核也根本不会拿它去绑定CH343设备。有人可能想那我等内核更新不就行了实际上Linux内核主线从6.x版本开始陆续加入了对CH343的原生支持但Ubuntu 22.04 LTS默认的5.15内核没有。你不升级内核、不换HWE硬件支持栈的话光靠apt update是不会等到CH343驱动的。而且对生产环境来说为了一个串口芯片去升级整个内核也不现实还是老老实实编译安装官方驱动最稳妥。先做个快速自查确认手上的芯片到底是不是CH343lsusb如果看到Bus 001 Device 003: ID 1a86:55d3 WCH.CN这行那基本可以确定是CH343。常见芯片的PID对照表如下芯片型号USB VID:PIDUbuntu 22.04默认支持情况默认设备节点CH3401a86:7523支持ch341.ko/dev/ttyUSB0CH3411a86:5523支持ch341.ko/dev/ttyUSB0CH3421a86:55d4不支持编译驱动后可见CH3431a86:55d3不支持编译驱动后为/dev/ttyCH343USB0CH91021a86:55d4部分内核支持/dev/ttyACM0或ttyCH343USB0注意CH342和CH343的PID相近单看lsusb输出容易混淆但驱动安装流程一样放心往下走。2. 认准芯片再动手CH343与CH340的驱动亲缘关系和设备名差异CH343是沁恒WCH推出的新一代USB转串口芯片最大波特率支持到6Mbps比CH340的2Mbps高一截还增加了硬件流控、RS485方向控制这些功能近几年在国产开发板上露脸频率越来越高。但恰恰是这颗芯片在Linux下的支持节奏比CH340慢了好几拍导致很多人踩坑。先说一个容易混淆的点CH343和CH340虽然都是沁恒家的但它们的USB通信协议并不相同。CH340使用的是厂商自定义的USB转串口协议Linux内核里专门为它写了ch341.ko而CH343支持两种模式——厂商自定义模式和CDC ACM标准模式。默认出厂配置下CH343跑在厂商自定义模式所以需要单独的ch343.ko驱动来对接。如果你的板子被配置成了CDC ACM模式那情况又不一样系统自带的cdc_acm.ko会直接接管生成的设备节点是/dev/ttyACM0这种情况反而不需要编译任何驱动。判断当前设备跑在什么模式看dmesg输出就知道dmesg | tail -20如果看到类似usb 1-2: ch343 converter now attached to ttyCH343USB0说明被官方驱动接管如果看到cdc_acm 1-2:1.0: ttyACM0: USB ACM device说明走的是标准CDC ACM模式。设备名这块也是个容易误判的点。官方ch343ser_linux驱动编译加载后生成的设备节点不是常见的/dev/ttyUSB0而是/dev/ttyCH343USB0。我第一次装完驱动习惯性地去ls /dev/ttyUSB*结果什么都没有还以为是驱动没加载成功后来才反应过来是这个命名差异。ls -l /dev/ttyCH343USB*当然如果你对设备名有强迫症可以改驱动源码里的设备名定义把ttyCH343USB改成ttyUSB然后重新编译。但我个人不建议这么做因为ttyUSB0这个名字太容易和CH340、CP2102、FTDI这些设备的节点混淆尤其是多设备共存的时候还不如用CH343专属命名来得清爽。3. 编译安装全流程从下载官方驱动到ttyCH343USB0出现在/dev下既然内核不自带那就自己动手。WCH官方提供了ch343ser_linux驱动源码支持Linux内核2.6.x到5.xUbuntu 22.04完全在支持范围内。整个编译安装流程可以分为环境准备、获取源码、编译、安装、加载验证五步。3.1 准备编译工具链编译内核模块和编译普通C程序不一样必须要有与当前运行内核版本完全对应的内核头文件。这一步骤没做好后面编译必报错。打开终端先确认当前内核版本uname -rUbuntu 22.04通常输出类似5.15.0-91-generic这样的结果。然后安装编译工具和对应的内核头文件sudo apt update sudo apt install -y build-essential linux-headers-$(uname -r) dkmsbuild-essential提供gcc、make这些基础编译工具linux-headers-$(uname -r)提供当前内核的编译配置和头文件。命令里的$(uname -r)会自动展开成你当前的内核版本所以不用手动去查。还有一个点值得提一下如果你的系统安装的是HWE内核比如5.19.0-xx-generic同样用这条命令安装对应头文件即可不需要额外处理。3.2 获取官方驱动源码WCH官方驱动仓库在GitHub上仓库名是WCHSoftGroup/ch343ser_linux。可以用git clone拉取也可以直接下载zip包git clone https://github.com/WCHSoftGroup/ch343ser_linux.git cd ch343ser_linux/driver如果你在企业内网不方便访问GitHub也可以去沁恒官网下载中心找CH343的Linux驱动本质上是同一份源码。我个人推荐用GitHub版本因为官方会持续提交对较新内核的适配补丁。3.3 编译模块在driver目录下直接执行make如果前面的内核头文件安装正确编译过程一般十几秒就结束生成ch343.ko文件。这个文件就是我们要的内核模块。编译过程中如果出现类似error: ‘struct usb_serial_driver’ has no member named ‘port_probe’的报错大概率是源码版本太老和5.15内核的USB serial API不兼容。解决办法是把仓库拉到最新版或者检查一下本地源码是不是很老的版本。3.4 安装模块到系统目录编译完成后执行sudo make install sudo depmod -a sudo modprobe ch343make install会把ch343.ko拷贝到/lib/modules/$(uname -r)/extra/目录下depmod -a重新扫描模块依赖关系让系统知道新增了这个模块modprobe ch343则直接加载模块。这一步和手动insmod ch343.ko的区别在于经过depmod后模块被纳入了内核模块管理体系后续即使设备热插拔内核也会自动加载它而不是只对当前会话生效。3.5 验证设备节点模块加载后插入CH343设备再查看设备和内核日志dmesg | tail -20 ls -l /dev/ttyCH343USB*正常的话dmesg里会出现usb 1-2: ch343 converter now attached to ttyCH343USB0之类的信息/dev下出现ttyCH343USB0节点。到这一步驱动已经工作串口通信已经可用了。缺权限的话需要加sudo先测试一下无妨sudo minicom -D /dev/ttyCH343USB0 -b 115200能进minicom界面说明驱动OK。4. 用DKMS把驱动“焊接”进系统开机自启的关键操作如果按照上面的方式直接make install驱动确实能工作但有一个隐患内核一旦升级/lib/modules/$(uname -r)/整个目录会被替换刚安装的ch343.ko就没了。下次重启后插上设备发现又回到了最初“设备不识别”的状态又得重新编译一遍。这个体验非常糟糕尤其是对经常执行apt upgrade的人。DKMS就是来解决这个问题的。它会把驱动的源码和编译配置注册进系统当新内核安装时DKMS自动为新内核重新编译并安装模块。换句话说驱动不再和某个特定内核版本绑定而是跟着系统内核走属于一劳永逸的方案。4.1 把源码放到DKMS管理目录DKMS要求驱动源码放在/usr/src/包名-版本号/目录下名字必须符合这个格式。我们把它命名成ch343-1.0sudo mkdir -p /usr/src/ch343-1.0 cd /usr/src/ch343-1.0 sudo cp -r ~/ch343ser_linux/driver ./这里我把整个driver目录拷贝过去里面有ch343.c、Makefile这些核心文件。如果你的源码还在别的地方按实际路径调整即可。4.2 编写dkms.conf配置文件DKMS工作的时候需要知道怎么编译这个模块、编译出来的模块叫什么名字、应该安装到内核的哪个目录。这些信息都写在dkms.conf里。在/usr/src/ch343-1.0/下创建这个文件sudo vi dkms.conf内容如下PACKAGE_NAMEch343 PACKAGE_VERSION1.0 BUILT_MODULE_NAME[0]ch343 BUILT_MODULE_LOCATION[0]driver DEST_MODULE_LOCATION[0]/kernel/drivers/usb/serial/ MAKE[0]make -C ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build/driver KERNELDIR${kernel_source_dir} modules CLEAN[0]make -C ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build/driver KERNELDIR${kernel_source_dir} clean AUTOINSTALLyes各字段含义简单说明一下方便你将来移植到其他驱动PACKAGE_NAME和PACKAGE_VERSIONDKMS识别驱动的标识必须和目录名对应。BUILT_MODULE_NAME编译产出的内核模块名称也就是ch343.ko里的ch343。BUILT_MODULE_LOCATION相对于源码根目录模块文件所在的位置。DEST_MODULE_LOCATION模块最终安装到内核树中的目标目录USB串口驱动惯例放在/kernel/drivers/usb/serial/。MAKE和CLEAN指定编译和清理命令。注意这里使用了${dkms_tree}和${kernel_source_dir}两个变量DKMS会自动展开成实际源码路径和当前内核源码路径。AUTOINSTALLyes安装新内核时自动触发重建这是开机自启的核心开关。4.3 注册并构建DKMS模块执行以下命令把驱动注册进DKMS并完成第一次编译安装sudo dkms add -m ch343 -v 1.0 sudo dkms build -m ch343 -v 1.0 sudo dkms install -m ch343 -v 1.0每条命令的作用add把/usr/src/ch343-1.0注册进DKMS的数据库。build用当前内核源码编译模块。install把编译好的ch343.ko链接到当前内核模块目录并触发depmod。执行后可以用以下命令确认模块状态dkms status输出里出现ch343/1.0, 5.15.0-91-generic, x86_64: installed就代表DKMS注册成功。如果之前手动执行过make install建议先清理掉避免系统里存在两份模块。先卸载手动安装的版本sudo rmmod ch343 2/dev/null sudo rm -f /lib/modules/$(uname -r)/extra/ch343.ko sudo depmod -a然后再走DKMS流程。其实这一步也可以不做内核模块是按照目录顺序加载的同时存在两份一般也不会有冲突但为了干净我还是建议清理一次。4.4 验证开机自启是否生效为了确认DKMS确实做到了“开机自动加载”可以执行sudo modprobe -r ch343 ls /dev/ttyCH343USB* 2/dev/null-r参数会卸载模块设备节点跟着消失。然后重启系统或者手动加载一下sudo modprobe ch343 ls -l /dev/ttyCH343USB*设备节点再次出现。如果在重启后不做任何操作设备节点也能在插入USB时自动出现说明DKMS的AUTOINSTALL和模块依赖机制已经共同把它变成了系统自带的模块。5. 免sudo访问与固定设备名udev规则一次配到位模块加载只是第一步真正用起来的时候还有一个特别烦人的问题非root用户访问不了/dev/ttyCH343USB0。默认情况下设备节点的所有者是root所属组是dialout权限是crw-rw----。普通用户直接打开会报Permission denied每次都得sudo这在写脚本、跑Python串口程序时非常不方便。解决方式有两种。第一把当前用户加入dialout组重新登录后生效sudo usermod -aG dialout $USER这个方法的优点是简单缺点是把所有串口设备都放开了而且需要注销重新登录才生效。第二种方式更精准用udev规则给指定的CH343设备单独设置权限。创建udev规则文件sudo vi /etc/udev/rules.d/99-ch343.rules写入以下内容SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}55d3, MODE0666, GROUPdialout然后重载规则并触发sudo udevadm control --reload-rules sudo udevadm trigger拔插一下USB设备再执行ls -l /dev/ttyCH343USB0权限会变成crw-rw-rw-普通用户也能直接打开。建议拔插一次因为udevadm trigger对已经存在的设备有时不会完整重新应用所有规则。再说说多个CH343设备同时插在机器上的情况。默认情况下内核按插入顺序分配设备名假设你插了两个CH343模块那它们分别叫ttyCH343USB0和ttyCH343USB1。但如果重启或者调换USB口名字可能互换。对写代码的人来说串口设备名漂移是个很头大的问题——程序里写死的/dev/ttyCH343USB0可能今天对应A设备明天就变成B设备。解决办法是用udev的SYMLINK给设备创建一个固定的符号链接。每颗CH343芯片都有唯一的序列号通过udevadm可以查到udevadm info -a -n /dev/ttyCH343USB0 | grep serial输出里的ATTRS{serial}就是芯片序列号比如A50285BI。然后在udev规则里加上SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}55d3, ATTRS{serial}A50285BI, SYMLINKmcu重载规则后不管设备被系统识别成ttyCH343USB0还是ttyCH343USB1都一定有一个/dev/mcu指向它。程序里只写/dev/mcu就不怕名字漂移了。6. 我踩过的坑Secure Boot、头文件缺失、模式识别错乱的排查链路驱动安装本身不难但排查问题时如果思路不清晰很容易卡在某个报错上半天下不来。这一节把我实际遇到过的几个典型坑完整梳理一遍都按“现象→排查→解决”的链路来写。6.1 Secure Boot拦截第三方内核模块现象sudo modprobe ch343执行后没有报错但ls /dev/ttyCH343USB*什么都没有。dmesg里能看到Lockdown: insmod: unsigned module loading is restricted; see man kernel_lockdown.7原因UEFI的Secure Boot开启后内核会拒绝加载没有数字签名的第三方模块。CH343驱动是我们自己编译的没有签名自然被拦下来。排查方式执行mokutil --sb-state如果返回SecureBoot enabled基本就是这个问题。解决方式有两种最直接的办法进BIOS关闭Secure Boot。不同主板路径不同一般在Security或Boot选项卡里把Secure Boot设置为Disabled保存重启。不想关Secure Boot的话可以对模块签名。但这个过程涉及创建MOK密钥、导入密钥、签名模块比较繁琐对大多数个人开发场景没必要。6.2 内核头文件版本和运行内核不一致现象编译驱动时提示找不到/lib/modules/$(uname -r)/build或者提示缺少generated/autoconf.h。原因装了头文件但版本对不上。最常见的情况是你安装的linux-headers-$(uname -r)并不是当前运行内核的版本而是最新内核版本的头文件。这是因为Ubuntu自动更新内核后还没重启系统运行在旧内核上但apt安装的头文件是最新内核的。排查方式uname -r dpkg -l | grep linux-headers对比两个命令的输出。如果头文件版本和运行版本不一致执行sudo apt install -y linux-headers-$(uname -r)装了对应的头文件后重新进入源码目录先make clean再make。顺便说一句升级内核后一定要重启否则头文件和运行内核永远是错位的。我刚接触这个坑时曾经在同一个会话里反复编译失败浪费了大半个小时。6.3 CH343被CDC ACM模式接管出现了ttyACM0而不是ttyCH343USB0现象明明没装CH343驱动插入设备后/dev/ttyACM0出现了用起来也能通信但lsusb看到的还是1a86:55d3。原因这颗芯片被配置成了CDC ACM模式。CH343的固件可以通过工具切换模式厂商自定义模式需要ch343.ko驱动CDC ACM模式则由内核cdc_acm.ko驱动直接识别。排查方式dmesg里如果出现cdc_acm 1-4:1.0: ttyACM0: USB ACM device那就是这种情况。此时设备走的是标准USB串口协议不需要额外装驱动直接用/dev/ttyACM0就行。这一点特别容易让人产生困惑。我在一次调试中明明没加载ch343模块ttyACM0却能用一度怀疑自己是不是见鬼了。后来查了CH343的数据手册才知道它有这种双模式设计。如果你的项目对波特率要求很高需要用到非标准波特率建议还是切回厂商自定义模式用官方驱动因为CDC ACM模式在某些内核版本下对自定义波特率的支持不够好。6.4 ModemManager抢占串口现象用Python的pyserial打开串口有时会报Resource busy但用lsof /dev/ttyCH343USB0查不到进程占用。原因Ubuntu桌面版自带的ModemManager服务会自动探测新出现的串口设备尝试用AT指令和它们通信判断是不是3G/4G上网卡。这个探测过程会短时间占用串口如果刚好撞上你打开串口的瞬间就会冲突。排查方式systemctl status ModemManager查看服务状态journalctl -u ModemManager -f查看它的日志。解决方式sudo systemctl disable --now ModemManager如果你用不到4G上网卡、拨号上网这类功能直接禁掉这个服务没任何影响。如果是服务器版Ubuntu一般默认没有这个服务不用管。6.5 多设备同时插入设备节点漂移导致程序连错设备现象插了多个USB转串口设备程序打开的串口时好时坏数据完全对不上。原因前面讲过的设备节点漂移问题。/dev/ttyCH343USB0并不是固定指向某一颗芯片的内核按枚举顺序分配。排查方式udevadm info -a -n /dev/ttyCH343USB0 | grep -E manufacturer|product|serial确认当前节点对应的是哪颗芯片。解决方式就是前面提过的固定符号链接不再赘述。这里想强调一点配上固定链接之后应用层代码一定要改用固定链接路径否则规则写了等于白写。7. 验证通信和后续维护从minicom实测到卸载清理驱动装好权限配好接下来就是实打实地测试一下通信是否正常。这里分享几个常用的验证方式和维护建议。7.1 用minicom做回环测试把CH343模块的TXD和RXD引脚短接然后安装minicomsudo apt install -y minicom minicom -D /dev/ttyCH343USB0 -b 115200在minicom界面里敲几个字符如果屏幕上有回显说明发送和接收通路都正常。如果没有回显把TXD和RXD对调一下再试。这个操作看似基础但能快速区分是驱动问题还是硬件接线问题避免在错误的方向上浪费时间。7.2 用Python快速验证如果你平时主要用Python做串口开发直接用pyserial做一次收发测试更直观import serial ser serial.Serial(/dev/ttyCH343USB0, 115200, timeout1) ser.write(bhello ch343\r\n) response ser.read(100) print(response) ser.close()前提是已经装了pyserialpip3 install pyserial。运行脚本前确认当前用户对设备有读写权限否则会报PermissionError: [Errno 13] Permission denied: /dev/ttyCH343USB0。7.3 卸载和清理驱动如果你以后不想用这个驱动了或者要换一种安装方式完整卸载流程如下sudo modprobe -r ch343 sudo dkms remove ch343/1.0 --all sudo rm -rf /usr/src/ch343-1.0dkms remove会从DKMS数据库移除这个驱动同时删除所有已安装内核版本下的模块文件。执行完dkms status应该不再显示ch343。7.4 关于非标准波特率的一个小提示CH343硬件上最高支持6Mbps但很多串口工具界面里只能选到921600。如果你需要更高的波特率可以用stty手动设置stty -F /dev/ttyCH343USB0 3000000然后再用cat或minicom打开有些工具会自动识别当前波特率有些不会需要手动填。这个功能在调试一些高速传感器模块时很有用我遇到过好几次低波特率下通信正常、调高就乱码最后发现是工具界面压根没把波特率设置到位。整套流程走下来核心其实就是三件事编译驱动、DKMS接入、udev规则。编译驱动解决的是“内核不认识这颗芯片”的问题DKMS解决的是“内核升级后驱动还在不在”的问题udev规则解决的是“普通用户能不能用”的问题。这三件事处理完CH343在Ubuntu 22.04下就真的和CH340一样即插即用了。我自己给设备配上固定的/dev/mcu链接之后日常开发已经基本感觉不到这颗芯片的存在对我来说这就是最理想的状态。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门