日期:2014-05-17  浏览次数:20985 次

C# serialport数据接收不全的问题?
C# serialport读取松下PLC的数据,用的是松下Mewtocol通讯协议,我在timer_tick事件中接收数据,因要实时读取数据,timer设置为1毫秒,数据接收时不全,代码如下:

  clsPLC plc = new clsPLC();
  string data = "%01#RDD0600006002";
  data += plc.CalBcc(data) + (char)13;
  serialPort.WriteLine(data);
  string outdata = serialPort.ReadExisting();
  if (outdata.Length >0)
  {  
  if (outdata.Substring(0, 1) == "%" 
  && outdata.Length >=19)
  {
  iTime += 1;
  dgvData.Rows.Add(iTime.ToString(),outdata, outdata.Substring(6, 4), outdata.Substring(14, 4));
   
  }
  }
timer设置为100毫秒,可以正确接收数据,但PLC的数据变化快,100毫秒无法准确反应所有数据,不知如何来解决这个问题?



------解决方案--------------------
我有个严重的怀疑,你每1毫秒发送一次请求的意义在哪里?

若传输速率是1200波特(其中有一个起始位, 8 个数据位, 2 个停止位),那么,每秒所能传送的字符数是1200/(1+8+1+2)= 100个。 

假设1个报文20个字符

你的通信极限也就是200毫秒1个报文。

如果是9600/(1+8+1+2) = 800 个

你的通信极限在 40 毫秒 1 个报文

如果是半双工,这个效率还要低很多。

你可以根据你的波特率调整请求的间隔,再快就没什么意义了




------解决方案--------------------
lz的理解有误。 serialport的接受数据事件是实时的,一旦有数据到达就会触发此事件。因此不需要你去定时1ms读。而应当单独定义一个timer,每1ms给plc写数据。
另外你接收数据的处理可以优化。

private void serialport_DataReceived(Object sender, SerialDataReceivedEventArgs e)
{
int bytesToRead = this.serialPort1.BytesToRead; //表示总共有多少数据要读取 
//声明char数组
byte[] ch = new byte[bytesToRead];
//char[] ch1 = new char[bytesToRead];
int bytesRead = 0;
  
//将读取到的bytes存储在ch数组中
//bytesRead = serialport.Read(ch, 0, bytesToRead);
bytesRead = this.serialPort1.Read(ch, 0, bytesToRead);
//bytesRead = this.serialPort1.Read(ch1, 0, bytesToRead);
  
//将ch数组转换为string类型
str = this.ByteArrayToHexString(ch).Replace(" ", "").Trim();
Console.WriteLine(str);
}

------解决方案--------------------
恩,ls都说了,把任务分开就可以

我们通常是使用消息队列,直接把数据缓存入队列

而另一个线程负责处理队列。这样实际类似流水线操作,上个工序只管上个工序滴,下个工序也只管从总线上拿工件

至于这个中间肯定会有时间差,不过无所谓了要差都差了,也就是数据是连续滴,但是都总体延后了一点(这一点问题不太大,对计算机的运行速度来说,基本是可以承受滴)