更新记录
1.0.0(2026-10-30)
- 首次发布:安卓 USB 转串口通信插件,支持 uni-app 与 uni-app x
- 串口枚举、打开(自动申请 USB 授权)、关闭
- 波特率 / 数据位 / 停止位 / 校验位 / 流控设置与运行时修改
- 文本与 Base64 二进制读写、后台持续接收
- DTR / RTS 电平控制、控制线状态读取、硬件收发缓冲区清空
- USB 插拔监听,设备拔出时自动关闭串口
- 资源释放接口,支持页面卸载时一次性回收
平台兼容性
uni-app(4.72)
| Vue2 | Vue2插件版本 | Vue3 | Vue3插件版本 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | × | × | √ | 1.0.0 | √ | 1.0.0 | 5.0 | 1.0.0 | × | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | - | × | × | × | × | - | × | × |
uni-app x(4.72)
| Chrome | Safari | Android | Android插件版本 | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|
| × | × | 5.0 | 1.0.0 | × | × | × |
插件介绍
安卓 USB 转串口(OTG)UTS 原生插件。手机通过 USB Host 直接与 USB 转串口模块通信,无需 root、无需访问 /dev/tty* 节点。
支持 uni-app 与 uni-app x, 无需额外集成任何库。
支持的芯片
| 芯片 / 设备 | driverName |
VID | PID | 端口数 |
|---|---|---|---|---|
| CH340 | Ch34xSerialDriver |
0x1A86 | 0x7523 | 1 |
| CH341A | Ch34xSerialDriver |
0x1A86 | 0x5523 | 1 |
| CP2101 / CP2102 / CP2103 / CP2104 / CP2109 | Cp21xxSerialDriver |
0x10C4 | 0xEA60 | 按接口数(通常 1) |
| CP2105 | Cp21xxSerialDriver |
0x10C4 | 0xEA70 | 2 |
| CP2108 | Cp21xxSerialDriver |
0x10C4 | 0xEA71 | 4 |
| FT232R | FtdiSerialDriver |
0x0403 | 0x6001 | 1 |
| FT232H | FtdiSerialDriver |
0x0403 | 0x6014 | 1 |
| FT230X / FT231X / FT234XD | FtdiSerialDriver |
0x0403 | 0x6015 | 1 |
| FT2232H | FtdiSerialDriver |
0x0403 | 0x6010 | 2 |
| FT4232H | FtdiSerialDriver |
0x0403 | 0x6011 | 4 |
| PL2303(type 01 / T / HX) | ProlificSerialDriver |
0x067B | 0x2303 | 1 |
| PL2303GC / GB / GT / GL / GE / GS | ProlificSerialDriver |
0x067B | 0x23A3 / 0x23B3 / 0x23C3 / 0x23D3 / 0x23E3 / 0x23F3 | 1 |
| CDC-ACM 标准串口(Arduino Uno / Mega、树莓派 Pico、STM32 VCP、ESP32-S3 原生 USB 等) | CdcAcmSerialDriver |
按 USB CDC 接口描述符自动识别,不依赖 VID/PID | — | 按数据接口数 |
| Fibocom L610 / L612(4G 模组 AT 串口) | GsmModemSerialDriver |
0x1782 | 0x4D10 / 0x4D12 | 1 |
| Google CR50(Chromebook 调试串口) | ChromeCcdSerialDriver |
0x18D1 | 0x5014 | 1 |
说明:
- 表中
driverName即getDeviceList返回的ports[i].driverName,可据此在业务里区分芯片型号。 - 插件返回的
vendorId/productId是十进制,例如 CH340 为6790/29987(即 0x1A86 / 0x7523)。 - 多端口芯片(CP2105 / CP2108 / FT2232H / FT4232H 等)在
getDeviceList中会按「设备 × 端口」展开成多条记录,用各自的index分别打开。 - CDC-ACM 靠接口描述符识别而非 VID/PID,因此大量自研 USB 虚拟串口设备(含复合设备)也能直接识别。
- 不在表中的芯片不会被枚举出来,
getDeviceList只会返回能匹配到驱动的设备。
使用场景
- 工控 / 医疗 / 检测设备通过 USB 转串口模块(RS232 / RS485 转 USB)读取传感器与仪器数据
- 小票打印机、电子秤、扫码模块等串口外设与 App 通信
- 现场调试时用手机替代电脑串口助手,收发 AT 指令或自定义协议帧
使用流程
- 注册监听:
registerUsbStateReceiver({ onEvent })监听插拔,拔出时插件会自动关闭当前串口。 - 枚举串口:
getDeviceList({ success })拿到可用串口列表,ports[i].index即后续打开用的下标。 - 打开串口:
openPort({ index, baudRate, ... }),设备未授权时自动弹出系统 USB 授权框,用户允许后自动继续打开。 - 收发数据:
write({ data })发送,startReadLoop({ onData })持续接收,或read({ timeout })单次读取。 - 关闭与释放:
stopReadLoop()→closePort()→releaseResources()(页面onUnload调用)。
运行须知:插件内含预编译的原生串口驱动,必须打自定义基座运行(标准基座不含该依赖);手机需支持 OTG,部分机型需在系统设置中打开 OTG 开关。
用法
import {
getDeviceList,
openPort,
closePort,
read,
write,
setParameters,
setControlSignals,
getControlLines,
clearBuffers,
startReadLoop,
stopReadLoop,
registerUsbStateReceiver,
releaseResources
} from '@/uni_modules/zy-usb-serial'
注册插拔监听
registerUsbStateReceiver({
onEvent: (e) => {
// e.event 取值:deviceAttached(插入) / deviceDetached(拔出,串口已被自动关闭)
if (e.event === 'deviceAttached') {
console.log('串口模块已插入:' + e.deviceName)
} else {
console.log('串口模块已拔出:' + e.deviceName)
}
},
success: (res) => console.log(res.errMsg),
fail: (err) => console.log('监听注册失败 ' + err.errCode + ' ' + err.errMsg)
})
枚举并打开串口
getDeviceList({
success: (res) => {
console.log('可用串口:' + res.ports.length)
// 波特率缺省 115200,数据位 8,停止位 1,校验位 0(无),流控 0(无)
openPort({
index: res.ports[0].index,
baudRate: 115200,
readTimeout: 500, // 该串口默认读超时(毫秒,0 为一直阻塞)
success: (info) => console.log('已打开 ' + info.driverName + ' 端口 ' + info.portIndex),
fail: (err) => console.log('打开失败 ' + err.errCode + ' ' + err.errMsg)
})
},
fail: (err) => console.log('枚举失败 ' + err.errCode + ' ' + err.errMsg)
})
发送数据
// 文本(UTF-8)
write({ data: 'AT+CSQ\r\n', success: (res) => console.log('已发送 ' + res.bytes + ' 字节') })
// 十六进制:空格、逗号、短横线、0x 前缀都会被自动忽略
write({ hex: '00 01 02 03', success: (res) => console.log(res.bytes) })
write({ hex: '0x00,0x01,0x02,0x03', success: (res) => console.log(res.bytes) })
// 二进制:传 Base64,例如 0x00 0x01 0x02 0x03 => 'AAECAw=='
write({ base64: 'AAECAw==', timeout: 2000, success: (res) => console.log(res.bytes) })
持续接收
startReadLoop({
readTimeout: 200, // 缺省取 openPort 的 readTimeout;0 会被按 100 毫秒处理
bufferSize: 4096,
onData: (d) => {
// d.bytes / d.base64 / d.hex / d.text
console.log('收到 ' + d.bytes + ' 字节:' + d.hex)
},
onError: (err) => console.log('接收已停止 ' + err.errCode + ' ' + err.errMsg),
success: (res) => console.log(res.errMsg)
})
stopReadLoop({ success: (res) => console.log(res.errMsg) })
单次读取
read({
timeout: 500, // 缺省取 openPort 的 readTimeout
maxBytes: 256, // 缺省 256,最大 4096
success: (d) => {
// 超时没有数据时 d.bytes 为 0(不算失败)
console.log(d.bytes, d.hex, d.text)
}
})
修改参数与控制线
setParameters({
baudRate: 9600,
success: (info) => console.log(info.baudRate + ' ' + info.dataBits + ' ' + info.parity)
})
setControlSignals({ dtr: true, rts: false, success: (lines) => console.log(lines) })
getControlLines({ success: (lines) => console.log(lines.cd, lines.cts, lines.dsr, lines.ri) })
clearBuffers({ input: true, output: true, success: (res) => console.log(res.errMsg) })
DTR / RTS 控制线说明
DTR、RTS 是两根调制解调器控制线,只用于给对端设备打电平信号,不承载业务数据,通过 setControlSignals 设置、getControlLines 回读。openPort 缺省已把两者置高(dtr: true, rts: true)。
| 信号 | 全称 | 方向 | 含义 |
|---|---|---|---|
dtr |
Data Terminal Ready | 手机 → 设备 | 主机已就绪 / 在线 |
rts |
Request To Send | 手机 → 设备 | 请求发送 |
cd |
Carrier Detect | 设备 → 手机 | 载波检测(只读) |
cts |
Clear To Send | 设备 → 手机 | 清除发送(只读) |
dsr |
Data Set Ready | 设备 → 手机 | 数据装置就绪(只读) |
ri |
Ring Indicator | 设备 → 手机 | 振铃指示(只读) |
常见用途:
- 给 MCU 自动复位 / 进下载模式:ESP8266、ESP32、Arduino 的下载电路把
DTR、RTS接到EN、IO0,靠两根线的电平组合拉出复位时序,烧录工具因此无需手动按复位键。 - 当普通 GPIO 用:未开硬件流控时,串口屏、继电器板、传感器常把
DTR/RTS当额外控制线(如 RS485 收发方向、唤醒设备、切换工作模式)。 - 满足设备的「主机在线」判断:部分 4G 模组、串口打印机检测不到
DTR置高会一直不回数据,现象是「发指令没反应」,把DTR打开即可。
注意事项:
- 只有
flowControl = 0(无硬件流控)时手动设置rts才有意义;开启 RTS/CTS 流控后RTS由串口芯片自动管理,手动设置会被忽略或失败。 - 部分芯片或驱动不支持这两根线,
setControlSignals会走fail回调,错误码 9220014(串口不支持该操作)。 cd/cts/dsr/ri是输入方向,只能读;getControlLines一次取回全部四路,比逐个读取节省 USB 请求。setControlSignals至少传一个字段,未传的字段保持当前电平;成功回调返回设置后的四路控制线状态。
关闭与释放
closePort({ success: (res) => console.log(res.errMsg) })
releaseResources({ success: (res) => console.log(res.errMsg) })
插件方法
| 方法 | 说明 | 回调 |
|---|---|---|
getDeviceList(options) |
枚举可用串口,多端口设备按「设备 × 端口」展开 | 成功 ports 为串口数组 |
openPort(options) |
打开串口,缺权限时自动弹窗并在授权后继续打开(超时 60 秒) | 成功返回当前串口参数 |
closePort(options) |
关闭当前串口并停止后台接收 | 成功 { errMsg } |
read(options) |
同步读取一次,timeout 缺省取 openPort 的 readTimeout |
成功返回数据体 |
write(options) |
发送数据,hex(十六进制)/ data(文本)/ base64(二进制)三选一,同时传时优先 hex |
成功 { bytes } |
setParameters(options) |
运行时修改波特率 / 数据位 / 停止位 / 校验位 / 流控,只传需要改的字段 | 成功返回当前串口参数 |
setControlSignals(options) |
设置 DTR / RTS 电平,至少传一个 | 成功返回控制线状态 |
getControlLines(options) |
读取控制线状态 | 成功返回控制线状态 |
clearBuffers(options) |
清空硬件收发缓冲区,input / output 缺省 true |
成功 { errMsg } |
startReadLoop(options) |
启动后台持续接收,数据持续回调 onData |
启动结果一次性回调 |
stopReadLoop(options) |
停止后台持续接收 | 成功 { errMsg } |
registerUsbStateReceiver(options) |
注册 USB 插拔监听,拔出时自动关闭串口 | 注册结果一次性回调,事件持续回调 |
releaseResources(options) |
停止接收、关闭串口、注销监听 | 成功 { errMsg } |
write 的三种数据来源
| 字段 | 类型 | 说明 | 优先级 |
|---|---|---|---|
hex |
string |
十六进制字符串,如 '00 01 FF'、'0x00,0x01'、'0001ff';空格 / 逗号 / 短横线 / 冒号 / 下划线 / 换行等分隔符与 0x 前缀自动忽略,有效位数为奇数或含非法字符时报 9220001 |
最高 |
base64 |
string |
Base64(不换行)编码的二进制,如 'AAECAw==' |
中 |
data |
string |
文本,按 UTF-8 编码后写入,如 'AT+CSQ\r\n' |
最低 |
三者都为空时报 9220001;实际写入字节数在成功回调的
bytes中返回,写超时缺省 2000 毫秒。
串口信息结构(getDeviceList 的 ports 元素)
{
index : 0, // 端口列表下标,openPort 时作为 index 传入
deviceIndex : 0, // 设备在 USB 设备列表中的下标
portIndex : 0, // 端口在设备内的下标
portCount : 1, // 设备内端口总数
deviceId : 1002, // 系统分配的设备 ID
deviceName : '/dev/bus/usb/001/002',
vendorId : 6790, // 厂商 ID(十进制)
productId : 29987, // 产品 ID(十进制)
productName : 'USB Serial', // 可能为 null
manufacturerName : 'wch.cn', // 可能为 null
serialNumber : null, // 未授权或无序列号时为 null
driverName : 'Ch34xSerialDriver' // 匹配到的驱动名
}
打开 / 参数结果结构(openPort、setParameters)
{
index : 0, // 端口列表下标
deviceId : 1002,
vendorId : 6790,
productId : 29987,
driverName : 'Ch34xSerialDriver',
portIndex : 0,
baudRate : 115200, // 波特率
dataBits : 8, // 数据位:5 / 6 / 7 / 8
stopBits : 1, // 停止位:1(1 位) / 3(1.5 位) / 2(2 位)
parity : 0, // 校验位:0 无 / 1 奇 / 2 偶 / 3 Mark / 4 Space
flowControl : 0 // 流控:0 无 / 1 RTS-CTS / 2 DTR-DSR / 3 XON-XOFF / 4 XON-XOFF 内联
}
数据体结构(read 成功、startReadLoop 的 onData)
{
bytes : 12, // 本次字节数;read 超时时为 0
base64 : '...', // Base64(不换行)编码
hex : '41542b43', // 十六进制小写、无分隔符
text : 'AT+C' // 按 UTF-8 解码的文本(二进制数据可能是乱码,请用 base64)
}
控制线结构(getControlLines 成功、setControlSignals 成功)
{
cd : false, // 载波检测
cts : false, // 清除发送
dsr : false, // 数据装置就绪
ri : false // 振铃指示
}
插拔事件结构(registerUsbStateReceiver 的 onEvent)
{
event : 'deviceAttached', // deviceAttached(插入) / deviceDetached(拔出)
deviceId : 1002,
deviceName : '/dev/bus/usb/001/002',
vendorId : 6790,
productId : 29987
}
错误码
| 错误码 | 说明 |
|---|---|
| 9220001 | 参数错误 |
| 9220002 | 串口未打开,请先调用 openPort |
| 9220003 | 未找到可用的 USB 串口设备 |
| 9220004 | USB 权限被拒绝 |
| 9220005 | 打开串口失败 |
| 9220006 | 串口读写失败 |
| 9220007 | 设置串口参数失败 |
| 9220008 | 关闭串口失败 |
| 9220009 | 应用上下文获取失败 |
| 9220010 | 等待 USB 授权超时 |
| 9220011 | 后台读取启动失败 |
| 9220012 | USB 设备已拔出 |
| 9220013 | 释放资源失败 |
| 9220014 | 串口不支持该操作 |
| 9220015 | 串口设备被占用 |
权限说明
本插件不需要任何运行时权限。
| 权限 | 用途 |
|---|---|
android.hardware.usb.host(硬件特性,非运行时权限) |
声明设备需要 USB Host 能力,用于访问 USB 转串口模块 |
说明:USB 设备访问通过系统授权弹窗逐设备授权,不涉及存储、定位等运行时权限;手机需支持 OTG。

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 62
赞赏 0
下载 12729113
赞赏 1958
赞赏
京公网安备:11010802035340号