
简介资源为ARM64架构如AGX Orin平台在Ubuntu22.04系统下安装PL2303USB转串口芯片驱动的完整教程资料面向嵌入式开发者、机器人与自动驾驶领域的串口调试中级用户旨在解决新版系统缺少内核原生驱动、编译环境配置复杂等痛点。压缩包共111个文件以c源码、h头文件、makefile编译脚本为主另含ko内核模块、symvers符号表等可直接编译加载也便于对照排查依赖问题整体大小仅671KB。资源内置PL2303G Linux驱动v1.0.6的完整源码与编译配置依据说明即可完成环境准备、模块编译、加载及设备节点验证针对权限不足、设备缺失等常见故障还给出了dmesg日志排查思路。目前已有1094人学习下载方案经多人验证可行。读者借此可掌握在Ubuntu22.04下管理串口驱动的关键流程未来内核升级后也能基于源码自行适配有效降低嵌入式开发中的调试成本。1. 为什么在 AGX Orin 上装 PL2303 会翻车先搞清芯片版本再动手装驱动AGX Orin 这套 ARM64 架构的 ARM 盒子系统装了 Ubuntu 22.04插上一根常见的 PL2303 USB 转串口线ls /dev/ttyUSB* 半天没反应dmesg 里滚动几行“Unknown device”——这几乎是每个人第一次碰上的场景。问题不在接口也不在串口线本身而在 PL2303 芯片的版本内核自带的 pl2303 驱动只覆盖一部分老芯片新版芯片需要额外驱动。这篇文章不会让你一开始就编译源码而是按“确认芯片版本 → 加载内置驱动 → 不行再编译驱动 → 避坑”的顺序走一遍适合嵌入式开发者、机器人调试和车载工控场景下的新手也适合被同一问题卡过的熟手。2. 装驱动前先确认三件事芯片版本、内核模块和串口节点开门见山先把底层逻辑理清PL2303 是 USB 转串口的桥接芯片操作系统透过 USB 枚举拿到 Vendor ID 和 Product ID再匹配对应驱动。Linux 内核里有一个 pl2303 驱动模块但它对芯片的兼容性按版本划分。老版本芯片对应 USB ID 067b:2303通常能被直接识别而新版本比如 ID 067b:23a3 或 067b:23a0内核驱动可能完全不认得系统只能把它当成未知 USB 设备挂在那里。所以动手前的第一件事不是急着下载驱动而是确认你手里的芯片是哪个版本。2.1 用 lsusb 读取设备 ID老版 067b:2303 与新版 067b:23a3 的区别把 USB 转串口模块插到 AGX Orin 的任意 USB 口上打开终端执行lsusb如果设备被内核识别为 USB 设备你会看到类似下面的一行Bus 001 Device 003: ID 067b:2303 PL2303 Serial注意 ID 格式是“厂商ID:设备ID”。067b 是 PL2303 的厂商 ID2303 是老版 PL2303A/PL2303X 的设备 ID。如果你看到的 ID 是 067b:23a3那基本就是 PL2303HXA 或 PL2303GRA 这类新版芯片内置驱动大概率不认。还有一些线材用的是 067b:23aa也属于新版。把看到的 ID 记下来后面选编译路线时用得上。这里有个细节lsusb 输出里如果出现“Unknown device”而不是具体型号不代表 USB 枚举失败只说明系统还没有给这个设备分配一个匹配的驱动。这种情况下芯片的 ID 依然能看到但 /dev/ttyUSB 不会存在。所以 lsusb 是辨别芯片身份最廉价的手段不需要拆线。确认了设备 ID 之后还要确认系统里是否已经存在对应设备节点和驱动模块这能决定你是直接 modprobe 还是进入源码编译分支。2.2 用 modinfo 确认内核自带 pl2303 模块是否存在AGX Orin 上的 Ubuntu 22.04 用的是 NVIDIA 定制内核虽然和桌面版同为 5.15 系列但模块配置可能不一样。执行下面命令查看内置模块信息modinfo pl2303如果返回了模块路径和描述信息说明内核里已经带了 pl2303 驱动。如果返回“modinfo: ERROR: Module pl2303 not found”说明这个内核镜像没有编译 pl2303 模块你需要么换用你自制的内核要么走第 4 章的源码编译路线。我这里说的“内置模块”是内核树中编译好的 .ko 文件并不是系统装了什么额外的包。在 AGX Orin 上我一般会再确认一下内核模块路径是否有这个文件find /lib/modules/$(uname -r)/kernel/drivers/usb/serial -name *pl2303*如果输出有 pl2303.ko有些内核里是 pl2303.ko.xz那问题就简单了。如果没有文件但 modinfo 能查到可能是模块在别的子目录里这属于正常现象。确认模块存在后可以顺便看下模块支持的设备 ID 列表modinfo pl2303 | grep aliasalias 行里能看到代码里注册的 USB ID。如果里面有 067b:23a3 或 067b:23aa那你的新版芯片其实也能被内置驱动识别如果只有 067b:2303 而没有你手里的 ID那就必须走编译路线。这一步能省下不少无谓的编译时间。2.3 用 udevadm 与 /dev 节点判断系统是否枚举出 ttyUSB很多新手插上线第一时间去 ls /dev/ttyUSB没看到节点就下结论说是驱动没装。其实 USB 转串口设备会先生成 USB 接口再被串口驱动绑定最终才能创建 /dev/ttyUSB0。在驱动缺失的情况下/dev 里没有节点是正常的。但为了区分是驱动问题还是硬件问题先用 udevadm 看内核事件更可靠udevadm monitor --kernel --property--kernel 参数表示只显示内核事件--property 表示把事件附带属性一起打印。执行后重新插拔一次 USB 转串口线屏幕上会滚动出几段内核事件。注意看有没有 “PRODUCT67b/2303/1” 这种字段以及 “ACTIONadd”。如果只看到 add 事件没有后续的 “ttyUSB” 相关的绑定事件说明驱动没有接管。如果连 add 都没有那问题出在物理层比如 USB 线没插紧或者设备供电不足。如果内核已经绑定了驱动/dev 下会生成节点可以用下面的命令看节点和属主ls -l /dev/ttyUSB*正常情况下会显示 ttyUSB0 或类似名称属主是 root所属组是 dialout。如果没有节点说明驱动未加载或未绑定。这里的核心判断逻辑是先由 USB 核心枚举然后串口驱动匹配最后由 udev 创建设备节点三个环节缺一不可。完成这三步确认后你手里至少有一个清晰的结论芯片版本老或新内置模块在或不在设备节点有没有。按照结论去选下一步而不是盲目打字。3. 优先加载内核自带驱动modprobe 加载与 udev 权限持久化如果你的内核自带 pl2303 模块且 modinfo 的 alias 列表里有你手里的设备 ID那这一步能用最少的步骤解决。这里先演示最小加载命令再讲开机自动加载和权限持久化。别小看持久化AGX Orin 重启后如果模块没有加载串口节点不会自动出现很多现场调试因此重新插拔半小时。3.1 最小加载命令 modprobe pl2303 以及如何开机自动加载加载驱动模块的命令只有一行sudo modprobe pl2303执行后马上检查lsmod | grep pl2303如果能看到 pl2303 模块在列表里说明已经加载成功。紧接着再插拔一次串口线或者等模块加载后设备可能自动被绑定看 /dev/ttyUSB0 是否出现。modprobe 和 insmod 的区别在于modprobe 会处理模块依赖、参数和自动加载所以日常操作都用 modprobe。但 modprobe 只对当前会话有效重启后会失效。AGX Orin 这类工控设备经常无人值守开机最好让模块在开机时自动加载。常见做法是把模块名写入一个配置文件echo pl2303 | sudo tee /etc/modules-load.d/pl2303.conf确认文件内容cat /etc/modules-load.d/pl2303.confsystemd 会在启动早期读取 /etc/modules-load.d/ 下的配置文件逐个加载模块名。这里的 pl2303.conf 就是一个纯文本文件里面每行写一个模块名不需要 .ko 后缀。注意如果模块本身不被内核支持这里会静默失败需要 rebooting 后才发现没加载所以建议先用 modprobe 验证再写配置文件。3.2 用 dmesg 定位设备接入事件区分正常枚举和失败加载模块后把设备重新插一下然后执行dmesg | tail -30正常情况你会看到类似这样几行usb 1-1: new full-speed USB device number 6 using tegra-xusb usb 1-1: New USB device found, idVendor067b, idProduct2303 usb 1-1: New USB device strings: Mfr1, Product2, SerialNumber3 pl2303 1-1:1.0: pl2303 converter detected usb 1-1: pl2303 converter now attached to ttyUSB0最后一行就是驱动绑定成功的标志。如果 dmesg 中有 “Unknown device” 但没有 converter 信息说明驱动没有匹配如果驱动模块没加载你只会看到前几行 USB 枚举信息就停了。在 AGX Orin 上USB 控制器名称可能是 tegra-xusb 或 xhci-tegra这属于正常现象不影响判断。为了过滤无关信息也可以用 grep 只看 pl2303 相关行dmesg | grep -i pl2303如果内核日志被 ring buffer 冲掉可以先把 dmesg 时间戳加上dmesg -T | grep -i pl2303-T 参数把内核时间戳转成可读时间便于对照插拔动作。这一步的意义在于它能帮你把“驱动没加载”“驱动加载了但匹配失败”“设备完全没枚举”三种情况分开避免你拿着同一个工具去排查完全不同的故障。3.3 给串口设备加 udev 规则解决权限和固定设备名加载驱动后/dev/ttyUSB0 默认属主是 root用户不在 dialout 组就无法访问。很多人总用 sudo 跑串口工具这固然能通但权限问题会在你写服务脚本、运行无人值守程序时反复出现。正确做法是把当前用户加入 dialout 组sudo usermod -aG dialout $USER然后注销重新登录或者用 newgrp dialout 使会话立即生效。检查是否生效groups输出里包含 dialout 就说明OK。这比每次 sudo 干净多了。但还有一个更实际的需求有时系统里同时插了多个 PL2303或者 PL2303 和其他 USB 串口共存/dev/ttyUSB 节点编号可能漂移。我的做法是写 udev 规则根据序列号固定设备名。先读取设备的序列号如果线里有udevadm info -a -n /dev/ttyUSB0 | grep serial输出里找到 ATTRS{serial} 的值然后创建一个规则文件sudo tee /etc/udev/rules.d/99-pl2303-rs485.rules EOF SUBSYSTEMtty, ATTRS{idVendor}067b, ATTRS{idProduct}2303, ATTRS{serial}ABCD1234, SYMLINKpl2303-1, MODE0666 EOF执行重载sudo udevadm control --reload-rules sudo udevadm trigger这里解释几个参数SUBSYSTEM 指定设备属于 tty 子系统ATTRS{idVendor}067b 匹配厂商 ID注意不用加冒号ATTRS{serial} 用来区分同型号的不同个体如果没有序列号可以去掉这一项SYMLINKpl2303-1 会在 /dev 下创建一个符号链接方便程序直接使用固定路径MODE0666 含义是所有用户可读写这在多人调试环境或产品原型上很实用但生产环境建议改成 MODE0660 加上 GROUPdialout。重载规则后拔插一次设备用 ls -l /dev/pl2303-1 查看是否出现。如果出现后续所有串口工具都指向这个固定名字不会再因为节点漂移而改代码。4. 内核自带驱动不支持新版芯片源码编译 PL2303 驱动的完整流程当 modinfo 的 alias 列表里没有你手头的 ID或者 dmesg 提示 unknown device 时就需要走源码编译路线。ARM64 架构下的编译步骤和 x86 台式机没有本质区别因为 AGX Orin 自带完整的开发工具链一般使用本机编译而不是交叉编译。关键是装对内核头文件以及解决源码与当前内核 API 的兼容问题。4.1 安装 ARM64 下的内核头文件、gcc 和 make在 AGX Orin 的 Ubuntu 22.04 上内核是 NVIDIA 定制的 tegra 内核普通的内核头文件包不一定匹配。要先看当前内核版本uname -r输出通常类似 5.15.0-tegra。如果直接运行 apt install linux-headers-$(uname -r)系统可能会因为包名不存在而报错。更好的做法是先用 apt list 搜索一下可用的头文件包apt list --installed | grep linux-headers apt-cache search linux-headers-$(uname -r)如果搜到了匹配版本就安装sudo apt install linux-headers-$(uname -r)如果没有可能需要先更新源sudo apt update sudo apt upgrade然后再安装。注意这里说的头文件包是编译外部内核模块必需的环境里面存着内核模块构建所需的 Makefile、头文件和 Kconfig 配置。gcc 和 make 一般系统自带如果没有也一并装上sudo apt install gcc make验证编译环境ls /lib/modules/$(uname -r)/build如果这个目录存在且里面有 Makefile说明头文件包安装正确。如果 /lib/modules/$(uname -r)/build 是个软链接且指向不存在的位置那你的头文件包装错了版本需要重装。这一步是源码编译的大前提很多人在等待编译报错之前就已经输在这里了。4.2 修改驱动源码的 Makefile指定内核构建目录拿到芯片厂商提供的驱动源码包通常是 tar.gz 或 zip解压到工作目录。源码包一般会有一个 pl2303.c 和一个 Makefile。这里以源码包解压到 ~/pl2303-driver 为例mkdir -p ~/pl2303-driver tar -xzf pl2303-driver.tar.gz -C ~/pl2303-driver --strip-components1 cd ~/pl2303-driver ls打开 Makefile 看一看cat Makefile很多老驱动包的 Makefile 可能是这样obj-m pl2303.o KERNEL_DIR ? /usr/src/linux-headers-$(shell uname -r) CFLAGS -DPL2303_DEBUG有的则是直接写死路径。我们需要确认 KERNEL_DIR 或 KDIR 指向 /lib/modules/$(uname -r)/build。如果不是可以改写成这样obj-m pl2303.o KDIR : /lib/modules/$(shell uname -r)/build all: make -C $(KDIR) M$(PWD) modules clean: make -C $(KDIR) M$(PWD) clean这里 obj-m pl2303.o 告诉内核构建系统把 pl2303.o 编译成模块KDIR 是内核头文件所在的构建目录M$(PWD) 表示在源码包所在目录进行外部模块构建。注意不同驱动包里的目标文件名可能不是 pl2303.o比如是 pl2303x.o要按实际文件名改。有的厂商源码包会包含多个文件比如 linux_2_6_X-pl2303_module.c 之类这种建议先读一下源码包的 README确认入口文件。Makefile 不要瞎猜先用 cat 看一眼再改否则后面编译出来的模块可能不是你想要的接口。4.3 执行 make 编译模块处理常见编译错误在源码目录执行make如果编译成功目录下会生成 pl2303.ko 和一堆 .o 文件。用 ls 检查ls -l pl2303.ko编译过程中最常见的错误有两类。第一类是函数签名和结构体不匹配因为 Linux 内核 API 在 5.15 之后改过不少地方老版驱动源码可能还在用旧的函数原型。报错信息通常是不知名函数或者字段不存在。这种情况我不会去硬改源码而是找与该内核版本兼容的分支或补丁包。第二类错误是缺少头文件比如 linux/compiler.h 找不到这本质是内核头文件没装对回上一节检查。如果你手头的源码在新内核上缺了某些宏定义一个常见的临时做法是在 Makefile 里追加 CFLAGS 增加编译宏。比如CFLAGS -DPL2303_DEBUG不过治标不治本。更靠谱的方法是先检查当前内核的编译配置文件里有没有开启 CONFIG_USB_SERIAL_PL2303grep PL2303 /boot/config-$(uname -r) 2/dev/null || grep PL2303 /proc/config.gz 2/dev/null如果 CONFIG_USB_SERIAL_PL2303y 或 m那内核自带的 pl2303 驱动会和你编译的模块抢设备绑定这时你编译出来的驱动模块即使装进去也不一定能被系统加载。这种情况需要决定是屏蔽内置模块还是把自己的模块做成黑名单不过一般建议优先用内置模块因为老内核的驱动兼容性更好。编译成功后不要马上 modprobe先把内置模块卸载干净不然两个模块同时存在设备绑定会被内核里的那个抢先。4.4 安装模块并用 depmod 刷新依赖加载自编译驱动把编译生成的 pl2303.ko 拷贝到内核模块目录sudo cp pl2303.ko /lib/modules/$(uname -r)/kernel/drivers/usb/serial/然后刷新模块依赖sudo depmod -adepmod 会扫描 /lib/modules/$(uname -r) 下所有 .ko生成 modules.dep 和 modules.alias。这一步很关键如果不做modprobe 很可能找不到刚拷贝的模块报 “module not found”。卸载内置驱动如果之前加载过sudo modprobe -r pl2303再加载你编译好的驱动sudo modprobe pl2303验证加载路径确保 modprobe 用的是刚从源码编译出来的那个 .ko而不是内核自带的。可以用以下命令查看模块文件路径modinfo pl2303 | grep filenamemodinfo 会显示 filename 字段确认它指向你拷贝的那个 /lib/modules/$(uname -r)/kernel/drivers/usb/serial/pl2303.ko。注意有些系统里可能会同时存在两个 pl2303 模块一个在内核自带的压缩包里一个在你刚拷贝的目录depmod 生成依赖时会以标准目录为准。最后重新插拔设备用 dmesg 看是否出现 “converter detected” 和 “attached to ttyUSB0”。如果还是没有检查你编译出来的模块是否被内核签名机制拒绝。AGX Orin 的默认镜像一般不开启模块签名强制但如果你自己改过内核可能需要处理签名问题这个就比较深了不是三两句能说清建议回头检查 dmesg 中的错误码。5. 串口驱动安装避坑5 条从失败到解决的踩坑记录这一章直接把我见过的翻车场景列出来每条按“现象—原因—解决”写。这些坑基本都从 AGX Orin 和 Ubuntu 22.04 的实际使用中总结出来顺序是按发生频率排的。5.1 现象modprobe 报 module not found 但模块明明存在模块文件明明存在于 /lib/modules/$(uname -r)/kernel/drivers/usb/serial/ 下但执行 modprobe pl2303 还是报错 “Module pl2303 not found”。原因通常是 depmod 没有执行或者你安装的自编译模块文件权限不对。解决先看 /lib/modules/$(uname -r)/modules.dep 里有没有 pl2303 的关键字如果没有执行 sudo depmod -a再 modprobe。另外模块文件的所有者如果不是 root或者文件扩展名不是 .ko 而是 .ko.gz / .ko.xz 但路径没对应也会被 modprobe 忽略。检查一下文件权限和扩展名别把 .ko.gz 直接丢进去当 .ko 用。5.2 现象插上后 dmesg 没有任何输出USB 线不供电有时候 USB 转串口线插到 AGX Orin 的 USB-A 口上完全没有任何反应lsusb 也看不到设备。原因是很多 USB 转串口模块用的供电来自 USB 主机的 VCC如果线材内部接触不良、USB 口供电不足或者正在使用扩展坞的劣质口就会出现“插了个空气”的效果。解决换一个 USB 口最好是直连板载 USB-A 口保证线材质量不要用超过 1 米的延长线如果模块上带电源指示 LED看它亮不亮。可以用一个手边的 USB 小风扇做供电测试排除主机接口问题。这个坑看似低级但最容易在调试一开始浪费半小时。5.3 现象ttyUSB0 出现但 open 失败权限不是 root 的事当 dmesg 显示设备已经 attach 到 ttyUSB0但用串口工具打开时报 “permission denied”即使用户已经在 dialout 组还是打不开。原因是 udev 规则里对设备节点的权限组设置有问题或者该 ttyUSB 节点被旧的 udev 规则覆盖。解决先 ls -l /dev/ttyUSB0 看属主和组如果不是 dialout重载你的 udev 规则如果系统里还有其他 udev 规则比如 ModemManager 抢占了设备需要把串口设备加入 ModemManager 的黑名单或者干脆把 ModemManager 停用。在 AGX Orin 的 Ubuntu 桌面版上ModemManager 会尝试把 USB 串口识别成 modem并锁定设备导致 open 失败或系统日志出现 “ModemManager: Could not grab port”。这个原因排查起来很隐蔽我把停用 ModemManager 的方法写出来sudo systemctl stop ModemManager sudo systemctl disable ModemManager停用后重新插拔大概率就能正常打开。如果是服务器版本没有 ModemManager这步跳过即可。5.4 现象串口输出乱码、丢字节波特率和流控设置怎么查驱动装好了用 minicom 或 Python 读串口数据结果一片乱码或者丢字节。原因不是驱动问题而是通信双方波特率、数据位、停止位、流控不匹配。解决用 stty 查看当前串口参数stty -F /dev/ttyUSB0 -a然后用 stty 临时设置波特率stty -F /dev/ttyUSB0 115200 cs8 -cstopb -ixon这里-F /dev/ttyUSB0指定操作哪个串口115200是波特率cs8表示 8 位数据位-cstopb表示 1 位停止位-ixon表示关闭软件流控。如果对端设备要求 7 位数据位改成 cs7如果要求 2 位停止位去掉 -cstopb 前面的负号。更建议用 minicom 之类的工具配置好参数再测试因为有菜单比命令行直观。还有一点PL2303 的驱动在 ARM64 上可能会有短时批量传输问题如果丢字节严重可以尝试把 USB 转串口的 URB 缓冲调大但这不是常规做法一般不碰。优先排除波特率。5.5 现象编译时报错缺少 linux/compiler.h其实是 headers 装错版本编译驱动源码时报错 fatal error: linux/compiler.h: No such file or directory。原因不是系统没有此文件而是内核头文件包没装全或者 /lib/modules/$(uname -r)/build 软链接指到了错误的目录。解决重新安装与当前内核完全一致的 linux-headers 包然后检查 build 软链接是否有效ls -l /lib/modules/$(uname -r)/build如果执行 apt install linux-headers-$(uname -r) 提示找不到包先 apt search linux-headers-$(uname -r) 确认包名可能你需要安装名为 linux-headers-tegra 的 metapackage。装好后在源码目录重新 make clean make一般能过。这个坑在 AGX Orin 上尤其常见因为定制内核的头文件包名和通用包名不一样不带 5.15-tegra 后缀。6. 装完驱动后的最后一步回环验证和 udev 固定别名驱动模块加载成功不等于通信链路可靠。我的习惯是先把 TX 和 RX 短接做一个回环测试用 Python 的 pyserial 发送一段数据同时读取自己发出去的内容。短接时用一根杜邦线把串口模块的 TXD 和 RXD 引脚接在一起然后执行python3 - EOF import serial ser serial.Serial(/dev/ttyUSB0, 115200, timeout1) test bAGX-Orin-PL2303-loopback-test ser.write(test) data ser.read(len(test)1) print(ok if data test else fmismatch: {data!r}) ser.close() EOF如果打印 ok说明发送和接收路径都没问题驱动、权限、接线全通了。这里读长度是 len(test)1多读一个字节能顺便检查有没有多余脏数据。回环测试是性价比最高的验证手段比在终端里看输出直观得多。通信链路打通后再固化一个固定别名。前面第 3 章讲过用 udev 给设备绑定符号链接这里建议把规则里的 MODE 设成 0660GROUP 设成 dialout避免太开放。规则文件命名从 99- 开头覆盖系统其他规则优先级最高。做完这些如果你还要接多路串口可以在 udev 规则里同时放多条规则分别绑定不同序列号的设备到 /dev/pl2303-rs485 和 /dev/pl2303-debug。这样应用层代码永远不用关心物理口序号换口插也不会乱了。最后还有一个习惯要提每次刷完内核或升级系统固件后内核模块目录会变/lib/modules/$(uname -r)/ 下可能没有你上次装的驱动需要重新编译安装。我自己曾经因为升级系统后忘记重编驱动第二天现场串口全哑排查半天才发现是内核模块目录换了。现在我会把驱动源码和编译命令写成一个脚本放在 /opt/pl2303-build升级后先跑一遍再继续用。希望这个流程能帮你少踩几个坑祝一次点亮。本文还有配套的精品资源点击获取