尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Ubuntu 22.04 CH340驱动排查与ttyUSB固定设备名指南
简介面向Ubuntu 22.04用户这份资源专注于解决CH340 USB转串口芯片在Linux内核中未被默认支持、需要手动编译安装驱动的问题。适用于嵌入式开发、单片机调试、物联网设备通信等场景尤其适合刚接触Linux驱动安装的初学者。包体包含16个文件主要类型有CH340驱动源码ch34x.c、预编译内核模块ch34x.ko、Makefile编译脚本、模块依赖与符号表文件modules.order、Module.symvers、编译过程生成的命令与临时文件以及readme.txt安装说明整体容量仅291KB结构紧凑。已有777人学习下载。资源提供了从源码编译到模块加载的完整要素读者可依据readme.txt逐步操作无需另外搜寻驱动包同时预编译的ko模块也能直接用于当前内核环境降低编译门槛。无论手动编译还是直接加载都能获得明确的文件支撑帮助在Ubuntu 22.04中顺利识别CH340设备并配置串口权限从而快速开展串口通信开发与调试。1. Ubuntu 22.04 插上 CH340 没反应多数时候不是驱动缺失手上一块 CH340 的 USB 转 TTL 板子在 Windows 上插上就有 COM 口换到 Ubuntu 22.04 后发现lsusb能认出芯片但/dev/ttyUSB0就是不出来。搜ubuntu 22.04 安装 CH340串口驱动能找到的教程大多是老版本系统的做法照着敲完make还报错最后只能干瞪眼。这篇把从判断、编译、加载到固定设备名的完整路径讲清楚覆盖玩 ESP32、STM32、调试路由器、连 3D 打印机主板和工控串口设备的场景。核心结论先说Ubuntu 22.04 的内核其实自带 CH340 驱动模块模块名是ch341大多数情况你缺的不是驱动是判断顺序和权限。2. 先判断是缺驱动还是权限问题dmesg 与 lsusb 快速定位2.1 插上设备后先看这两条命令拿到一块 CH340 板子插上之后不要急着编译任何东西。先打开终端观察系统对这次插入动作的反应。两条命令就能把问题分成两类# 查看 USB 枚举信息和内核驱动加载日志 dmesg | tail -n 20 # 确认 USB 总线是否识别到 CH340 芯片 lsusbdmesg的尾部输出会告诉你内核是否识别了设备、是否绑定了驱动。lsusb输出里找1a86这个厂商 IDCH340 类芯片的固定厂商 ID。常见的结果组合和对策如下表dmesg 现象含义下一步出现ch341-uart converter now attached to ttyUSB0驱动已在工作去查权限和设备节点usb 1-1: new full-speed USB device但无后续 ttyUSB 字样USB 层识别驱动层未绑定考虑手动装驱动或加载模块完全没有 USB 枚举信息线材、供电、接口问题换线换口检查虚拟机 USB 直通注意ch341-uart这个内核日志里的名称CH340 芯片在内核里的驱动模块名是ch341不是ch340。很多人在lsmod | grep ch340里查不到东西就以为驱动没装其实应该查ch341。2.2 内核自带 ch341 模块的边界Ubuntu 22.04 默认内核为 5.15 系列这个版本的内核源码树里已经包含了ch341驱动模块位于内核的 USB 串口驱动目录下。也就是说绝大多数直接插上就能用的场景内核自己就处理了不需要你手动编译任何驱动。那为什么还有这么多人搜怎么装 CH340 驱动因为我实际遇到的情况是设备能被 USB 层识别但驱动没有自动绑定。触发这个问题的常见原因有几个。比如芯片是 CH340 的早期批次其内部配置信息与新版内核驱动的匹配逻辑有差异或者内核在启动时把ch341模块列入黑名单有些嵌入式板卡镜像会这么干再比如你用的是从某商家买的 CH340 模块芯片上的 VID/PID 被改写过内核的 USB 串口驱动匹配表认不出它。判断模块是否被系统加载用这条lsmod | grep ch341有输出说明模块已经加载问题在绑定或权限侧。没输出先尝试手动加载一次# 手动加载 ch341 模块 sudo modprobe ch341 # 再观察一次内核日志 dmesg | tail -n 10modprobe和insmod的区别在于它会自动处理模块依赖对于ch341这种不依赖其他外部模块的驱动两者都能加载但modprobe更规范后续配合modules-load.d做开机自启也更顺手。2.3 权限问题先排除设备节点出现了ls /dev/ttyUSB*能看到/dev/ttyUSB0但打开串口报Permission denied这是 Ubuntu 22.04 下最常见的假驱动故障。默认情况下 ttyUSB 设备属于dialout组当前用户不在这个组里就没有读写权限。# 把当前用户加入 dialout 组 sudo usermod -aG dialout $USER加完组不是立刻生效的。很多人卡在这一步明明加了组重新打开终端还是权限不足。因为用户会话的组信息在登录时就已经固定了必须完全注销重新登录或者执行newgrp dialout临时切换组身份。重启当然也行但为了这么点事重启不值当。3. 源码编译安装 CH340 驱动从下载到 insmod 的完整命令3.1 准备内核头文件如果你确认了内核没加载ch341或者内核自带的驱动匹配不上你的芯片下一步才是手动编译驱动。编译内核模块必须要有当前内核的头文件这是新手最容易踩的坑直接sudo apt install linux-headers-generic装完发现编译还是报错因为装的是通用版本而系统当前跑的内核可能是 HWE 版本Ubuntu 22.04.2 之后的硬件支持内核两者版本号对不上。# 安装与当前内核完全匹配的头文件 sudo apt update sudo apt install linux-headers-$(uname -r)$(uname -r)会动态取出当前内核版本号比如5.15.0-91-generic拼出来的包名就是linux-headers-5.15.0-91-generic。用这个写法比手打版本号可靠内核升级后重新执行也不会装错。装完后验证一下编译环境# 确认头文件目录存在且非空 ls /lib/modules/$(uname -r)/build正常情况下这个目录会软链接到/usr/src/linux-headers-xxx里面有 Makefile 和 include 目录。如果ls报目录不存在说明头文件没装上或者装错了版本。3.2 获取 CH340 官方驱动源码并确认 Makefile驱动源码从芯片厂商的官网下载搜CH341SER_LINUX就能找到对应页面。下载下来是一个 ZIP 压缩包解压后是 Linux 下的驱动源码目录。不要从各种第三方博客的网盘链接下载那些包可能被改动过编出来的模块行为会非常奇怪。# 解压官方源码包 unzip CH341SER_LINUX.ZIP cd CH341SER_LINUX进入目录后你会看到几个文件ch341.c驱动源码、Makefile、readme说明文件可能还有modprobe_install.sh安装脚本。先打开 Makefile 看开头的几行# 查看 Makefile 中的内核路径配置 head -n 30 Makefile新版官方包里的 Makefile 一般是这样写的KDIR : /lib/modules/$(shell uname -r)/build也就是自动取当前内核版本不需要手工改。如果你拿到的包是老版本的Makefile 里可能写死了一个版本号路径这种情况下要手动改成上面的形式否则编译时找不到内核源码目录直接报错。3.3 编译与加载源码目录确认无误后直接编译# 清理旧的编译产物 make clean # 编译生成 ch341.ko 模块文件 makemake clean不是为了好看是因为如果你之前编译失败过目录里会残留.o和.cmd之类的半成品文件不清理直接再make可能会跳过重新编译沿用损坏的旧产物。make成功后会生成ch341.ko这就是最终的内核模块文件。接着加载# 加载编译好的模块 sudo insmod ch341.ko # 检查模块是否加载成功 lsmod | grep ch341insmod加载指定路径下的模块文件它不查依赖、不查版本匹配适合加载本地刚编出来的模块。加载后如果lsmod里出现了ch341并且dmesg尾部出现类似ch341-uart converter now attached to ttyUSB0的日志说明驱动已经接管设备。此时看一眼/dev/目录ttyUSB0应该已经出现。如果出现了但没有权限回到上一章的dialout组方案处理。3.4 官方安装脚本与手动加载的区别官方包里的modprobe_install.sh脚本做的事情是把ch341.ko复制到系统内核模块目录然后执行depmod更新模块依赖之后你就可以用modprobe ch341来加载它。它的好处是让模块进入系统模块管理体系而不是像insmod那样只在当前会话临时生效。# 在源码目录执行官方安装脚本 sudo ./modprobe_install.sh不过这个脚本在实际使用中有个问题它默认把模块装到当前内核的模块目录但后续内核升级后新内核目录下没有这个模块驱动就又消失了。所以我自己一般不用这个脚本而是直接用下一章的 dkms 方案让驱动跟着内核版本自动重建。4. 用 dkms 让驱动跨内核升级不失效4.1 为什么 insmod 装完重启就没了直接insmod ch341.ko加载的模块只存在于当前运行的内核内存里重启后彻底消失。把.ko文件手动复制到/lib/modules/$(uname -r)/extra/再执行depmod -a也只是对当前内核版本生效。Ubuntu 22.04 的自动安全更新会频繁升级内核包每次升级后模块都得重新编译一次非常烦人。dkmsDynamic Kernel Module Support就是解决这个问题的标准做法把源码登记到系统每次内核更新后自动为新内核重新编译模块。4.2 把官方源码整理成 dkms 可识别的目录结构dkms 要求模块源码放在/usr/src/包名-版本号/下并且目录里必须有一个dkms.conf配置文件。先在系统里建目录把官方源码拷进去。# 创建 dkms 源码目录 sudo mkdir -p /usr/src/ch341-2.0.0 # 把驱动源码复制过去不需要那些安装脚本 sudo cp ch341.c Makefile /usr/src/ch341-2.0.0/ch341-2.0.0这个名字里的版本号不是固定的你可以用其他版本号但必须和后面dkms add时指定的名字保持一致。我自己习惯用2.0.0作为版本标识因为这是官方驱动常见的归档版本号方便记忆。接着写dkms.conf配置文件# 创建并写入 dkms 配置 sudo tee /usr/src/ch341-2.0.0/dkms.conf EOF PACKAGE_NAMEch341 PACKAGE_VERSION2.0.0 BUILT_MODULE_NAME[0]ch341 DEST_MODULE_LOCATION[0]/kernel/drivers/usb/serial MAKE[0]make -C ${kernel_source_dir} M${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build CLEANmake -C ${kernel_source_dir} M${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean AUTOINSTALLyes EOFdkms.conf每一项都有讲究。BUILT_MODULE_NAME[0]指定编译生成的模块名必须和源码实际生成的一致这里就是ch341。DEST_MODULE_LOCATION[0]决定模块安装到内核模块树的位置/kernel/drivers/usb/serial是内核自带 USB 串口驱动的标准位置放在这里可以让modprobe正常检索到。最关键的AUTOINSTALLyes表示新内核安装后自动重建此模块。4.3 执行 dkms 的 add / build / install目录结构和配置文件就绪后执行三步# 登记模块源码 sudo dkms add -m ch341 -v 2.0.0 # 为当前内核编译模块 sudo dkms build -m ch341 -v 2.0.0 # 安装模块到内核模块树 sudo dkms install -m ch341 -v 2.0.0dkms add是在登记它会检查/usr/src/ch341-2.0.0目录是否存在且包含dkms.conf然后写入 dkms 的数据库。build会调用dkms.conf里的MAKE[0]指定的命令用当前内核的头文件编译。install把编好的ch341.ko复制到内核模块目录并执行depmod。三步都成功的话执行检查# 查看 dkms 里的模块状态 dkms status输出里ch341/2.0.0的状态应该是installed。此时可以用sudo modprobe ch341加载也可以重启后让系统自动处理。4.4 开机自动加载与模块优先级dkms install只是让模块在系统中存在不会主动加载它。如果当前内核已经跑着内核自带的ch341没问题但如果你的场景需要强制使用这个新编的模块就要配置开机自动加载# 写入开机自动加载配置 echo ch341 | sudo tee /etc/modules-load.d/ch341.confmodules-load.d目录下的配置文件会在系统启动早期被读取里面的模块名会被自动modprobe。这里有个值得讲的细节dkms 安装的模块放在/lib/modules/$(uname -r)/extra/目录内核自带的同名模块在/lib/modules/$(uname -r)/kernel/drivers/usb/serial/depmod生成的依赖关系里extra目录的优先级更高所以modprobe ch341优先加载你编译的版本不会出现两个同名模块互相打架的情况。如果之后想卸载这套东西三步走先dkms remove -m ch341 -v 2.0.0 --all再删/usr/src/ch341-2.0.0和/etc/modules-load.d/ch341.conf最后sudo depmod -a。顺序不能反否则 dkms 会找不到源码报错。5. CH340 驱动安装避坑清单编译失败、设备消失与 Secure Boot5.1 现象make报错找不到/lib/modules/.../build新装好的 Ubuntu 22.04进入官方源码目录执行make直接输出类似Makefile: xxx: /lib/modules/5.15.0-xx-generic/build: No such file or directory的错误。原因系统默认最小安装不带内核头文件/lib/modules/$(uname -r)/build这个软链接根本不存在。解决方式看起来简单但有个细节如果之前已经apt install linux-headers-generic过仍报这个错大概率是当前跑的内核是 HWE 版本与 generic 头文件版本不一致。要去确认# 对比当前内核版本和已安装的头文件版本 uname -r apt list --installed | grep linux-headersuname -r的输出类似5.15.0-91-genericapt list里应该看到linux-headers-5.15.0-91-generic。如果版本对不上直接sudo apt install linux-headers-$(uname -r)强制按当前内核版本装。5.2 现象insmod成功但/dev/ttyUSB0就是不出来模块加载没有报错lsmod里也有ch341但插上设备后/dev/ttyUSB*什么都没有。这时候问题基本不在驱动而在 USB 设备本身没被正确枚举。一种常见情况是在虚拟机里跑 UbuntuVMware 或 VirtualBox 默认不把 USB 设备直通给虚拟机宿主机的 USB 口插了设备客户机根本看不到。另一个常用环境是 WSL2它默认不挂载 USB 设备需要额外的 usbipd 工具做设备转发。排查时看dmesg有没有 USB 层的枚举记录# 拔插一次设备后专门看 USB 枚举日志 dmesg | grep -i usb | tail -n 15如果完全没有new full-speed USB device之类的日志说明 USB 层就没看到设备。除了虚拟化透传问题还有可能是 USB 延长线质量差导致芯片反复掉线或者主板 USB 口供电不足。换一个直连的 USB 口试一下能排除掉一半的玄学问题。5.3 现象Secure Boot 开启后模块加载被拒绝sudo insmod ch341.ko执行后输出Operation not permitted或者dmesg里出现module verification failed: signature and/or required key missing之类的提示。原因UEFI 的 Secure Boot 开启了它会校验内核模块的数字签名未签名的第三方模块一律拒绝加载。两条路。第一条是开发机上直接关掉 Secure Boot进 BIOS 设置里找到 Secure Boot 选项并禁用一劳永逸但某些预装系统尤其是品牌机关闭后可能影响 Windows 启动操作前先确认。第二条是给模块签名并注册 MOKMachine Owner Key这个流程更安全但麻烦一点。常见做法是# 生成签名密钥对并导入系统 MOK mokutil --import module-signing.cer执行后按提示设置一个一次性密码重启后系统会进入 MOK 管理界面选择 enroll 并输入刚才设置的密码完成导入。之后再重新编译模块并签名加载时就不会被 Secure Boot 拦截。这个流程我只建议需要长期保持 Secure Boot 开启的环境做个人开发机上关掉省心得多。5.4 现象多个 CH340 设备插拔后 ttyUSB 编号漂移系统里同时插了两块 CH340 的板子初始状态是/dev/ttyUSB0和/dev/ttyUSB1拔掉一块再插回去两块设备的编号可能互换。这就是 ttyUSB 设备的经典问题内核按 USB 端口的枚举顺序分配编号不按芯片身份分配。如果上位机软件写死了连接/dev/ttyUSB0下次就可能会连到错误的板子数据链路全是乱码甚至毫无响应。解决方向是用 udev 规则按芯片的序列号或物理端口绑定固定设备名。具体做法放在下一章展开这里先记住一个排查习惯插拔变号是 udev 规则的锅不是驱动的问题不要靠反复插拔碰运气。6. 固定串口设备名的进阶技巧udev 规则与日常验证6.1 用 udevadm 读出芯片的身份信息要给设备固定名字先得知道系统是怎么区分这两块长得一模一样的 CH340 板子的。udevadm能读出设备树上的所有属性# 查询 ttyUSB0 的设备属性 udevadm info -a -n /dev/ttyUSB0输出很长重点看三处ATTRS{idVendor}厂商 IDCH340 一般是1a86、ATTRS{idProduct}产品 ID常见的是7523、ATTRS{serial}芯片的序列号字符串。如果两块板子的serial不同恭喜可以用序列号精确区分如果serial为空或完全一样很多便宜模块出厂时没写序列号就只能退而求其次用设备所在 USB 端口路径来区分。6.2 写 udev 规则并按序列号绑定根据查到的属性在/etc/udev/rules.d/下新建规则文件# 创建 udev 规则文件 sudo tee /etc/udev/rules.d/99-ch340.rules EOF # 按序列号绑定到固定设备名 SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}7523, ATTRS{serial}A1, SYMLINKch340_dev EOFSUBSYSTEMtty限定规则只作用于 tty 设备ATTRS{idVendor}和ATTRS{idProduct}限定芯片型号ATTRS{serial}精确到具体设备SYMLINKch340_dev表示额外创建一个名为/dev/ch340_dev的符号链接指向实际设备节点。这样写的好处是不管系统把它枚举成ttyUSB0还是ttyUSB3/dev/ch340_dev始终指向同一块板子。写完规则要重载# 重新加载 udev 规则并触发生效 sudo udevadm control --reload-rules sudo udevadm trigger--reload-rules让 udev 重新读取规则文件trigger让它重新匹配所有已存在的设备。执行后ls -l /dev/ch340_dev应该能看到符号链接指向某个 ttyUSB 节点。如果多个 CH340 设备序列号都一样就得用物理端口路径区分规则改成匹配KERNELS1-1.2:1.0这种端口路径字符串。这个方案有个副作用换个 USB 口插名字就失效了。所以能用序列号就用序列号它是芯片出厂时写入的跟插哪个口无关。6.3 快速验证驱动和链路是否正常固定好设备名之后日常验证链路是否通我一般不急着写代码先命令行测一发# 设置串口波特率并发送测试数据 stty -F /dev/ch340_dev 115200stty配置串口参数-F指定设备文件115200是波特率。设置完可以往串口写几个字节看对面的设备是否有反应。如果没有stty装一下sudo apt install util-linux更快的方式是用 Python 的 pyserial 直接打开串口python3 -m serial.tools.miniterm /dev/ch340_dev 115200miniterm是 pyserial 自带的一个迷你终端能交互式地读写串口非常适合快速验证硬件链路。能进到这个界面并且键入字符有回显说明驱动、权限、设备名全部正常剩下的就是业务代码层面的事了。这一套流程走下来回头看很多驱动装不上的问题其实卡在判断顺序上先看内核日志、再查模块、然后处理权限最后才轮得到编译和 dkms。我自己早期在这上面也栽过跟头对着老教程编译半天最后发现只是没加 dialout 组。后来养成习惯凡是串口设备问题先dmesg再看lsmod再查权限三步走完再决定要不要碰源码省下了大量时间。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Redis面试常问2-- 从海量数据里查询某一固定前缀的key? SCAN cursor 实战避坑指南

