1266 lines
24 KiB
Markdown
1266 lines
24 KiB
Markdown
# CH34 Flutter 插件使用手册
|
||
|
||
> 版本: 1.0.0
|
||
> 支持的芯片: CH340/CH341/CH342/CH343/CH344/CH347/CH9101/CH9102/CH9103/CH9104/CH9143
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [简介](#一简介)
|
||
2. [安装与配置](#二安装与配置)
|
||
3. [快速开始](#三快速开始)
|
||
4. [API 参考](#四api-参考)
|
||
5. [类型定义](#五类型定义)
|
||
6. [完整示例](#六完整示例)
|
||
7. [常见问题](#七常见问题)
|
||
|
||
---
|
||
|
||
## 一、简介
|
||
|
||
`ch34` 是一个 Flutter 插件,为 WCH CH34X 系列 USB 转串口芯片提供 Flutter 接口支持。通过该插件,Flutter 应用可以与 CH34X 芯片进行串口通信。
|
||
|
||
### 支持的芯片型号
|
||
|
||
| 芯片型号 | 说明 |
|
||
|---------|------|
|
||
| CH340 | 单串口 USB 转串口芯片 |
|
||
| CH341 | 并口/串口 USB 转换芯片 |
|
||
| CH342 | 双串口 USB 转串口芯片 |
|
||
| CH343 | 增强型单串口芯片 |
|
||
| CH344 | 四串口 USB 转串口芯片 |
|
||
| CH347 | 高速 USB 转串口芯片 |
|
||
| CH9101 | 单串口 USB 转串口芯片 |
|
||
| CH9102 | 双串口 USB 转串口芯片 |
|
||
| CH9103 | 四串口 USB 转串口芯片 |
|
||
| CH9104 | 八串口 USB 转串口芯片 |
|
||
| CH9143 | 多串口 USB 转串口芯片 |
|
||
|
||
### 系统要求
|
||
|
||
- Android 4.4 及以上版本
|
||
- 支持 USB Host 或 OTG 功能的 Android 设备
|
||
|
||
---
|
||
|
||
## 二、安装与配置
|
||
|
||
### 2.1 添加依赖
|
||
|
||
在 `pubspec.yaml` 中添加:
|
||
|
||
```yaml
|
||
dependencies:
|
||
ch34: ^1.0.0
|
||
```
|
||
|
||
### 2.2 导入插件
|
||
|
||
```dart
|
||
import 'package:ch34/ch34.dart';
|
||
```
|
||
|
||
### 2.3 初始化配置
|
||
|
||
在应用启动时进行初始化配置:
|
||
|
||
```dart
|
||
// 开启调试模式(可选,默认关闭)
|
||
await Ch34Manager.setDebug(true);
|
||
|
||
// 设置全局读取超时时间(可选,默认 0 表示异步传输)
|
||
await Ch34Manager.setReadTimeout(1000); // 1000ms
|
||
```
|
||
|
||
---
|
||
|
||
## 三、快速开始
|
||
|
||
### 3.1 基本使用流程
|
||
|
||
```dart
|
||
// 1. 枚举可用设备
|
||
final devices = await Ch34Manager.enumDevice();
|
||
if (devices.isEmpty) {
|
||
print('未找到 CH34X 设备');
|
||
return;
|
||
}
|
||
|
||
// 2. 选择设备
|
||
final device = devices.first;
|
||
print('找到设备: ${device.deviceName}, 芯片: ${device.chipType}');
|
||
|
||
// 3. 打开设备
|
||
final opened = await Ch34Manager.openDevice(device.deviceName);
|
||
if (!opened) {
|
||
print('打开设备失败');
|
||
return;
|
||
}
|
||
|
||
// 4. 设置串口参数
|
||
await Ch34Manager.setSerialParameter(
|
||
device.deviceName,
|
||
0, // 串口号(从 0 开始)
|
||
const SerialParameter(
|
||
baud: 9600,
|
||
dataBits: DataBits.bits8,
|
||
stopBits: StopBits.one,
|
||
parity: Parity.none,
|
||
hardwareFlowControl: false,
|
||
),
|
||
);
|
||
|
||
// 5. 注册数据回调
|
||
Ch34Manager.registerDataCallback(
|
||
device.deviceName,
|
||
0,
|
||
(data) {
|
||
print('收到数据: $data');
|
||
},
|
||
);
|
||
|
||
// 6. 发送数据
|
||
await Ch34Manager.writeData(
|
||
device.deviceName,
|
||
0,
|
||
Uint8List.fromList([0x01, 0x02, 0x03]),
|
||
);
|
||
|
||
// 7. 使用完毕后断开
|
||
await Ch34Manager.disconnect(device.deviceName);
|
||
```
|
||
|
||
### 3.2 权限处理
|
||
|
||
```dart
|
||
// 请求 USB 设备权限
|
||
final granted = await Ch34Manager.requestPermission(device.deviceName);
|
||
if (!granted) {
|
||
print('USB 权限被拒绝');
|
||
return;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、API 参考
|
||
|
||
### 4.1 基础方法
|
||
|
||
#### getPlatformVersion
|
||
|
||
获取平台版本。
|
||
|
||
```dart
|
||
static Future<String?> getPlatformVersion()
|
||
```
|
||
|
||
**返回值**: 平台版本字符串
|
||
|
||
---
|
||
|
||
### 4.2 设备枚举与识别
|
||
|
||
#### enumDevice
|
||
|
||
枚举当前所有可用的 USB 设备。
|
||
|
||
```dart
|
||
static Future<List<UsbDeviceInfo>> enumDevice()
|
||
```
|
||
|
||
**返回值**: 可用 USB 设备列表
|
||
**异常**: `Ch34Exception` - 枚举失败时抛出
|
||
|
||
#### getChipType
|
||
|
||
获取指定设备的芯片型号。
|
||
|
||
```dart
|
||
static Future<String?> getChipType(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: 芯片型号字符串,`null` 表示无法识别
|
||
|
||
---
|
||
|
||
### 4.3 设备打开与权限
|
||
|
||
#### openDevice
|
||
|
||
打开 USB 设备。
|
||
|
||
```dart
|
||
static Future<bool> openDevice(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: `true` 成功,`false` 失败
|
||
|
||
#### requestPermission
|
||
|
||
申请 USB 设备的权限。
|
||
|
||
```dart
|
||
static Future<bool> requestPermission(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: `true` 已授权,`false` 被拒绝
|
||
|
||
---
|
||
|
||
### 4.4 USB 状态监听
|
||
|
||
#### setUsbStateListener
|
||
|
||
注册 USB 设备插拔状态监听。
|
||
|
||
```dart
|
||
static void setUsbStateListener(
|
||
void Function(String deviceName, bool connected) onStateChanged,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `onStateChanged` - 状态变化回调函数
|
||
|
||
#### removeUsbStateListener
|
||
|
||
移除 USB 状态监听。
|
||
|
||
```dart
|
||
static void removeUsbStateListener()
|
||
```
|
||
|
||
---
|
||
|
||
### 4.5 串口信息
|
||
|
||
#### getSerialCount
|
||
|
||
获取设备的串口数目。
|
||
|
||
```dart
|
||
static Future<int> getSerialCount(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: 串口数目,`-1` 表示读取芯片型号失败
|
||
|
||
#### getSerialBaud
|
||
|
||
获取串口波特率(仅 CH9114 系列有效)。
|
||
|
||
```dart
|
||
static Future<int> getSerialBaud(String deviceName, int serialNumber)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
|
||
**返回值**: 大于 0 表示波特率,小于 0 表示出错
|
||
|
||
#### getChipMasterFrequency
|
||
|
||
获取芯片主频(仅 CH9114 系列有效)。
|
||
|
||
```dart
|
||
static Future<ChipMasterFrequency> getChipMasterFrequency(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: 芯片主频信息对象
|
||
|
||
#### enableSerial
|
||
|
||
打开或关闭串口(仅 CH9114 系列有效)。
|
||
|
||
```dart
|
||
static Future<bool> enableSerial(
|
||
String deviceName,
|
||
int serialNumber,
|
||
bool enable,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `enable` - `true` 打开,`false` 关闭
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
---
|
||
|
||
### 4.6 串口参数设置
|
||
|
||
#### setSerialParameter
|
||
|
||
设置串口参数。
|
||
|
||
```dart
|
||
static Future<bool> setSerialParameter(
|
||
String deviceName,
|
||
int serialNumber,
|
||
SerialParameter parameter,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号(从 0 开始)
|
||
- `parameter` - 串口参数配置
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
---
|
||
|
||
### 4.7 数据读写
|
||
|
||
#### writeData
|
||
|
||
发送串口数据(同步发送)。
|
||
|
||
```dart
|
||
static Future<int> writeData(
|
||
String deviceName,
|
||
int serialNumber,
|
||
Uint8List data, {
|
||
int timeout = 0,
|
||
})
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `data` - 要发送的数据
|
||
- `timeout` - 超时时间(毫秒),0 表示不超时
|
||
|
||
**返回值**: 实际发送的字节数
|
||
|
||
#### asyncWriteData
|
||
|
||
发送串口数据(异步发送)。
|
||
|
||
```dart
|
||
static Future<void> asyncWriteData(
|
||
String deviceName,
|
||
int serialNumber,
|
||
Uint8List data,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `data` - 要发送的数据
|
||
|
||
**说明**: 将数据加入缓存持续发送,不返回状态和结果
|
||
|
||
#### readData
|
||
|
||
阻塞读取串口数据。
|
||
|
||
```dart
|
||
static Future<Uint8List> readData(
|
||
String deviceName,
|
||
int serialNumber,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
|
||
**返回值**: 读取到的数据
|
||
|
||
#### readDataWithTimeout
|
||
|
||
主动读取串口数据(带超时参数)。
|
||
|
||
```dart
|
||
static Future<Uint8List> readDataWithTimeout(
|
||
String deviceName,
|
||
int serialNumber,
|
||
int vTime,
|
||
int vMin,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `vTime` - 等待时间(毫秒)
|
||
- `vMin` - 读取的最小字节数
|
||
|
||
**返回值**: 读取到的数据
|
||
|
||
**读取行为说明**:
|
||
- `vTime>0, vMin>0`: 阻塞直到读取到第一个字符后开始计时,时间到或已读够 vMin 个字符则返回
|
||
- `vTime>0, vMin=0`: 读到数据立即返回,否则最多等待 vTime
|
||
- `vTime=0, vMin>0`: 一直阻塞直到读到 vMin 个字符后返回
|
||
|
||
#### registerDataCallback
|
||
|
||
注册串口数据回调。
|
||
|
||
```dart
|
||
static Future<void> registerDataCallback(
|
||
String deviceName,
|
||
int serialNumber,
|
||
void Function(Uint8List data) onData,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `onData` - 数据接收回调函数
|
||
|
||
**说明**: 注册后数据自动推送,不需要主动调用 `readData`。**推荐使用此方式接收数据**。
|
||
|
||
#### removeDataCallback
|
||
|
||
取消注册串口数据回调。
|
||
|
||
```dart
|
||
static void removeDataCallback(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
---
|
||
|
||
### 4.8 连接状态
|
||
|
||
#### isConnected
|
||
|
||
判断 USB 设备是否已经连接。
|
||
|
||
```dart
|
||
static Future<bool> isConnected(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: `true` 已连接,`false` 未连接
|
||
|
||
#### getConnectedDevices
|
||
|
||
获取当前已经打开的设备列表。
|
||
|
||
```dart
|
||
static Future<List<String>> getConnectedDevices()
|
||
```
|
||
|
||
**返回值**: 已打开的设备名称列表
|
||
|
||
---
|
||
|
||
### 4.9 断开与关闭
|
||
|
||
#### disconnect
|
||
|
||
断开 USB 设备的连接。
|
||
|
||
```dart
|
||
static Future<void> disconnect(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
#### close
|
||
|
||
释放资源,关闭所有串口设备。
|
||
|
||
```dart
|
||
static Future<void> close()
|
||
```
|
||
|
||
---
|
||
|
||
### 4.10 GPIO 功能
|
||
|
||
#### isSupportGpio
|
||
|
||
查询设备是否支持 GPIO 功能。
|
||
|
||
```dart
|
||
static Future<bool> isSupportGpio(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: `true` 支持,`false` 不支持
|
||
|
||
#### queryGpioCount
|
||
|
||
查询该 USB 设备的 GPIO 数目。
|
||
|
||
```dart
|
||
static Future<int> queryGpioCount(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: GPIO 数目
|
||
|
||
#### queryGpioStatus
|
||
|
||
查询指定 GPIO 的状态。
|
||
|
||
```dart
|
||
static Future<GpioStatus> queryGpioStatus(
|
||
String deviceName,
|
||
int gpioIndex,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `gpioIndex` - GPIO 编号(从 0 开始)
|
||
|
||
**返回值**: GPIO 状态
|
||
|
||
#### queryAllGpioStatus
|
||
|
||
查询所有 GPIO 状态。
|
||
|
||
```dart
|
||
static Future<List<GpioStatus>> queryAllGpioStatus(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
**返回值**: 全部 GPIO 状态列表
|
||
|
||
#### enableGpio
|
||
|
||
使能指定 GPIO。
|
||
|
||
```dart
|
||
static Future<bool> enableGpio(
|
||
String deviceName,
|
||
int gpioIndex,
|
||
bool enable,
|
||
GpioDirection direction,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `gpioIndex` - GPIO 编号
|
||
- `enable` - `true` 使能,`false` 关闭
|
||
- `direction` - GPIO 方向
|
||
|
||
**返回值**: `true` 使能成功,`false` 使能失败
|
||
|
||
#### setGpioVal
|
||
|
||
设置指定 GPIO 的电平值。
|
||
|
||
```dart
|
||
static Future<bool> setGpioVal(
|
||
String deviceName,
|
||
int gpioIndex,
|
||
GpioValue value,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `gpioIndex` - GPIO 编号
|
||
- `value` - GPIO 电平值
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
#### getGpioVal
|
||
|
||
获取指定 GPIO 的电平值。
|
||
|
||
```dart
|
||
static Future<GpioValue> getGpioVal(
|
||
String deviceName,
|
||
int gpioIndex,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `gpioIndex` - GPIO 编号
|
||
|
||
**返回值**: GPIO 电平值
|
||
|
||
---
|
||
|
||
### 4.11 信号控制
|
||
|
||
#### setDtr
|
||
|
||
设置 DTR 信号。
|
||
|
||
```dart
|
||
static Future<bool> setDtr(
|
||
String deviceName,
|
||
int serialNumber,
|
||
bool valid,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `valid` - 是否有效(低电平有效)
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
#### setRts
|
||
|
||
设置 RTS 信号。
|
||
|
||
```dart
|
||
static Future<bool> setRts(
|
||
String deviceName,
|
||
int serialNumber,
|
||
bool valid,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `valid` - 是否有效(低电平有效)
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
#### setBreakSignal
|
||
|
||
设置 Break 信号。
|
||
|
||
```dart
|
||
static Future<bool> setBreakSignal(
|
||
String deviceName,
|
||
int serialNumber,
|
||
bool valid,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `valid` - 是否有效(低电平有效)
|
||
|
||
**返回值**: `true` 设置成功,`false` 设置失败
|
||
|
||
---
|
||
|
||
### 4.12 Modem 状态回调
|
||
|
||
#### registerModemStatusCallback
|
||
|
||
注册 Modem 控制信号状态回调。
|
||
|
||
```dart
|
||
static Future<void> registerModemStatusCallback(
|
||
String deviceName,
|
||
void Function(ModemStatus status) onModemStatus,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `onModemStatus` - Modem 状态变化回调
|
||
|
||
#### removeModemStatusCallback
|
||
|
||
移除 Modem 状态回调。
|
||
|
||
```dart
|
||
static void removeModemStatusCallback(String deviceName)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
|
||
---
|
||
|
||
### 4.13 错误查询
|
||
|
||
#### querySerialErrorCount
|
||
|
||
查询串口错误状态。
|
||
|
||
```dart
|
||
static Future<int> querySerialErrorCount(
|
||
String deviceName,
|
||
int serialNumber,
|
||
SerialErrorType errorType,
|
||
)
|
||
```
|
||
|
||
**参数**:
|
||
- `deviceName` - 设备名称
|
||
- `serialNumber` - 串口号
|
||
- `errorType` - 错误类型
|
||
|
||
**返回值**: 该种错误出现的次数
|
||
|
||
---
|
||
|
||
### 4.14 全局配置
|
||
|
||
#### setReadTimeout
|
||
|
||
设置读取超时时间。
|
||
|
||
```dart
|
||
static Future<void> setReadTimeout(int timeout)
|
||
```
|
||
|
||
**参数**:
|
||
- `timeout` - 超时时间(毫秒)
|
||
|
||
**说明**: 全局有效,应在 APP 初始化时调用
|
||
|
||
#### addNewHardware
|
||
|
||
添加自定义硬件 VID/PID。
|
||
|
||
```dart
|
||
static Future<void> addNewHardware(
|
||
int vid,
|
||
int pid, {
|
||
String? chipType,
|
||
})
|
||
```
|
||
|
||
**参数**:
|
||
- `vid` - 硬件 VID
|
||
- `pid` - 硬件 PID
|
||
- `chipType` - 芯片类型(可选)
|
||
|
||
#### setDebug
|
||
|
||
设置调试模式。
|
||
|
||
```dart
|
||
static Future<void> setDebug(bool enabled)
|
||
```
|
||
|
||
**参数**:
|
||
- `enabled` - `true` 开启,`false` 关闭
|
||
|
||
#### isDebugMode
|
||
|
||
返回当前是否处于调试模式。
|
||
|
||
```dart
|
||
static Future<bool> isDebugMode()
|
||
```
|
||
|
||
**返回值**: `true` 处于调试模式,`false` 不处于
|
||
|
||
---
|
||
|
||
## 五、类型定义
|
||
|
||
### 5.1 枚举类型
|
||
|
||
#### DataBits - 数据位
|
||
|
||
```dart
|
||
enum DataBits {
|
||
bits5(5), // 5 位数据位
|
||
bits6(6), // 6 位数据位
|
||
bits7(7), // 7 位数据位
|
||
bits8(8); // 8 位数据位(默认)
|
||
}
|
||
```
|
||
|
||
#### StopBits - 停止位
|
||
|
||
```dart
|
||
enum StopBits {
|
||
one(1), // 1 位停止位(默认)
|
||
two(2), // 2 位停止位
|
||
}
|
||
```
|
||
|
||
#### Parity - 校验位
|
||
|
||
```dart
|
||
enum Parity {
|
||
none(0), // 无校验(默认)
|
||
odd(1), // 奇校验
|
||
even(2), // 偶校验
|
||
mark(3), // 标记校验
|
||
space(4), // 空格校验
|
||
}
|
||
```
|
||
|
||
#### GpioDirection - GPIO 方向
|
||
|
||
```dart
|
||
enum GpioDirection {
|
||
inDir, // 输入方向
|
||
outDir, // 输出方向
|
||
}
|
||
```
|
||
|
||
#### GpioValue - GPIO 电平值
|
||
|
||
```dart
|
||
enum GpioValue {
|
||
low, // 低电平
|
||
high, // 高电平
|
||
}
|
||
```
|
||
|
||
#### SerialErrorType - 串口错误类型
|
||
|
||
```dart
|
||
enum SerialErrorType {
|
||
framingError, // 帧错误
|
||
parityError, // 校验错误
|
||
overrunError, // 溢出错误
|
||
breakInterrupt, // 中断错误
|
||
}
|
||
```
|
||
|
||
### 5.2 数据类
|
||
|
||
#### SerialParameter - 串口参数
|
||
|
||
```dart
|
||
class SerialParameter {
|
||
const SerialParameter({
|
||
this.baud = 115200, // 波特率
|
||
this.dataBits = DataBits.bits8, // 数据位
|
||
this.stopBits = StopBits.one, // 停止位
|
||
this.parity = Parity.none, // 校验位
|
||
this.hardwareFlowControl = false, // 硬件流控
|
||
});
|
||
}
|
||
```
|
||
|
||
**常用波特率**: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
|
||
|
||
#### UsbDeviceInfo - USB 设备信息
|
||
|
||
```dart
|
||
class UsbDeviceInfo {
|
||
final String deviceName; // 设备名称
|
||
final int productId; // 产品 ID (PID)
|
||
final int vendorId; // 厂商 ID (VID)
|
||
final int serialCount; // 串口数量
|
||
final String? chipType; // 芯片型号(如果识别)
|
||
}
|
||
```
|
||
|
||
#### GpioStatus - GPIO 状态
|
||
|
||
```dart
|
||
class GpioStatus {
|
||
final int index; // GPIO 编号
|
||
final GpioDirection direction; // 方向
|
||
final GpioValue value; // 电平值
|
||
final bool enabled; // 是否已使能
|
||
}
|
||
```
|
||
|
||
#### ChipMasterFrequency - 芯片主频
|
||
|
||
```dart
|
||
class ChipMasterFrequency {
|
||
final int frequency; // 芯片主频(Hz)
|
||
final bool switchEnable; // 是否允许切换主频
|
||
final int coStatus; // 晶振状态
|
||
}
|
||
```
|
||
|
||
#### ModemStatus - Modem 状态
|
||
|
||
```dart
|
||
class ModemStatus {
|
||
final bool cts; // Clear To Send
|
||
final bool dsr; // Data Set Ready
|
||
final bool ri; // Ring Indicator
|
||
final bool dcd; // Data Carrier Detect
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、完整示例
|
||
|
||
### 6.1 设备扫描与管理
|
||
|
||
```dart
|
||
import 'package:ch34/ch34.dart';
|
||
import 'dart:typed_data';
|
||
|
||
class SerialDeviceManager {
|
||
static List<UsbDeviceInfo> _devices = [];
|
||
|
||
/// 扫描并连接设备
|
||
static Future<void> scanAndConnect() async {
|
||
try {
|
||
// 获取已连接设备
|
||
final connected = await Ch34Manager.getConnectedDevices();
|
||
print('已连接设备: $connected');
|
||
|
||
// 枚举所有可用设备
|
||
_devices = await Ch34Manager.enumDevice();
|
||
print('发现 ${_devices.length} 个设备');
|
||
|
||
for (final device in _devices) {
|
||
print('设备: ${device.deviceName}');
|
||
print(' VID: 0x${device.vendorId.toRadixString(16).toUpperCase().padLeft(4, '0')}');
|
||
print(' PID: 0x${device.productId.toRadixString(16).toUpperCase().padLeft(4, '0')}');
|
||
print(' 芯片: ${device.chipType ?? "未知"}');
|
||
print(' 串口数: ${device.serialCount}');
|
||
}
|
||
} on Ch34Exception catch (e) {
|
||
print('设备扫描失败: $e');
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.2 串口通信封装
|
||
|
||
```dart
|
||
class SerialPortService {
|
||
String? _deviceName;
|
||
int _serialNumber = 0;
|
||
bool _isConnected = false;
|
||
|
||
/// 打开串口
|
||
Future<bool> open(String deviceName, {int baudRate = 9600}) async {
|
||
try {
|
||
// 请求权限
|
||
final granted = await Ch34Manager.requestPermission(deviceName);
|
||
if (!granted) {
|
||
return false;
|
||
}
|
||
|
||
// 打开设备
|
||
final opened = await Ch34Manager.openDevice(deviceName);
|
||
if (!opened) {
|
||
return false;
|
||
}
|
||
|
||
// 设置参数
|
||
final configured = await Ch34Manager.setSerialParameter(
|
||
deviceName,
|
||
_serialNumber,
|
||
SerialParameter(
|
||
baud: baudRate,
|
||
dataBits: DataBits.bits8,
|
||
stopBits: StopBits.one,
|
||
parity: Parity.none,
|
||
),
|
||
);
|
||
|
||
if (!configured) {
|
||
await Ch34Manager.disconnect(deviceName);
|
||
return false;
|
||
}
|
||
|
||
_deviceName = deviceName;
|
||
_isConnected = true;
|
||
return true;
|
||
} catch (e) {
|
||
print('打开串口失败: $e');
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// 关闭串口
|
||
Future<void> close() async {
|
||
if (_deviceName != null) {
|
||
Ch34Manager.removeDataCallback(_deviceName!);
|
||
await Ch34Manager.disconnect(_deviceName!);
|
||
_deviceName = null;
|
||
_isConnected = false;
|
||
}
|
||
}
|
||
|
||
/// 发送数据
|
||
Future<int> send(List<int> data) async {
|
||
if (!_isConnected || _deviceName == null) {
|
||
throw StateError('串口未连接');
|
||
}
|
||
|
||
return await Ch34Manager.writeData(
|
||
_deviceName!,
|
||
_serialNumber,
|
||
Uint8List.fromList(data),
|
||
);
|
||
}
|
||
|
||
/// 异步发送数据
|
||
Future<void> sendAsync(List<int> data) async {
|
||
if (!_isConnected || _deviceName == null) {
|
||
throw StateError('串口未连接');
|
||
}
|
||
|
||
await Ch34Manager.asyncWriteData(
|
||
_deviceName!,
|
||
_serialNumber,
|
||
Uint8List.fromList(data),
|
||
);
|
||
}
|
||
|
||
/// 注册数据接收回调
|
||
Future<void> onData(void Function(Uint8List data) callback) async {
|
||
if (_deviceName == null) {
|
||
throw StateError('串口未连接');
|
||
}
|
||
|
||
await Ch34Manager.registerDataCallback(
|
||
_deviceName!,
|
||
_serialNumber,
|
||
callback,
|
||
);
|
||
}
|
||
|
||
/// 获取连接状态
|
||
bool get isConnected => _isConnected;
|
||
}
|
||
```
|
||
|
||
### 6.3 GPIO 控制示例
|
||
|
||
```dart
|
||
class GpioController {
|
||
/// 配置并设置 GPIO
|
||
static Future<void> configureGpio(
|
||
String deviceName,
|
||
int gpioIndex,
|
||
) async {
|
||
// 检查是否支持 GPIO
|
||
final supported = await Ch34Manager.isSupportGpio(deviceName);
|
||
if (!supported) {
|
||
print('设备不支持 GPIO 功能');
|
||
return;
|
||
}
|
||
|
||
// 查询 GPIO 数量
|
||
final count = await Ch34Manager.queryGpioCount(deviceName);
|
||
if (gpioIndex >= count) {
|
||
print('GPIO 编号超出范围');
|
||
return;
|
||
}
|
||
|
||
// 使能 GPIO(输出方向)
|
||
final enabled = await Ch34Manager.enableGpio(
|
||
deviceName,
|
||
gpioIndex,
|
||
true,
|
||
GpioDirection.outDir,
|
||
);
|
||
|
||
if (!enabled) {
|
||
print('使能 GPIO 失败');
|
||
return;
|
||
}
|
||
|
||
// 设置高电平
|
||
await Ch34Manager.setGpioVal(
|
||
deviceName,
|
||
gpioIndex,
|
||
GpioValue.high,
|
||
);
|
||
|
||
// 读取电平值验证
|
||
final value = await Ch34Manager.getGpioVal(deviceName, gpioIndex);
|
||
print('GPIO $gpioIndex 电平: $value');
|
||
}
|
||
|
||
/// 查询所有 GPIO 状态
|
||
static Future<void> printAllGpioStatus(String deviceName) async {
|
||
final statuses = await Ch34Manager.queryAllGpioStatus(deviceName);
|
||
for (final status in statuses) {
|
||
print('GPIO ${status.index}: '
|
||
'方向=${status.direction}, '
|
||
'电平=${status.value}, '
|
||
'使能=${status.enabled}');
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.4 Modem 状态监听
|
||
|
||
```dart
|
||
class ModemMonitor {
|
||
static Future<void> startMonitoring(String deviceName) async {
|
||
await Ch34Manager.registerModemStatusCallback(
|
||
deviceName,
|
||
(ModemStatus status) {
|
||
print('Modem 状态变化:');
|
||
print(' CTS: ${status.cts}');
|
||
print(' DSR: ${status.dsr}');
|
||
print(' RI: ${status.ri}');
|
||
print(' DCD: ${status.dcd}');
|
||
},
|
||
);
|
||
}
|
||
|
||
static void stopMonitoring(String deviceName) {
|
||
Ch34Manager.removeModemStatusCallback(deviceName);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.5 错误检测
|
||
|
||
```dart
|
||
class ErrorDetector {
|
||
static Future<void> checkErrors(String deviceName, int serialNumber) async {
|
||
final framingErrors = await Ch34Manager.querySerialErrorCount(
|
||
deviceName,
|
||
serialNumber,
|
||
SerialErrorType.framingError,
|
||
);
|
||
|
||
final parityErrors = await Ch34Manager.querySerialErrorCount(
|
||
deviceName,
|
||
serialNumber,
|
||
SerialErrorType.parityError,
|
||
);
|
||
|
||
print('帧错误: $framingErrors, 校验错误: $parityErrors');
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 七、常见问题
|
||
|
||
### 7.1 找不到设备
|
||
|
||
**问题**: `enumDevice()` 返回空列表
|
||
|
||
**解决方法**:
|
||
1. 确认设备支持 USB Host/OTG 功能
|
||
2. 检查 USB 线缆连接是否正常
|
||
3. 确认 Android 设备已开启 OTG 功能(部分手机需要手动开启)
|
||
4. 检查芯片是否在支持列表中
|
||
|
||
### 7.2 权限被拒绝
|
||
|
||
**问题**: `requestPermission()` 返回 `false`
|
||
|
||
**解决方法**:
|
||
1. 确保在 `AndroidManifest.xml` 中添加了 USB 权限声明
|
||
2. 用户需要在系统弹窗中点击"允许"
|
||
3. 可以尝试重新请求权限
|
||
|
||
### 7.3 数据收发异常
|
||
|
||
**问题**: 发送数据成功但收不到回复
|
||
|
||
**解决方法**:
|
||
1. 确认串口参数(波特率、数据位、停止位、校验位)与对端设备一致
|
||
2. 使用 `registerDataCallback` 代替 `readData`,推荐回调方式接收数据
|
||
3. 检查线缆连接和电平匹配(3.3V vs 5V)
|
||
4. 使用 `querySerialErrorCount` 检查是否有串口错误
|
||
|
||
### 7.4 多串口设备使用
|
||
|
||
**问题**: CH344/CH9104 等多串口设备如何使用
|
||
|
||
**解决方法**:
|
||
```dart
|
||
// 多串口设备每个串口都需要单独配置
|
||
for (int i = 0; i < device.serialCount; i++) {
|
||
await Ch34Manager.setSerialParameter(
|
||
device.deviceName,
|
||
i, // 不同的串口号
|
||
const SerialParameter(baud: 9600),
|
||
);
|
||
|
||
Ch34Manager.registerDataCallback(
|
||
device.deviceName,
|
||
i,
|
||
(data) {
|
||
print('串口 $i 收到数据: $data');
|
||
},
|
||
);
|
||
}
|
||
```
|
||
|
||
### 7.5 设备热插拔处理
|
||
|
||
**问题**: 设备拔出后如何检测
|
||
|
||
**解决方法**:
|
||
```dart
|
||
// 注册 USB 状态监听
|
||
Ch34Manager.setUsbStateListener((deviceName, connected) {
|
||
if (!connected) {
|
||
print('设备 $deviceName 已拔出');
|
||
// 清理资源
|
||
Ch34Manager.removeDataCallback(deviceName);
|
||
} else {
|
||
print('设备 $deviceName 已插入');
|
||
// 重新打开设备
|
||
}
|
||
});
|
||
```
|
||
|
||
### 7.6 自定义 VID/PID
|
||
|
||
**问题**: 如何支持非标准 VID/PID 的设备
|
||
|
||
**解决方法**:
|
||
```dart
|
||
// 添加自定义硬件
|
||
await Ch34Manager.addNewHardware(
|
||
0x1234, // 自定义 VID
|
||
0x5678, // 自定义 PID
|
||
chipType: 'CH340', // 可选:指定芯片类型
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 附录:通信通道说明
|
||
|
||
插件内部使用以下通道与 Android 原生端通信:
|
||
|
||
| 通道类型 | 名称 | 用途 |
|
||
|---------|------|------|
|
||
| MethodChannel | `ch34` | 双向方法调用 |
|
||
| EventChannel | `ch34/data` | 串口数据推送 |
|
||
| EventChannel | `ch34/modem` | Modem 状态变化 |
|
||
| EventChannel | `ch34/usb_state` | USB 插拔状态 |
|
||
|
||
---
|
||
|
||
*文档版本: 1.0.0*
|
||
*插件版本: 1.0.0*
|