2011-10-23 41 views
0

私はデバイス(MODBUSプロトコル)に接続しようとしており、CRC(CRC16)を計算する必要があります。そここのプロトコルの標準実装がありますが、私は、この式を使用して、私のCRCを作成する必要があります。奇妙なCRC計算

X15 + X2 + 1(この式で標準の実装があります:X16 + X15 + X2 + 1)

を私はCRCのためのdiffernt値をテストしましたが、それらのどれも私に正しい答えを与えていません。いくつかのバイトをポートに書き込む必要があります。このバイト文字列の最後には、デバイス情報を取得するために2つのCRCバイトを書き込む必要があります。

+0

だから質問は何ですか? – Amy

+0

私の質問は、X15 + X2 + 1の式を使ってCRCを見つける正確な方法です。このバイトを私のポートにどのように書き込むべきですか?私はC#(VS2010)を使用して、port.writeまたはport.writelineを使用する必要がありますか?これらのバイトをどのようにポートに渡すべきですか? ASCII文字列または16進数として?ありがとう –

+1

バイナリ文字列(バイト配列から形成することができます)、ASCII文字列も16進数も渡さないでください。 Port.Writeを使用できます。おそらく[Port.ByteArrayToString](http://franson.com/serialtools/reference_manual.asp?class=Port&item=ByteArrayToString&platform=net)を使用する必要があります。 –

答えて

2

ご質問はありますか? あなたの質問は、「メッセージの最後にMODBUSのCRCを計算すると、モデムのデバイスが有効なMODBUSメッセージとして認識されます。

もう1つのチェックサムまたはCRC機能を実装する前に、まず最初にテストベクタを取得しようとします。

の有効なメッセージの例がありますか?末尾にのCRCが含まれていますか?

ウィキペディアによれば、上位ビットは常に1であり、nビットのためCRCが(N + 1)によって定義されなければならないので、」cyclic redundancy check、 nビットレジスタをオーバーフロービット除数、いくつかの作家は、除数の上位ビットについて言及する必要はないと仮定しています。

MODBUSが "X^15 + X^2 + 1"多項式(16ビットのCRCであるため、x^16を理解している)を使用していると言う作者は、他の作家とまったく同じ多項式を参照していますつまり、MODBUSは "X^16 + X^15 + X^2 + 1"多項式を使います。 両方の著者は、まったく同じCRCを生成し、相互に相互運用可能なコードを記述します。

また、 "フォワード"方向の標準MODBUS CRCを計算する人は、しばしばマジック定数 "0x8005"を使用します。 標準的なMODBUS CRCを逆方向に計算する人は、代わりにマジック定数 "0xA001"を使用します( "0x8005"のビット反転)。 どちらの人も、まったく同じCRCバイトを生成し、相互に相互運用可能なコードを記述します。

オンラインでMODBUS CRC計算の多くの実装があります。おそらくそのうちの1つが役に立つかもしれません。オンライン

順不同で、オンラインの多くのオプション http://www.zorc.breitbandkatze.de/crc.html

CRC計算 http://www.lammertbies.nl/comm/info/crc-calculation.html

、多くの他の人とCRCの計算を生きる:

abcdefghijklm nopq

多くの実装では、バイト指向している少し速く実行されますが、大きなルックアップテーブル を必要とし(そしてどのようにテストそれは、ルックアップテーブルがあるかどうか私にはこれまで明らかからです有効)。

多くの実装では、はるかに短いプログラムサイズ を生成し、次のようなバグが潜んでいる(ただし、チェックサムを計算するように長さ約8倍を取る)ことができ、より少ないほこりの多いコーナーを、持っている、ビット指向です:

// warning: untested code 
// optimized for size rather than speed 
// (i.e., uses a bit-oriented calculation rather than table-driven calculation) 
uint16_t modbusCRC(uint8_t* data, int length) { 
    uint16_t crc = 0xFFFF; 
    for(int pos = 0; pos<length; pos++){ 
     crc ^= (uint16_t)data[pos]; 
     for(int i=0; i<8; i++){ 
      if(crc & 1){  // LSB is set 
       crc >>= 1;     // Shift right 
       crc ^= 0xA001;    // XOR 0xA001 
      }else{       // LSB is not set 
       crc >>= 1; 
      }; 
     }; 
    }; 
    return crc; 
} 
int main(void){ 
    uint8_t message[80] = { // 6-byte test vector 
     0x11, 0x03, 0x00, 0x6B, 0x00, 0x03 
    }; 
    int message_length = 6; 
    uint16_t the_CRC = modbusCRC(message, message_length); // find CRC of the message 
    message[message_length++] = the_CRC & 0xFF; // send low byte first 
    message[message_length++] = the_CRC >> 8; // then send high byte 
    assert(0x76 == message[6]); // test against known-good CRC 
    assert(0x87 == message[7]); 
    send_message(message, message_length); // send all 8 bytes of the message, 
    // including the two MODBUS CRC bytes. 
    // (Must send *all* 8 bytes of the message, 
    // even though there are multiple 0x00 bytes). 
} 

"バイナリMODBUS"( "Modbus RTUフレームフォーマット")は、メッセージのすべてのデータを2 CRCバイトを含む未加工の8ビットバイトとして送信します。

"ASCII MODBUS"( "Modbus ASCIIフレームフォーマット")は、8ビットのチェックサムを含む多かれ少なかれ単純なASCIIテキストとしてメッセージを送信します。 (チェックサムは2バイトのASCII 16進数の2文字として送信されます)。