2016-06-04 11 views
-1

Ich versuche, mit einem EPOS2-Motorcontroller über RS232 Serial mit einem Arduino Duemilanove zu verbinden (weil es das ist, was ich herumliegen hatte). Ich habe es größtenteils zum Laufen gebracht - ich kann Daten senden und empfangen, wenn ich die CRC-Prüfsumme manuell berechne - aber ich versuche, die Geschwindigkeit des Motors dynamisch zu steuern, die Daten ändern und daher die Prüfsumme ändern muss. Die Dokumentation für die Berechnung der Prüfsumme ist hier, auf Seite 24:Serielle Kommunikation zwischen Arduino und EPOS: CRC-Berechnungsprobleme

ich den Code direkt aus dieser Dokumentation kopiert, und integriert sie in meinen Code und es nicht die Prüfsumme korrekt zu berechnen. Unten ist eine verkürzte Version meiner vollständigen Skizze (getestet, was 0x527C ergibt). Der seltsamste Teil ist, dass er in meiner vollständigen Skizze einen anderen Wert berechnet als in der unteren, aber beide sind falsch. Ist etwas offensichtlich, dass ich vermisse?

byte comms[6] = { 0x10, 0x01, 0x03, 0x20, 0x01, 0x02 }; // CRC should be 0xA888 

void setup() { 
    Serial.begin(115200); 
} 

void loop() { 
    calcCRC(comms, 6, true); 
    while(1); 
} 

word calcCRC(byte *comms, int commsSize, boolean talkative) { 
    int warraySize = commsSize/2 + commsSize % 2; 
    word warray[warraySize]; 

    warray[0] = comms[0] << 8 | comms[1]; 
    Serial.println(warray[0], HEX); 

    for (int i = 1; i <= warraySize - 1; i++) { 
    warray[i] = comms[i * 2 + 1] << 8 | comms[i * 2]; 
    Serial.println(warray[i], HEX); 
    } 

    word* warrayP = warray; 

    word shifter, c; 
    word carry; 
    word CRC = 0; 


    //Calculate pDataArray Word by Word 
    while (commsSize--) 
    { 
    shifter = 0x8000; 
    c = *warrayP ++; 
    do { 
     carry = CRC & 0x8000; 
     CRC <<= 1; 
     if (c & shifter) CRC++; 
     if (carry) CRC ^= 0x1021; 
     shifter >>= 1; 
    } while (shifter); 
    } 

    if (talkative) { 
    Serial.print("the CRC for this data is "); 
    Serial.println(CRC, HEX); 
    } 

    return CRC; 
} 

ich den Link unten verwendet, um die Prüfsumme zu berechnen, die für diese Daten funktioniert:

https://www.ghsi.de/CRC/index.php?Polynom=10001000000100001&Message=1001+2003+0201

so vielen Dank !!

Antwort

0

Hier anzufangen.

Zunächst einmal verwenden Sie commsSize-- für Ihre Schleife, die sechs Mal durchlaufen wird, wenn Sie nur drei Wörter in der warray haben. Sie tun also einen Out-of-Bounds-Zugriff von warray und erhalten notwendigerweise ein zufälliges Ergebnis (oder einen Absturz).

Zweitens ist der Aufbau Ihres ersten Wortes rückwärts von Ihren anderen Builds. Ihr online CRC leidet unter dem gleichen Problem, also haben Sie anscheinend nicht einmal einen zuverlässigen Testfall.

Dritte (kein Problem für den Testfall), wenn Sie eine ungerade Anzahl von Bytes der Eingabe haben, tun Sie einen Out-of-Bounds-Zugriff von comms, um das letzte Wort auszufüllen. Und Sie führen die CRC-Bits zu oft aus, es sei denn, die Spezifikation lenkt in diesem Fall eine Art Padding. (Ihr Dokumentationslink ist unterbrochen, sodass ich nicht sehen kann, was passieren soll.) Auch dann verwenden Sie zufällige Daten für das Padding anstelle von Nullen.

Das ganze Wort Umwandlung Ding ist sowieso eine Verschwendung von Zeit. Sie können es bei der richtigen Reihenfolge der Bytes nur Byte für Byte tun. Dies vermeidet auch das Problem der ungeraden Anzahl von Bytes. Dies wird die 0xa888 vom Eingang produzieren sind Sie auf den Online-CRC-Rechner (die Ihre Bytes in einer verkorksten Ordnung sind, aber genau so, wie man sie an den Rechner gegeben hat):

unsigned char dat[6] = { 0x10, 0x01, 0x20, 0x03, 0x02, 0x01 }; 

unsigned crc1021(unsigned char *dat, int len) { 
    unsigned crc = 0; 
    while (len) { 
     crc ^= *dat++ << 8; 
     for (int k = 0; k < 8; k++) 
      crc = crc & 0x8000 ? (crc << 1)^0x1021 : crc << 1; 
     len--; 
    } 
    return crc & 0xffff; 
} 
+0

Dank! Das war hilfreich! Der Dokument-Link funktionierte auf mehreren Geräten, ich entschuldige mich dafür. Ich habe es mit Worten gemacht, weil die Dokumentation es so gemacht hat. Außerdem war die Byte-Reihenfolge "durcheinander", weil dies die Reihenfolge ist, die das EPOS benötigt, um sie zu erhalten. Um ehrlich zu sein, hätte ich meinen Code vielleicht besser kommentieren können ... Danke nochmal für die Hilfe! –

Verwandte Themen