控件中国网现已改版,您看到的是老版本网站的镜像,系统正在为您跳转到新网站首页,请稍候.......
中国最专业的商业控件资讯网产品咨询电话:023-67870900 023-67871946
产品咨询EMAIL:SALES@COMPONENTCN.COM

C#串口编程遇到的问题以及解决方法

作者:佚名 出处:互联网 2010年03月26日 阅读:

C#串口编程遇到的问题以及解决方法

  本文介绍C#串口编程遇到的问题以及解决方法。
  最近在做的项目中涉及到串口通信编程,队友在做这一模块的时候遇到了一个相信很多人都可能遇到的问题,那就是接受数据的冲突或者丢失。队友让我帮他调试的时候,足足花了近两个小时才把问题给解决了,现觉得有必要总结一下以给遇到类似问题的朋友一个思路吧~

  问题是这样的,从相应的硬件设备每隔2秒便发送一个大小为15的字节数据,存的是16进制数据,每条数据以7E开头以7E结尾。例如:7E 09 01 1A ... 7E。但是PC端在接受显示的时候却出现了问题,如前五个数据接受正常,接下来的都是以00填充,而剩下的10个数据却出现在下条数据显示的位置。如下所示:


 7E 09 01 1A 5C 00 00 00 00 00 00 00 00 00 00 /////// 03 06 1A 2C 3D 09 6C 32 12 7E 00 00 00 00 00 00/////// ........


  总之感觉错位了,对了,先把PC端代码贴一下吧:

 


 public partial class Form1 : Form
  {
  /// 
  /// 接受数据的串口类
  /// 
  SerialPort spReceive;
  delegate void ReceivData(byte[] bytes);
  public Form1()
  {
  Form1.CheckForIllegalCrossThreadCalls = false;
  InitializeComponent();
  spReceive =new SerialPort("COM5", 57600, Parity.None, 8, StoPBits.One);
  spReceive.Open();
  //设置触发DataReceived事件的阀值,在调试中发现这个不起作用,不解~
  spReceive.ReceivedBytesThreshold =15;
  spReceive.DataReceived +=new System.IO.Ports.SerialDataReceivedEventHandler(spReceive_DataReceived);
  }
  /// 
  /// 更新接受到得数据到UI界面显示
  /// 
  /// 
  public void UpdateReceiveToUI(byte[] bytes)
  {
  if (txtReceive.InvokeRequired)
  {
  ReceivData dl = new ReceivData(UpdateReceiveToUI);
  object arg = bytes;
  txtReceive.Invoke(dl, arg);
  }
  else
  txtReceive.Text += "/////////" + BitConverter.ToString(bytes);
  }
  /// 
  /// 接收到串口数据触发的事件
  /// 
  /// 
  /// 
  public void spReceive_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
  {
  byte[] recevied = new byte[15];
  int size = spReceive.Read(recevied, 0, recevied.Length);
  if (size >0)
  UpdateReceiveToUI(recevied);
  }
  }

在调试的过程中,当我spReceive_DataReceived函数中的byte[] recevied = new byte[15]; 后面在加上个初始化,如下:


      for( int i=0; i 
  recevied[i]=11;


  这个时候界面显示的时候,凡是以00显示的地方都被11替换了。这肯定了这些00是由于传送的15个字节数组未被完全填充到我们定义的字节数组中,即 Read(byte [] bytes,int offset,int size)函数未一次性将字节数组填充完,而是分了两次。但是在此过程中我使用的是SerialPort类的DataReceived事件,即没收到一条数据便会触发,而这儿的现象仿佛是事件被触发了多次。后来自己在SerialPort类的属性里面找了下,突然发现了有个 ReceivedBytesThreshold属性,从这个属性可以看出我们可以控制接受多少个字节触发一次DataReceived事件。于是,我便将阀值设为15个字节,满以为问题解决了,可是结果却~

  囧啊,可是这个属性也给了我们一些提示,也找到了问题的症结所在。那就是,DataRecevied事件触发的阀值,即接受到多少个字节数触发一次偏小,结果导致了我们一条大小为15个字节的数据触发了两次DataReceived事件。要解决这个问题,我们可以沿着这个思路走下去,那就是延迟 DataRecevied事件的触发直到我们一条数据接受完毕。

  所以在spReceive_DataReceived事件函数中,我们做如下修改:


  byte[]  receiveBuffer=new byte[15];
  public void spReceive_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
  {
  int bytesRead = 0;
  spReceive.ReceivedBytesThreshold = 100000;     //延迟DataRecevied事件的再次触发
  while (true)
  {
  if (bytesRead >= 15)      //这儿的15是我一条数据的大小
  {
  byte[] bytes = new byte[bytesRead];
  Array.Copy(receiveBuffer, 0, bytes, 0, bytesRead);
  Array.Clear(receiveBuffer, 0, bytesRead);
  UpdateReceiveToUI(bytes);
  bytesRead = 0;
  break;
  }
  try
  {
  receiveBuffer[bytesRead] = (byte)spReceive.ReadByte();
  ++bytesRead;
  }
  catch (Exception ex1)
  {
  MessageBox.Show(ex1.Message);
  break;
  }
  bytesRead = 0;
  spReceive.ReceivedBytesThreshold = 1;            //将延迟改回正常
  }
  }


  经过上述的改动,便可以解决读取串口数据冲突与丢失的问题了~不周之处,还望各位斧正~

 

 

热推产品

  • ActiveReport... 强大的.NET报表设计、浏览、打印、转换控件,可以同时用于WindowsForms谀坔攀戀Forms平台下......
  • AnyChart AnyChart使你可以创建出绚丽的交互式的Flash和HTML5的图表和仪表控件。可以用于仪表盘的创......
首页 | 新闻中心 | 产品中心 | 技术文档 | 友情连接 | 关于磐岩 | 技术支持中心 | 联系我们 | 帮助中心 Copyright-2006 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 电话:023 - 67870900 传真:023 - 67870270 产品咨询:sales@componentcn.com 渝ICP备12000264号 法律顾问:元炳律师事务所 重庆市江北区塔坪36号维丰创意绿苑A座28-5 邮编:400020
在线客服
在线客服系统
在线客服
在线客服系统