2013-08-28 24 views
6

私はmodbus rs485 rs232を介して2つの位相計に通信するためにC#を使用しています。Modbus通信

私は読み取り値を受信できるように、バスを介してデータを送信する必要があります。
通常のワイヤを接続して送受信を短絡しました。データを受け取っていると、このイベントが発生する

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    byte[] buff = new byte[sp.BytesToRead]; 

    //Read the Serial Buffer 
    sp.Read(buff, 0, buff.Length); 
    string data= sp.ReadExisting(); 

    foreach (byte b in buff) 
    { 
     AddBuffer(b); //Add byte to buffer 
    } 
} 

次に、このバッファは、このいずれかである別の関数に送信されます。

private void AddBuffer(byte b) 
{ 
    buffer.Add(b); 

    byte[] msg = buffer.ToArray(); 

    //Make sure that the message integrity is correct 
    if (this.CheckDataIntegrity(msg)) 
    { 
     if (DataReceived != null) 
     { 
      ModbusEventArgs args = new ModbusEventArgs(); 
      GetValue(msg, args); 
      DataReceived(this, args); 
     } 
     buffer.RemoveRange(0, buffer.Count); 

    } 
} 

私はこの問題は、データであることを考えます完全性チェック:

public bool CheckDataIntegrity(byte[] data) 
{ 
    if (data.Length < 6) 
     return false; 
    //Perform a basic CRC check: 
    byte[] CRC = new byte[2]; 
    GetCRC(data, ref CRC); 
    if (CRC[0] == data[data.Length - 2] && CRC[1] == data[data.Length - 1]) 
     return true; 
    else 
     return false; 
} 

CRCチェックがありますが、奇妙なことは、本当ではない。 CRC計算:

private void GetCRC(byte[] message, ref byte[] CRC) 
{ 

    ushort CRCFull = 0xFFFF; 
    byte CRCHigh = 0xFF, CRCLow = 0xFF; 
    char CRCLSB; 

    for (int i = 0; i < (message.Length) - 2; i++) 
    { 
     CRCFull = (ushort)(CRCFull^message[i]); 

     for (int j = 0; j < 8; j++) 
     { 
      CRCLSB = (char)(CRCFull & 0x0001); 
      CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); 

      if (CRCLSB == 1) 
       CRCFull = (ushort)(CRCFull^0xA001); 
     } 
    } 
    CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF); 
    CRC[0] = CRCLow = (byte)(CRCFull & 0xFF); 
} 
+0

一般的な通信セッションのトランスクリプトを持っていて、CRCを備えたオンラインリソースはありますか?そして、あなたは少なくともそれらのサンプルメッセージにあなたのアルゴリズムを適用して、あなたが同じCRCを思い付くかどうかを知ることができます。 –

+1

"バッファ"変数とは何ですか?それはリストですか??あなたの "msg"変数が6より大きいと確信していますか?シリアルポートのバッファをバイト単位で分割するのではなく、リストで再構築してからグローバルバイト配列に変換するのはなぜですか?また、バッファの内容を読み込んだ直後にシリアルポートでReadExistingを呼び出すのはなぜですか? –

+0

CRCは正しい@AndyzSmithのようです。 本当にどこかでreadexistingを呼び出すことは何ですか?はいバッファはリストです – Combinu

答えて

2

問題はReadExisting()の使用です。バッファーがシリアルポートからの無駄なデータで満たされていたので、この方法では使用されませんでした。この問題はコメント内の@glaceによって識別されました!

1

あなたMODPOLLのようないくつかの既存のModbusマスタアプリケーションを介して、あなたのメーターとの通信を確立するための最初の必要性。次に、通信が正常に機能し、デバイスから有効な応答があったら、コードのテストを開始します。このようにして、問題はコード内のみに存在することができます。

たとえば、同時に2つのスレーブデバイスに接続するには、RS232の代わりにRS485を使用する必要があります。これは、PC側で異なる配線とRS485 to RS232コンバータを要求します。

RXとTXをシミュレーション目的でRS232に接続することは、マスターからの各MODBUSメッセージ(ブロードキャストメッセージを除く)がメッセージエコーとは異なる応答を必要とするため、良い考えではありません。また、マスターからの各MODBUSメッセージにはMODBUSクライアントアドレスが埋め込まれており、単一のクライアントだけがそれに応答する必要があります(MODBUSは単一マスター複数のスレーブプロトコルです)。 CRC計算用として

、これは(ASCIIが異なる)MODBUS RTUプロトコルのために役立つかもしれない:

function mb_CalcCRC16(ptr: pointer to byte; ByteCount: byte): word; 
var 
    crc: word; 
    b, i, n: byte; 
begin 
    crc := $FFFF; 
    for i := 0 to ByteCount do 
    if i = 0 then   // device id is 1st byte in message, and it is not in the buffer 
     b := mb_GetMessageID; // so we have to calculate it and put it as 1st crc byte 
    else 
     b := ptr^; 
     Inc(ptr); 
    endif; 
    crc := crc xor word(b); 
    for n := 1 to 8 do 
     if (crc and 1) = 1 then 
     crc := (crc shr 1) xor $A001; 
     else 
     crc := crc shr 1; 
     endif; 
    endfor; 
    endfor; 
    Return(crc); 
end; 

function mb_CalcCRC: word; // Calculate CRC for message in mb_pdu 
begin // this message can be one that is just received, or in a reply we have just composed 
    Return(mb_CalcCRC16(@mb_pdu[1], mb_GetEndOfData)); 
end; 

実装MODBUS RTUスレーブプロトコルでの作業組み込みAVRデバイスからの引用です。

+0

あなたの助けてくれてありがとう私は実際に問題が働いている...私はシリアルポートから間違って読んでいたようだ...しかし、まだ多くのappriciated! – Combinu

+0

@MysticJay解決策を回答として追加することができます(あなた自身の質問に答えることができます)。私はこれが、将来の読者が同様の問題に遭遇した場合に役立つと思う。 (私は参照のために[xkcd](http://xkcd.com/979/)を参照してください) – Default

+0

私はこれはCだとは思わない# – mrid

関連する問題