Redis面试常问2-- 从海量数据里查询某一固定前缀的key? SCAN cursor 实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/15 17:44:01
Natron Backdrop 节点完全指南:用分组容器组织节点图的实战与源码解析

Natron Backdrop 节点完全指南:用分组容器组织节点图的实战与源码解析

音视频视频处理图形学桌面应用 【免费下载链接】Natron Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry. 项目地址: https://gitcode.com/gh_mirrors/na/Natron 点击查看 …

📅 2026/10/15 17:39:00
小公司的合同管理,分三层就够了

小公司的合同管理,分三层就够了

公司用 Excel 和微信群管合同,多数不是因为不重视,而是因为不清楚哪些环节需要有人盯着;而恰恰是几个看起来不起眼的环节,会在履约期内留下隐患,产生扯皮、丢单、坏账的后果。合同大多分散在销售的笔记本、老板的邮箱、…

📅 2026/10/15 17:39:00
MORE NEWS

更多资讯

📰

webpack打包纯静态商城站:多页面资源处理与工程化实践

1. 从散落的静态文件到可交付产物:这次打包到底要解决什么手里有一套品优购的静态商城页面,纯HTML、CSS加一点图片和字体图标,没有框架、没有模块化、没有构建工具。这种项目在本地双击打开index.html就能跑,看起来岁月静好&#…

