多设备共用串口需要注意的问题

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。

不是所有设备都是这样的,只是某些。

猜你喜欢

转载自blog.csdn.net/lweiyue/article/details/82797344