CRC16 umwandeln in CRC16 modbus

Hallo,

ich generiere mit folgendem Code:

 #include <util/crc16.h>
      byte data[] = { 0x00, 0x20, 0x30, 0x00, 0x00, 0x00 };

      
    void setup() {
      Serial.begin(9600);
      Serial.println("CRC16 test started.");
      
    }
     
    void loop() {
      unsigned int crc = 0;
      for (unsigned int i = 0; i < sizeof(data); i++)
      {
        crc = _crc16_update(crc, data[i]);
      }
     
      Serial.print("CRC16 = ");
      Serial.println(crc,  HEX);
      Serial.println();
      delay(1000);
    }

einen funktionierenden CRC16 Wert. Allerdings benötige ich einen CRC16 Modbus Wert. Nach stundenlangem erfolglosen Googeln versuche ich es hier einmal. Sämtliche Erklärungen sind entweder als Binärwert beschrieben, oder in Python oder hochmathematisch oder...
Ich werde halt nicht schlau draus.
Ich überprüfe meine Werte hier:
http://www.lammertbies.nl/comm/info/crc-calculation.html
Auch deren Forum bringt mir nichts.
Wer kann helfen?

CRC16 Funktionen gibt es fertig. Du musst nur ein anderes Polynom verwenden

Gibt es sogar hier auf der avr libc Seite:
http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html

Oben ist die checkcrc() Funktion. Die ruft mehrmals crc16_update() auf, und darin setzt du dein Polynom ein

Dann lass uns doch mal an deinem Wissen teilhaben, was du wo bereits erarbeitet hast!

http://www.modbustools.com/modbus_crc16.htm

Wo ist das Problem, wenn das ganze in der Binärschreibweise beschrieben wird? Die Syntax von Python zu verstehen und das ganze in C umzusetzen, sollte nicht das Problem darstellen, in sofern gewisse Programmierkenntnisse vorhanden sind.

#Serenifly
Dieser Modbus ist ein eigenes Format. Der ist da anscheinend nicht gelistet.
Unter Wikipedia ist der CRC Code 2 stellig. Ich brauche diesen aber 4 stellig.
Siehe: http://www.lammertbies.nl/comm/info/crc-calculation.html
WO soll ich denn WELCHES Polynom einsetzen???

#sschultewolter
http://www.modbustools.com/modbus_crc16.htm
Das hab ich schon durchgekaut. Das ist der CRC16.

Mir ist auch klar, daß man Python-Code problemlos in C umsetzen kann. Wenn man den Code für CRC16 (Modbus) hat und das kann.

Damit bekomme ich auch dauernd falsche Werte:

Ah, ich glaube ich habe die erste Seite falsch verstanden. Ich dachte der Wert der da steht wäre das Polynom. Das soll aber die Checksumme sein :frowning:

Es muss doch irgendwo das verwendete Polynom stehen. Manche CRC Verfahren haben andere Algorithmen, aber meistens unterscheidet sich nur das Polynom

How to Compute the Modbus RTU Message CRC - Continental Control Systems, LLC

Das verwendet 0xA001 was auch genau das ist was deine avr libc Funktion aus #Reply 1 macht

Ich habe mir mal den C Code aus deinem ersten Link angesehen und da wird für Modbus auch die Standard CRC16 Funktion verwendet. Nichts spezielles:

crc_16_modbus  = update_crc_16(....)

Der Code arbeitet aber auch über eine Tabelle die mit einer init() Funktion berechnet wird.

Aber auch da ist das Polynom 0xA001 !

Nachtrag:
Einen Unterschied habe ich gefunden:

crc_16         = 0;
 crc_16_modbus  = 0xffff;

while ( *ptr ) {
  crc_16         = update_crc_16(     crc_16,         *ptr            );
  crc_16_modbus  = update_crc_16(     crc_16_modbus,  *ptr            );
}

Also das normale CRC16 nimmt 0 als Anfangswert und Modbus nimmt da 0xFFFF als Anfangswert. Vielleicht liegt es daran...

Das isses: FFFF
In den Herstellerunterlagen steht:
LRC=(FF-(01+03+F0+00+00+02))+1=(FF-F6)+1=09+1=0A
Was natürlich Quatsch ist, da der slave einen 4stelligen Wert benötigt.
Ich habe einfach dem CRC Wert statt 0 die FFFF zugewiesen. Das war das Ergebnis von mehreren Tagen herumexperimentieren:

   // http://www.lammertbies.nl/comm/info/crc-calculation.html
   //  CRC16 Modbus
    
    #include <util/crc16.h>
      byte data[] = { 0x01, 0x03, 0x01, 0x10, 0x00, 0x00 }; // gewünschten Wert eingeben
      
    void setup() { Serial.begin(9600);  }
     
    void loop()  {
      unsigned int crc = 0xFFFF;
      for (unsigned int i = 0; i < sizeof(data); i++)
       {
        crc = _crc16_update(crc, data[i]);
       }
      Serial.println(crc,  HEX);
      delay(1000);
    }

That's all! Nun muß nur noch das obere Nibble mit dem unteren vertauscht werden...
Danke an Alle!