📰

思科华为组播配置与排错实战:从RPF原理到IGMP Snooping部署

1. 从一个真实运维场景说起:为什么组播总在关键时刻掉链子很多做网络运维的朋友都有过类似的经历:公司要搞一场全员线上直播培训,或者园区要部署一套视频监控系统,单播方案跑几十路就已经把核心链路带宽吃满了,于是决定…

📰

Qt+CMake三大配置范式:从Demo到企业级项目的演进路径

1. 为什么Qt项目里CMakeLists.txt总让人“改得心虚”?你有没有过这种经历:刚用Qt Creator新建一个Qt Widgets Application,点开CMakeLists.txt一看,满屏的find_package(Qt6 REQUIRED COMPONENTS Widgets)、target_link_libraries(…

📰

吃透六自由度机器人D-H法:建模、正逆解与避坑全攻略

简介:六自由度机器人D-H法学习资料共3个文件,压缩包仅2.27MB,包含2个MATLAB程序(m文件)和1份Word说明文档。资料面向机器人学初学者、高校相关课程学生以及需要完成运动学作业的工程师,系统讲解D-H参数法原…

📰

Python调用Simulink编译DLL:零MATLAB依赖的轻量部署方案

简介:本资源是一套面向Python开发者与嵌入式仿真工程师的Simulink模型加速实践方案,聚焦于将Simulink模型编译为DLL并在Python中高效调用,显著降低MIL(模型在环)测试对MATLAB/Simulink许可证和运行时环境的依赖。资源以…

📰

Oransim路线图前瞻:从v0.2到因果基础模型,闭环AI媒体投放与百万级智能体集群的完整规划

【免费下载链接】oransim Causal Digital Twin for Marketing at Scale Predict any marketing decision before you spend a dollar. 项目地址: https://gitcode.com/gh_mirrors/or/oransim 点击查看 免费下载 Oransim 是一个开源的营销因果数字孪生框架&#xf…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