Skip to content

cSerialPort 事件详解

📋 事件列表

事件名说明触发条件
DataReceived数据接收输入缓冲区有新数据(需 StartMonitoring
FrameReceived帧接收启用分帧(FrameInterval>0)后,每收到一个完整帧触发
ErrorOccurred通信错误检测到线路错误
PinChanged信号线变化CTS/DSR/RING/RLSD 任一变化
TxEmpty发送缓冲区已空发送完成
BreakDetected检测到 Break收到 Break 信号
RingDetected检测到振铃收到振铃信号

📥 DataReceived 事件

说明

当输入缓冲区有新数据时触发。需要先调用 StartMonitoring 启动监控。

语法

vb
Private Sub object_DataReceived(ByVal BytesCount As Long)

参数

参数类型说明
BytesCountLong输入缓冲区中的字节数

使用示例

vb
Private WithEvents m_Port As cSerialPort

Private Sub m_Port_DataReceived(ByVal BytesCount As Long)
    Dim s As String
    s = m_Port.ReadExisting()
    Debug.Print "收到 " & BytesCount & " 字节: " & s
End Sub

注意事项

  • 必须先调用 StartMonitoring 才能触发此事件
  • 事件中应尽快读取数据,避免缓冲区溢出
  • 事件中不要执行耗时操作,否则会影响后续数据接收

🧩 FrameReceived 事件

说明

当启用分帧模式(FrameInterval > 0)后,每收到一个完整帧触发。这是解决"设备连发导致粘包"问题的核心事件。

详细的分帧原理与方案选型,请参阅 分帧协议专题

语法

vb
Private Sub object_FrameReceived(FrameData() As Byte)

参数

参数类型说明
FrameDataByte 数组这一帧的原始字节数据

启用方式

vb
' 启用分帧:30ms 无新数据 = 一帧结束
m_Port.FrameInterval = 30
m_Port.StartMonitoring 20   ' 轮询间隔建议 <= FrameInterval/2

使用示例

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.FrameInterval = 30
        m_Port.StartMonitoring 20
    End If
End Sub

Private Sub m_Port_FrameReceived(FrameData() As Byte)
    Dim s As String
    s = StrConv(FrameData, vbUnicode)
    Debug.Print "收到帧 (" & UBound(FrameData) + 1 & "字节): " & s
End Sub

注意事项

  • 必须设置 FrameInterval > 0 才会触发;为 0 时仍走 DataReceived 路径
  • FrameInterval=0DataReceived 正常触发,两者互斥
  • StopMonitoring / ClosePort 时会自动 flush 缓冲区中剩余的帧,不会丢失最后一帧
  • 搭配 cSerialFrameParser 可实现"协议分帧"(按分隔符/起止标记/长度字段精确切分)

⚠️ ErrorOccurred 事件

说明

检测到通信错误时触发。

语法

vb
Private Sub object_ErrorOccurred(ByVal ErrorCode As Long, ByVal ErrorMsg As String)

参数

参数类型说明
ErrorCodeLong通信错误码(CE_ 常量组合)
ErrorMsgString中文错误描述

错误码

常量说明
CE_RXOVER&H1接收缓冲区溢出
CE_OVERRUN&H2字符覆盖
CE_RXPARITY&H4校验错误
CE_FRAME&H8帧错误
CE_BREAK&H10中断检测
CE_TXFULL&H100发送缓冲区满

使用示例

vb
Private Sub m_Port_ErrorOccurred(ByVal ErrorCode As Long, ByVal ErrorMsg As String)
    Debug.Print "通信错误 [" & ErrorCode & "]: " & ErrorMsg

    Select Case ErrorCode
        Case CE_RXOVER
            ' 接收缓冲区溢出,清空缓冲区
            m_Port.PurgeRx
        Case CE_RXPARITY
            ' 校验错误,记录日志
            LogError "校验错误"
        Case CE_FRAME
            ' 帧错误,检查波特率配置
            LogError "帧错误,请检查波特率"
    End Select
End Sub

📊 PinChanged 事件

说明

CTS/DSR/RING/RLSD 任一信号线变化时触发。

语法

vb
Private Sub object_PinChanged(ByVal Events As Long)

参数

参数类型说明
EventsLong事件掩码(EV_CTS/EV_DSR/EV_RLSD/EV_RING 组合)

使用示例

vb
Private Sub m_Port_PinChanged(ByVal Events As Long)
    If (Events And EV_CTS) Then
        Debug.Print "CTS 变化: " & m_Port.CtsHolding
    End If
    If (Events And EV_DSR) Then
        Debug.Print "DSR 变化: " & m_Port.DsrHolding
    End If
    If (Events And EV_RLSD) Then
        Debug.Print "CD 变化: " & m_Port.CdHolding
    End If
End Sub

注意PinChanged 事件仅在 WaitForEvent 同步模式中触发。异步监控模式(StartMonitoring)目前不监控信号线变化。


📤 TxEmpty 事件

说明

发送缓冲区已空时触发。

vb
Private Sub m_Port_TxEmpty()
    Debug.Print "发送完成"
End Sub

仅在 WaitForEvent 同步模式中触发。


⚡ BreakDetected 事件

说明

检测到 Break 信号时触发。

vb
Private Sub m_Port_BreakDetected()
    Debug.Print "收到 Break 信号"
End Sub

仅在 WaitForEvent 同步模式中触发。


🔔 RingDetected 事件

说明

检测到振铃信号时触发。

vb
Private Sub m_Port_RingDetected()
    Debug.Print "检测到振铃"
End Sub

仅在 WaitForEvent 同步模式中触发。


事件触发模式对比

异步监控模式(StartMonitoring)

事件是否触发说明
DataReceived轮询检测到缓冲区有数据
ErrorOccurred轮询检测到通信错误
PinChanged不监控信号线变化
TxEmpty不监控发送完成
BreakDetected不监控 Break
RingDetected不监控振铃

同步等待模式(WaitForEvent)

事件是否触发说明
DataReceived收到 EV_RXCHAR 事件
ErrorOccurred收到 EV_ERR 事件
PinChanged收到 EV_CTS/EV_DSR/EV_RLSD 事件
TxEmpty收到 EV_TXEMPTY 事件
BreakDetected收到 EV_BREAK 事件
RingDetected收到 EV_RING 事件

⚠️WaitForEvent 会阻塞调用线程,不建议在 UI 线程使用。


最后更新: 2026-07-05

VB6及其LOGO版权为微软公司所有