如何在C# .NET中通过串口正确发送887字节数据?
串口发送唤醒字节丢包问题的解决方法
根本原因
你遇到的丢包问题,本质是SerialPort类的发送缓冲区未及时排空,或硬件流控配置不匹配,导致连续发送的数据被丢弃。单字节循环发送时,缓冲区快速填满后,未被硬件及时取走的数据会被直接丢弃;而添加Thread.Sleep(1)是通过强制等待让缓冲区有时间排空,但牺牲了发送速度。
正确实现方式
1. 一次性发送完整唤醒数组 + 等待缓冲区排空
避免单字节循环发送,直接构建完整的唤醒字节数组,一次性写入串口,然后等待发送缓冲区完全清空:
// 构建873个0x0E的唤醒数组 byte[] wakeSequence = Enumerable.Repeat((byte)0x0E, 873).ToArray(); // 一次性写入串口 P.Write(wakeSequence, 0, wakeSequence.Length); // 等待发送缓冲区排空,确保所有数据都已发送到硬件 while (P.BytesToWrite > 0) { // 用短延迟减少不必要等待,同时保证缓冲区及时处理 Thread.Sleep(1); }
这种方式的发送速度会接近理论值(2400 Bd 8N1下,873字节约3.6秒),不会出现超时问题。
2. 调整串口缓冲区与流控配置
- 增大发送缓冲区:默认的
WriteBufferSize可能不足以容纳完整的唤醒序列,手动设置更大的缓冲区:// 设置缓冲区大小为2048(远大于873) P.WriteBufferSize = 2048; - 关闭不必要的流控:如果硬件端未配置流控,开启流控会导致发送端误判硬件状态,停止发送或丢包:
P.Handshake = Handshake.None;
3. 使用BaseStream异步写入(推荐异步场景)
如果你的程序是异步架构,使用BaseStream的异步写入方法,确保数据完全发送:
byte[] wakeSequence = Enumerable.Repeat((byte)0x0E, 873).ToArray(); await P.BaseStream.WriteAsync(wakeSequence, 0, wakeSequence.Length); await P.BaseStream.FlushAsync();
异步方式不会阻塞主线程,同时能保证数据全部写入硬件。
关键注意点
- 避免单字节循环发送:这种方式会频繁触发串口的写入操作,不仅效率低,还容易导致缓冲区溢出丢包。
- 不要依赖固定延迟:固定
Thread.Sleep会引入不可控的时间开销,等待BytesToWrite归零才是可靠的判断方式。
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

