1. 程式人生 > >多裝置共用串列埠需要注意的問題

多裝置共用串列埠需要注意的問題

Modbus協議定義了從機地址,也就是說我們可以在一條總線上連線多臺儀器,這些儀器使用從機地址進行區分。經過多年的開發,總結出一些共用串列埠方面需要注意的問題。

1、接收到的資料,必須檢驗從機地址

特別在多執行緒的開發環境下,先發送不一定先接收。也就是說,向A儀器傳送資訊之後,可能會收到B儀器返回的資訊。這時候,如果我們把不是A儀器從機地址的資訊丟棄,B儀器有可能就收不到資訊了。最壞的情況是這樣:發給A,收到B,發給B,收到A……。這樣的話,將收不到A、B裝置的任何資訊。我們可以把收到的資訊都存起來,然後分配給相應的從機地址的裝置。

byte[] recv = ComPortDict[PortName].Receive();//接收資料,儲存到臨時變數

if (recv != null && recv.Length != 0)//資料不為空
{
    int start = 0;
    while (true)//處理粘包問題
    {
        if (recv.Length < start + 5)
        {
            break;
        }

        byte func = recv[start + 1];
        int len = 8;
        if (func == 0x01 || func == 0x02 || func == 0x03 || func == 0x04)//第2位為位元組數
        {
            len = start + recv[start + 2] + 5;
        }

        if (recv.Length < len)
        {
            break;
        }

        byte[] data = new byte[len];
        Array.Copy(recv, start, data, 0, len);//節選內容

        string key = PortName + "_" + data[0];//加上從機地址儲存
        if (ComDataDict.ContainsKey(key))
        {
            ComDataDict[key] = data;
        }
        else
        {
            ComDataDict.Add(key, data);
        }

        start += len;
    }
}

string key2 = PortName + "_" + SlaveAddr;
if (ComDataDict.ContainsKey(key2))
{
    return ComDataDict[key2];
}

2、粘包問題

即使不是多裝置共用串列埠,粘包問題也是會出現的。只是在多裝置共用串列埠時,粘包出現的概率會非常高。這時候,只要我們把收到的位元組流按Modbus協議切好即可。

protected byte[] CutModbusPart(byte[] recv)
{
    if (recv == null)
    {
        return null;
    }

    int SlaveAddr = int.Parse(mDevice.Addition1);

    int start = 0;
    while (true)//處理粘包問題
    {
        if (recv.Length < start + 5)
        {
            break;
        }

        byte func = recv[start + 1];
        int len = 8;
        if (func == 0x01 || func == 0x02 || func == 0x03 || func == 0x04)//第2位為位元組數
        {
            len = start + recv[start + 2] + 5;
        }

        if (recv.Length < len)
        {
            break;
        }

        byte[] data = new byte[len];
        Array.Copy(recv, start, data, 0, len);//節選內容

        if (data[0] == SlaveAddr)
        {
            return data;
        }

        start += len;
    }

    return null;
}

3、不同裝置輪流傳送,第一次傳送會出現接收不到的問題

如題。假如我向A傳送指令,收到A的返回。這時我再向B發命令,有可能是收不到B的返回的。我們需要再發一次,才能收到。最壞的情況是:發A,收A,發B,收B,這種很正常的流程,我們竟然也收不到資訊。我們需要這樣:發A,收A,發B,發B,收B。

不是所有裝置都是這樣的,只是某些。