在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
问题是这样的,从相应的硬件设备每隔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 { /// <summary> /// 接受数据的串口类 /// </summary> 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); } /// <summary> /// 更新接受到得数据到UI界面显示 /// </summary> /// <param name="bytes"></param> 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); } /// <summary> /// 接收到串口数据触发的事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> 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.Lengthl;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; //将延迟改回正常 } }
经过上述的改动,便可以解决读取串口数据冲突与丢失的问题了~不周之处,还望各位斧正~ |
请发表评论