我最近在做一个RS232的程序,遇到一个问题,就是我接收的数据有时候是对的,有时候是错的,比如我每次发送三个字节,但是接收的时候有的是只受到一个字节。
这是部分代码 string ComportName = "COM1";
comPort = new SerialPort(ComportName, 14400, Parity.None, 8, StopBits.One);
comPort.ReadTimeout = 100;
comPort.WriteTimeout = 100;
comPort.DataReceived += ByteReceived;
//comPort.ReceivedBytesThreshold = 1;
// comPort.WriteBufferSize = 3;
comPort.Open();
这是接收事件: int byteToRead = comPort.BytesToRead;
byte[] resultByte = new byte[byteToRead];
comPort.Read(resultByte, 0, byteToRead);
这是部分代码 string ComportName = "COM1";
comPort = new SerialPort(ComportName, 14400, Parity.None, 8, StopBits.One);
comPort.ReadTimeout = 100;
comPort.WriteTimeout = 100;
comPort.DataReceived += ByteReceived;
//comPort.ReceivedBytesThreshold = 1;
// comPort.WriteBufferSize = 3;
comPort.Open();
这是接收事件: int byteToRead = comPort.BytesToRead;
byte[] resultByte = new byte[byteToRead];
comPort.Read(resultByte, 0, byteToRead);
接收的字节数为什么要与发送的字节数相同?这很奇怪。接收的字节数应该是看设备的设置返回给你什么信息,跟你发送的字节数又不一样。
a->b , a 发送了n个字节, b 串口接收、添加到缓冲区。comPort.DataReceived += ByteReceived;
这个接收事件激活的条件,并不是全部接收后激活,这就是你的问题表现。
有时接收几个就激活,有时接收1个就激活,这时候缓冲区里有几个,你就能读出几个。 这并不是bug或者问题,这就是因为数据没有接收完成。 这就是串口通信的特点你可以在接收事件的方法第一行假如thread.sleep(500-1000 适当值), 适当延时来增加串口缓冲的填充率,来保证每次接收数据完整。 但是这个方法只能面向内容十分短小的通信。 大数据量的要按字节读取。 根据通信包做首尾判断。
这个地方加入断点的话,看到的comport的bytesToRead确实是正确的,但是在赋值给int byteToRead就变少了,真是太郁闷了。
{
try
{
int n = SerialPort1.BytesToRead;
byte[] buf = new byte[n];
SerialPort1.Read(buf, 0, n);//读取缓冲数据
bool data_1_catched = false;//缓存记录数据是否捕获到
buffer.AddRange(buf);
while (buffer.Count >= 12)
{
byte CRCH, CRCL;
byte[] crcTemp = new byte[10];
buffer.CopyTo(0, crcTemp, 0, 10); CRCData.CalculateCrc16(crcTemp, out CRCH, out CRCL);
if (buffer[10] != CRCH && buffer[11] != CRCL)
{
buffer.RemoveAt(0);
continue;//继续下一次循环
}
buffer.CopyTo(0, binary_data_1, 0, 12);//复制一条完整数据到具体的数据缓存
data_1_catched = true;
buffer.RemoveRange(0, 12);//正确分析一条数据,从缓存中移除数据。
}自己看吧
private List<byte> buffer = new List<byte>(256);//默认分配1/16页内存,并始终限制不允许超过
private byte[] binary_data_1 = new byte[12];//
C# 串口操作系列(2) -- 入门篇,为什么我的串口程序在关闭串口时候会死锁 ?
C# 串口操作系列(3) -- 协议篇,二进制协议数据解析
//系统延时
public void Delay(int ys)
{
for (int i = 1; i <= ys; i++)
{
//使用sleep(1)会比sleep(1000)好,因为让进程循环1000休息1ms=1s比直接让系统休眠1s好
//如果直接让进程休眠1s,让人感觉进程好像卡了,反应很慢。
System.Threading.Thread.Sleep(1);
Application.DoEvents();
}
}
{
byte CRCH, CRCL; //这个是我CRC校验用的,
byte[] crcTemp = new byte[10];
buffer.CopyTo(0, crcTemp, 0, 10); CRCData.CalculateCrc16(crcTemp, out CRCH, out CRCL);//一直到这 这个是我CRC校验用的, if (buffer[10] != CRCH && buffer[11] != CRCL)//如果CRC校验不对,做下面的处理
{
buffer.RemoveAt(0);//删除BUFF中的第一个数据。
continue;//继续下一次循环
}
清楚没?