日期:2014-05-18  浏览次数:20999 次

C# 接受串口数据处理的问题
串口接收放在一个事件里
form_load里

  //添加事件注册
  comm.DataReceived += comm_DataReceived;


接收函数:
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
  {
  int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
  byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
  string str = "";
  received_count += n;//增加接收计数
  comm.Read(buf, 0, n);//读取缓冲数据  
  //因为要访问ui资源,所以需要使用invoke方式同步ui。
  this.Invoke((EventHandler)(delegate
  {
  for (int i = 0; i < n; i++)
  {
  str += buf[i].ToString("X2");
  } 
  this.txGet.AppendText(str);
  //修改接收计数
  labelGetCount.Text = "Get:" + received_count.ToString();
  }));
  }


发送部分没有列出来,,其实就是发送一个命令包, 底层ARM板子,收到命令后
一直向外抛出数据

比如发送的命令: 
引导码 长度 命令码 校验和
  40 02 02 BC 

返回数据包
  09 01 xx xx xx xx xx xx xx xx xx xx xx xx xx xx 
  09 01 :为引导码
  每条引导码是固定的,但是长度不固定

 且ARM 我向外抛出时,并非一条一条往串口发送缓冲区打进去,

假设的情况:
  09 01 AA BB CC DD EE FF (假设这是一条整的记录包,且每次都返回这个数据包)
   
同时假设,上面的记录包一次从缓冲去,向上发送10条,,即 80个字节

 于是在C#的接收,也就是上面的 接收事件里,出现这样的情况
   
 一次不能接收全80个字符,通常要2次才能接收全,(如果一次大于80,则可能次数更多)
 通过断点,观察 int n = comm.BytesToRead 这个变量

  设置断点,n 的值,则两次变化
  n=2
  n=78

  n=4
  n=76
  等,两次的和肯定等于 80 的,即肯定保证了数据全部接收下来。

 当
  n=2
  n=78
 时,,则 第一次接受数据就只有: 09 01

  则第一条记录被打散了, 后面的AA BB CC DD EE FF ,要第二次接收才能收全
 
 第二次接收的就是: AA BB CC DD EE FF + 9 * ( 09 01 AA BB CC DD EE FF)

 而现在,又要把 AA BB CC DD EE FF 这个给取出来
  即: 在界面上显示 10条 “AA BB CC DD EE FF” 这样的字符串

 有何办法?
谢谢

 
 
  
 
 






------解决方案--------------------
你还是制定一个协议规则,比如开始字符和结束字符,以此作为接收内容的头和尾,或者加校验等等,你根据规则来提取完整信息
这样你可以将所有数据都接受到内存中,后台开个线程不停地处理,找到就显示,然后继续找
------解决方案--------------------
我觉得不是有多少你读多少,而是你期望读多少就读多少。
如果没有读取完整就超时处理。

而协议最好是类似 TCP/IP这样带有协议头的包格式,而不是流格式的。

而且这些通信类的程序,最好通信协议不要和通信方式混合在一起。
可以尝试看看七层通信模式。
------解决方案--------------------
把没次收到的数据 放进一个线程池里,在弄个线程去取数据 是否是是一个完整的数据包,是的解析不是的继续
------解决方案--------------------
SerialPort.DataReceived之“管收不管埋”

你的问题关键在于如何解析你的数据。你这个协议设计的不好,只有引导码,而包长度却不固定,那你如何判断多少数据才是完整的包啊。至少也要整个结束符啥的。