多裝置共用串列埠需要注意的問題
阿新 • • 發佈:2018-11-26
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。
不是所有裝置都是這樣的,只是某些。