cSerialPort 串口通信开发文档
🚀 cSerialPort - 纯 Win32 API 实现的 VB6 串口通信类,完整封装 Windows 串口通信能力
📖 目录
概述
cSerialPort 是 VBManLib 提供的串口通信类,直接调用 Win32 API 实现完整的串口通信功能。相比传统 MSComm 控件,它无需 OCX 依赖、支持 COM10 以上端口、可精确控制底层参数,适合工业控制、设备通信、Modbus 等场景。
✨ 主要特性
- 🔌 纯 API 实现 - 无需 MSComm OCX 控件,零外部依赖
- 🎯 完整封装 - 覆盖打开/关闭、读写、配置、信号线、错误处理、缓冲区管理
- 📡 事件驱动 - 异步轮询监控,不阻塞 UI 线程
- 🔧 精确配置 - 完整 DCB/COMMTIMEOUTS 参数,支持流控制、超时预设
- 📊 信号线控制 - DTR/RTS/Break/XON/XOFF 全套信号线操作
- 🔍 端口枚举 - 自动扫描系统可用串口
- 📦 二进制与文本 - 同时支持字节数组和文本读写
- 🛡️ 错误诊断 - 中文错误描述,完整状态查询
核心特性
1️⃣ 无 OCX 依赖 🔌
传统 MSComm 控件需要注册 MSCOMM32.OCX,部署麻烦且在 COM10 以上端口无法使用。cSerialPort 直接调用 kernel32 API,零依赖。
2️⃣ 异步事件监控 📡
使用 Win32 Timer 定时轮询缓冲区,检测到新数据自动触发 DataReceived 事件,不阻塞 UI 线程:
vb
Dim WithEvents sp As cSerialPort
Private Sub Start()
Set sp = New cSerialPort
sp.PortName = "COM3"
sp.OpenPort
sp.StartMonitoring 50 ' 50ms 轮询
End Sub
Private Sub sp_DataReceived(ByVal BytesCount As Long)
Debug.Print "收到: " & sp.ReadExisting()
End Sub3️⃣ 完整信号线控制 📊
支持 DTR/RTS/Break 手动控制,以及 CTS/DSR/RING/CD 状态查询:
vb
sp.SetDTR True ' 设置 DTR
sp.SetRTS True ' 设置 RTS
sp.SetBreak True ' 发送 Break 信号
Debug.Print sp.CtsHolding ' 查询 CTS 状态4️⃣ 灵活超时配置 ⏱️
提供三种预设模式,也可手动精确控制每个超时参数:
vb
sp.Config.SetNonBlockingRead ' 非阻塞:立即返回
sp.Config.SetBlockingRead ' 阻塞:等待指定字节数
sp.Config.SetReadTimeout 2000 ' 带超时:2秒5️⃣ 模式字符串兼容 🔤
支持与 BuildCommDCB API 兼容的模式字符串:
vb
sp.Config.FromModeString "baud=9600 parity=N data=8 stop=1"6️⃣ 数据分帧 🧩
解决设备连发导致的"粘包"问题,识别每一帧的边界:
- 方案 B(帧间隔超时):设置
FrameInterval属性,利用设备发完一帧后的停顿自动分帧 - 方案 C(协议分帧解析器):
cSerialFrameParser类按分隔符/起止标记/长度字段/固定长度精确切分
vb
' 方案 B:30ms 无新数据 = 一帧结束
sp.FrameInterval = 30
sp.StartMonitoring 20
Private Sub sp_FrameReceived(FrameData() As Byte)
Debug.Print "收到帧: " & StrConv(FrameData, vbUnicode)
End Sub详见 分帧协议专题
与 MSComm 控件的对比
| 特性 | MSComm 控件 | cSerialPort 类 |
|---|---|---|
| 依赖 | 需注册 MSCOMM32.OCX | 纯 API,零依赖 |
| 端口限制 | 仅 COM1~COM9 | 支持 COM10 以上 |
| 事件模型 | OnComm 事件 + CommEvent | 独立的事件(DataReceived 等) |
| 信号线控制 | DTREnable/RTSEnable 属性 | SetDTR/SetRTS/SetBreak 方法 |
| 超时控制 | 无(仅 InputLen/Threshold) | 完整 COMMTIMEOUTS 五参数 |
| 流控制 | Handshaking 属性(有限) | 完整 RTS/CTS、DTR/DSR、XON/XOFF |
| 缓冲区管理 | InBufferCount/OutBufferCount | 同上 + PurgeRx/PurgeTx/PurgeAll |
| 错误诊断 | 无详细错误 | 中文错误描述 + 状态字符串 |
| 二进制支持 | Input 属性 | ReadData/WriteData 字节数组 |
| 波特率 | 最高 115200 | 最高 256000(eBaudRate 枚举) |
| 数据分帧 | 无(仅 RThreshold 触发) | FrameInterval + cSerialFrameParser,解决粘包 |
| 端口枚举 | 无 | EnumSerialPorts 自动扫描 |
架构设计
类层次结构
cSerialPort (公开类)
├── m_Config: cSerialConfig (配置对象)
├── m_Handle: Long (串口句柄)
├── m_TimerID: Long (监控定时器)
└── 事件:DataReceived, ErrorOccurred, PinChanged, TxEmpty, BreakDetected, RingDetected子模块类
| 类名/模块 | 文件 | 职责 |
|---|---|---|
cSerialConfig | cSerialConfig.cls | 串口配置:封装 DCB 和 COMMTIMEOUTS,提供类型安全访问;定义配置枚举(eBaudRate/eParity/eStopBits/eDtrControl/eRtsControl/eFlowControl) |
cSerialPort | cSerialPort.cls | 串口主类;定义通信枚举(eCommEvent/eCommError/eModemStatus) |
modSerialPortAPI | modSerialPortAPI.bas | API 声明、常量、类型、辅助函数 |
说明:所有
Public Enum均定义在类模块中(而非标准模块),因为 VB6 标准模块的Public Enum不会随 DLL 类型库导出。移至类模块后,外部工程引用 DLL 时即可使用br115200、EV_RXCHAR、CE_RXOVER等枚举常量。modSerialPortAPI内部辅助函数(如GetCommErrorString)使用底层数值,避免与类模块形成循环引用。
对象关系图
cSerialPort
├── Config (cSerialConfig)
│ ├── BuildDCB() → DCB 结构
│ ├── BuildTimeouts() → COMMTIMEOUTS 结构
│ └── 预设方法 → 非阻塞/阻塞/超时模式
├── Handle (串口句柄)
│ ├── ReadFile / WriteFile
│ ├── GetCommModemStatus (信号线)
│ ├── ClearCommError (错误/状态)
│ └── PurgeComm (缓冲区)
└── Timer (监控定时器)
└── Poll() → 触发 DataReceived 事件工作流程
1. 创建 cSerialConfig 配置参数
2. cSerialPort.OpenPort() 打开串口
3. (可选) StartMonitoring() 启动事件监控
4. WriteText/WriteData 发送数据
5. DataReceived 事件 / ReadExisting 读取数据
6. ClosePort() 关闭串口快速开始
最简收发示例
vb
Dim sp As New cSerialPort
sp.PortName = "COM3"
sp.Config.BaudRate = br115200
If sp.OpenPort() Then
sp.WriteText "Hello"
Debug.Print sp.ReadExisting()
sp.ClosePort
End If事件驱动收发示例
vb
Private WithEvents m_Port As cSerialPort
Private Sub Form_Load()
Set m_Port = New cSerialPort
m_Port.PortName = "COM3"
m_Port.Config.BaudRate = br9600
If m_Port.OpenPort() Then
m_Port.StartMonitoring 50
End If
End Sub
Private Sub m_Port_DataReceived(ByVal BytesCount As Long)
Debug.Print "收到: " & m_Port.ReadExisting()
End Sub
Private Sub Form_Unload(Cancel As Integer)
m_Port.ClosePort
End Sub更完整的示例参见 快速入门
文档索引
| 文档 | 描述 |
|---|---|
| 快速入门 | 最简引用方式、常见场景代码示例 |
| 属性详解 | 所有属性的说明、类型和用途 |
| 方法详解 | 所有方法的参数、返回值和使用示例 |
| 事件详解 | 所有事件的详细说明和使用示例 |
| 分帧协议 | 解决粘包问题:帧间隔分帧 + 协议分帧解析器 |
| 高级进阶 | 流控制、超时策略、二进制协议、虚拟串口等 |
| 常见问题 | 常见问题与解决方案 |
最后更新: 2026-07-05