hi, es kam auch hier schon einige male die Frage nach dem CRC beim 1-Wire auf. Jedoch nichts was mich weiter gebracht hat :( Ich weiß nicht ob ich die sache mit dem CRC schon ganz verstanden habe... auch die sache mit dem CRC Polynom. Aber wenn ich es richtig verstehe bekomme ich 9 Bytes aus dem Scratchpad. Diese Speichere ich auch fein ab um Später damit zu arbeiten. Nun möchte ich jedoch testen ob die Daten richtig sind. Dazu habe ich ja das Byte 8 in dem sich die Prüfsumme des Blocks (Byte 0 bis Byte 7) befinden. Nun würde ich die Prüfsumme des Blocks errechnen und mit dem CRC Byte (Byte 8) abgleichen um herrauszufinden ob die übertragung erfolgreich war. Hier ist der hacken... ich finde immer wieder Codes usw. in denen ich den CRC eines Bytes errechnen kann... aber ich verstehe nicht wie es funktioniert und wie ich es dann für den ganzen Block mache... Evtl. kann mir ja jemand von euch helfen.
:
Gesperrt durch Moderator
Es gibt bestimmt tausende Erklärungen zu CRC und Beispielcode im Netz. Lies dich mal in die Theorie in Wikipedia ein und danach kannst du bestimmt eine CRC implementierung irgendwo finden. http://de.wikipedia.org/wiki/Zyklische_Redundanzprüfung Falls du AVR-GCC benutzt, gibt es dort den crc16.h Header, in diesem ist eine _crc_ibutton_update(uint8_t crc, uint8_t data) Funktion definiert, dies entspricht der CRC Funktion für alle 1Wire Devices von Maxxim also auch für das DS18B20.
1 | uint8_t crc=0; |
2 | |
3 | crc= _crc_ibutton_update(crc, databyte1); |
4 | crc= _crc_ibutton_update(crc, databyte2); |
5 | crc= _crc_ibutton_update(crc, databyte3); |
6 | ...
|
7 | ...
|
8 | crc= _crc_ibutton_update(crc, crc_DS18B20); |
9 | |
10 | //Wenn crc==0 dann alles ok, sonst Fehler.
|
Hier siehst du, wie man Funktionen für ein einzelnes Byte auf einen ganzen Block von Bytes anwendet. gruß cyblord
ah... den Link habe ich interessanter weise nicht gefunden... vielleicht falsche Suchbegriffe verwendet. Ich denke, jetzt habe ich die Sache mit dem CRC-Polynom verstanden. Bei meinem zu verwendenden Polynom handelt es sich ja um: x^8+x^5+x^4+1 = 1x^8+0x^7+0x^6+1x^5+1x^4+0x^3+0x^2+0x^1+1x^0 = 100110001 Also ist das meine Bitfolge des CRC-Polynoms. Richtig? Polynomdivision kann ich, aber ich wusste nicht wie ich es hier aufbauen/anwenden sollte ^^ Ich lese noch mal weiter und hoffe auf eine bestätigung von dir, ob ich mich da nicht versehen habe. ;)
Alles klar, ich habe es geschafft... ich habe einen definitiv richtigen Datensatz des DS18B20 ausgelesen und nach dem schema von Hand durchgerechnet. Hat sogar geklappt... Ohne einen fehler... hat aber auch lang genug gedauert :D Als ich dann verstanden habe wie das Prinzip funktioniert, konnte ich es umstzen. Danke dir. Ich würds hier gern mehr erklären, aber ich denke dass muss man wirklich selber MACHEN um es zu verstehen. Also ich rate jedem mit dem gleichen Problem, rechnet es einfach mal durch. Oben steht schon die Bitfolge für die Umrechnung!
wenn deine CRC Berechnung geklappt hat, könntest du die mal posten ? oder ein dein fertiges Programm ? MFG
Um die CRC-Berechnung nach Maxim 1-wire nachvollziehen zu können, habe ich anhand der AN27 das Sheet im Anhang gebastelt. Man muss dazu in der Spalte Input (weiße Felder) die einzelnen Bits eingeben und kann daneben die Entwicklung der CRC nachverfolgen. Im gelben Fenster zu Beginn der Zeile nach dem letzten eigegebenen Bit kann der CRC-Wert dann abgelesen werden, z.B. 5Eh, falls man den Wert 01h mit Anfangszustand 00h eingibt.
Warum genau wird hier eigentlich Seitenweise aus einer popeligen CRC Berechnungen der heilige Grahl gemacht? Worum gehts hier denn jetzt eigentlich? Das Polynom ist bekannt und es ist klein. CRC ist allseits bekannt und funktioniert mit jedem Generatorpolynom ungefähr gleich. Genau das CRC8 von Maxxim ist im AVR-GCC mit dabei und somit ist auch die Implementierung gegessen. Also wo ist jetzt das Problem dass man hier derart ausdauernd über ein derart triviales "Problem" diskutiert? gruß cyblord
Ich habs mal selbst geschrieben. Damit brauch ich keine LIB mehr... w1_data[] ist der Sende-/Empfangsbuffer. Mit dem 'case 35' ist das Lesen des Scratchpad fertig. 'case 36' macht je Byte einen Einsprung (entspricht einer for-Schleife über 'w1_bytenr' - läuft am Arduino mit kurzen Zyklen).
1 | case 35: /* wait reading ready */ |
2 | w1_bytenr = 0; |
3 | w1_crc = 0; |
4 | w1_action = 36; |
5 | break; |
6 | |
7 | case 36: /* calc/check CRC - get data */ |
8 | if (w1_bytenr < 8) |
9 | {
|
10 | w1_crc ^= w1_data[w1_bytenr]; |
11 | for (bitcnt = 0; bitcnt < 8; bitcnt++) |
12 | {
|
13 | if (w1_crc & 0x01) |
14 | {
|
15 | w1_crc >>= 1; |
16 | w1_crc ^= 0x8C; |
17 | }
|
18 | else
|
19 | w1_crc >>= 1; |
20 | }
|
21 | w1_bytenr++; |
22 | }
|
23 | else
|
24 | {
|
25 | /* CRC ready - compare it.. */
|
26 | if (w1_crc == w1_data[8]) // CRC check |
27 | {
|
28 | un16bit.uc[0] = w1_data[0]; |
29 | un16bit.uc[1] = w1_data[1]; |
30 | w1_temp[w1_channel][w1_idx[w1_channel]] = (un16bit.i * 10) / 16; |
31 | //sprintf(buf, "Tmp@%d=%d %d-%d", (int)w1_channel, (int)w1_temp[w1_channel][w1_idx[w1_channel]], (int)w1_data[8], (int)w1_crc);
|
32 | //RS485HwSerial0.println(buf);
|
33 | w1_idx[w1_channel] = (w1_idx[w1_channel] + 1) % 4; |
34 | w1_err[w1_channel] = 0; |
35 | }
|
36 | else
|
37 | {
|
38 | if (w1_err[w1_channel] < 5) w1_err[w1_channel]++; |
39 | else
|
40 | {
|
41 | mask = 1 << w1_channel; |
42 | w1_found &= ~mask; |
43 | }
|
44 | }
|
45 | w1_action = 0; |
46 | }
|
47 | break; |
Helmut -. schrieb: > Hast dafür fast 11 Jahre gebraucht? Reschbeggd! Und vor allem so ein Fragment, das so gut lesbar und weiter nutzbar ist . . . Vielleicht doch besser so? Beitrag "Re: Onewire + DS18x20 Library"