通过把SerialPort进行封装,以多线程和缓存的方式处理串口的发送和接收动作。
一、现象
不管如何设置ReceivedBytesThreshold的值,DataReceived接收到的数据都是比较混乱,不是一个完整的应答数据。
二、原因
1、上位机下发的命令比较密集,以200ms周期发送实时状态轮询命令。
2、在状态实时轮询命令中间有操作命令插入。
2、不同的命令,接收的应答格式也不同。
三、分析
不同的命令有不同的应答数据,但是不同的应答数据中都具有唯一的结束符,可以根据结束符来作为多个应答数据的分割标志。因此可以把应答数据进行缓存,然后另起一个线程对缓存的应答数据进行分析处理。
因此系统具有:
1、命令队列用来插入操作命令,空闲时处理状态实时轮询命令。
2、命令发送线程,以200ms周期性的发送队列中的命令。
3、应答集合,用来缓存DataReceived接收数据。
4、应答处理线程,对应答集合中的数据进行集中处理。
四、代码片段
1、定义
2、开始、停止线程
3、发送线程
4、接收和处理
5、以事件的形式在主界面实时显示处理后的应答数据
private void ShelvesDataReceived(object sender, ShelvesDataReceivedEventArgs e)
{
this.Invoke(new UpdateDelegate(this.Update), new object[] { e.Realtime });
}
private void Update(Realtime realtime)
{
this.lbl_send.Text = this.shelves.send.ToString();
this.lbl_received.Text = this.shelves.received.ToString();
this.txt_lowLine.Text = realtime.ActionLineOfLowZone.ToString();
this.txt_lowZoneState.Text = Request.GetStateMessage(realtime.LowZoneState);
this.txt_highLine.Text = realtime.ActionLineOfHighZone.ToString();
this.txt_highZoneState.Text = Request.GetStateMessage(realtime.HighZoneState);
this.txt_temperature.Text = realtime.Temperature.ToString();
this.txt_humidity.Text = realtime.Humidity.ToString();
}
五、结论
一般情况下,当下位机高速发送应答数据时,串口接收到的数据不会是一个完整应答数据,而是多个应答数据的混合集,因此当你以单一应答数据来解析收到的数据时往往会发现应答数据格式不正确,在界面上的表现就是“没有收到数据”。
另外把收到的原始字节数组解析为程序能读懂的数据也是一项费时费力的事情,因此会出现“高速收,低速埋”的矛盾。但是,如果只让串口执行“收”,而辅助线程执行“埋”,那么就有效的解决了这个矛盾,即使下位机发的速度再高,系统也能抗得住。
联系客服