串口通信之并发与单步

物理连接示意图如下所示,每个串口挂接多个采集器。

通信协议:

包头(1B) + 地址码(1B) + 命令字(1B) + 数据长度(1B) + 校验码1(1B) + 数据正文(nB) + 校验码2(1B)。

 

其中,校验码1校验地址码、命令字、数据长度,校验码2校验数据正文。

 

1. 并发通信,性能能高。下发命令顺序与返回数据的顺序可能不一致,要保证并发能够正常通信有个前提——返回数据包在接收缓冲区中不会断包,即不会出现A包前6字节 + B包 + A包后10字节之类数据。可能存在问题:a>连续向发送缓冲区写多(如50)条命令,发送缓冲区会混乱吗? b>怎么计算某个采集设备超时? c>发送命令的速度与各路数据返回的速度的平衡能控制吗?

   首先应该知道,多个采集设备通过串口R485总线连接在同一个串口上,而总线在某一时刻只能允许一路设备发送数据,其他各路设备都能收到此条数据。

  采用串口并发通信有3个前提:a>使用R485总线,而不是R232;b>同一串口挂载了多路设备;c>下位机采集设备处理返回数据时间较长。如果挂接了20路设备,每路收到命令后需10ms(5ms通信+5数据准备)返回数据,则单步轮询一次共需200ms,这样的实时性应该可以接受。但是如果每路收到命令后需200ms(5ms通信+195ms数据准备)返回数据,则单步轮询一次共需3900ms,这样的实时性是很差的,往往满足不了需求。我们完全可以让195ms并发。

图4  串口通信数据流图

 

串口并发以及时间如下:

  a> 一次轮询下发所有(20路)设备数据准备命令;

  b> 各路设备收到自己地址码的查询命令后,开始准备数据(195ms并发);

  c> 上位机等待300ms;

  d> 上位机逐路请求采集器数据;

  e> 某一个接收到请求自己数据命令后,返回b>准备好的数据(10ms);

  f> 上位机接收到某路下位机数据后,处理并显示,再执行d>

  共耗时:300(等各路完成195) + 10*20 = 500ms

   图2串口并发流程其实是不可能出现的,因为串口总线的控制只能通过d-f步骤来。

 

 

串口同步以及时间如下:

  a> 上位机逐路请求采集器数据;

  b> 某一个接收到请求自己数据命令后,准备数据(195ms),返回数据(5);

  c> 上位机接收到下位机数据后,处理并显示,再执行a>

  共耗时:(195 + 5) *20 = 4000ms

 

2. 单步通信,单步通信性能稍差。逐路发送命令,a>怎么更有效的等待当前路数据返回?

 

代码段一(串口单步方案1,发送线程和接收事件线程通过IsWaitingReceive同步。请问IsWaitingReceive多线程控制,会不会有无问题?):

    private bool IsWaitingReceive = false;

        private void SendCmdThread()

        {

            while (true)

            {

                if (!IsWaitingReceive)  //可以下发逐路轮询命令了

                {

                    SendOneCmd();

                    IsWaitingReceive = true;

                }

                Thread.Sleep(50);

            }

        }

 

        private int CurDeviceNo = 0;

        private int TotalDeviceCnt = 20;

        private void SendOneCmd()

        {

            //向地址码为CurDeviceNo设备发命令请求

            m_SerialPort.Write(buf, offset, count);

 

            //轮询设备

            ++CurDeviceNo;

            if (CurDeviceNo >= TotalDeviceCnt) CurDeviceNo = 0;

        }

 

        private byte[] m_RcvBuf = new byte[512];

        private int RcvCnt = 0;

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            int nLen = m_SerialPort.Read(m_RcvBuf, RcvCnt, m_SerialPort.BytesToRead);

            RcvCnt += nLen;

 

            //接下来在全局m_RcvBuf中查找合法完整数据包,解析、处理业务

     ······

            if (CurDeviceNo == 当前数据包中地址码)

                IsWaitingReceive = false;

        }

 

代码段二(串口单步方案2,同一个线程处理发送和接收):

   private int TotalDeviceCnt = 20;

        private void ComCmdThread()

        {

            byte[] bArr = null;

            while (true)

            {

                for (int i = 0; i < TotalDeviceCnt; i++ )    //轮询一轮

                {

                    bArr = SendOneCmd(i);

                    if (bArr != null)

                    {

                        DealData(bArr);

                    }

                }

                Thread.Sleep(200);

            }

        }

 

        private byte[] SendOneCmd(int curNo)

        {

            byte[] bRcv = null;

 

            m_SerialPort.DiscardInBuffer();         //清空接收缓存区以前多余的数据

            m_SerialPort.Write(buf, offset, count); //向curNo路设备发送命令

            Thread.Sleep(50);                       //延时,等待下位机回数据

 

            int nStartTime = Environment.TickCount;

            while (true)

            {

                if (Environment.TickCount - nStartTime > 100)    //超时

                {

                    Console.WriteLine("等待超时...");

                    break;

                }

                if (m_SerialPort.BytesToRead >= 25) //如果一个完整的数据包固定25字节

                {                                         //如果不是固定长度,可以进全局Buf,然后查找解析合法数据包

                    bRcv = new byte[25];

                    int nLen = m_SerialPort.Read(bRcv, 0, 25);  //这三个25,可以用其他变量代替

                    break;

                }

                //Thread.Sleep(10);     //看情况是否允许需要

            }

 

            return bRcv;

        }

        private void DealData(byte[] data)

        {

            //分析验证数据包的合法性

           ······

            //处理合法包的业务数据

    ······

        }

posted on 2012-05-07 21:51  fyhui  阅读(4103)  评论(1编辑  收藏  举报