Hallo in die Runde!
Im laufe der Jahre sind bei Bascom immer mehr CRC-Routinen oberhalb der üblichen CRC8 hinzu gekommen, aber leider noch keine CRC-Routine die "beliebig modifizierbar" wäre.
Es scheitert weniger an dem Setzen andererer Generatorpolynome, als viel mehr solch Parameter wie Polynomlänge.
Aktuell geht es bei mir um bestehende Übertragungsprotokolle die ich nachbauen will, hier anhand von Pocsag:
Codewörter mit 32Bit Breite, davon 21Bit Nutzdaten, gefolgt von 10Bit CRC und zuletzt ein Parity-Bit.
Etliche solcher Codewörter werden in einem DWORD-Array gesammelt. Mein Test-Datensatz besteht z.B. aus 50 solcher Codewörter, die geprüft werden sollen.
Gebastelt habe ich mir folgendes:
Display All
Es wird also in der ersten Phase die Parity geprüft.
Im zweiten Schritt wird die CRC jedes DWORD's geprüft.
Im Prinzip funktioniert das auch....Protokollausdruck:
Display All
Soweit funktioniert alles, allerdings mit etwas suboptimaler Effizienz:
Während der Parity-Check der 50 Dwörter gefühlt im einstelligen ms-Bereich durchrast, dauert die CRC-Berechnung über alle 50 Testdatensätze gefühlt 20 Sekunden.
Läuft auf einem ATMEGA324PB mit Baudquarz auf 3,6864MHz.
Freilich: Die UART-Ausgaben (115200Bd) mögen etwas bremsen und können freilich raus genommen werden.
Aber die Rechenzeit ist derart brutal das es m.E. kaum was mit dem UART zu tun hat.
Und in der Phase wo diese Routine oben läuft, macht der µC sonst nichts anderes nebenher.
Ergo: Das DWORD-Array, das Kopieren von DWORD und die Parity prüfen läuft fix,
Das was bremst muss irgendwas im unteren Teil, dem Label "PocCRC" sein.
Also die Select Case-Funktion, die Verschiebug des Generatorpolynoms in DWORD PolShift, oder die XOR.Berechnung.
Das solch eine CRC-Prüfung zufuß nicht im µs geht ist klar. Aber wünschenswert wäre in jedem Fall etwas im Bereich 10-100ms maximal statt knappe 20 Sekunden.
Allerdings sehe ich den Flaschenhals gerade nicht...wo dran harkt es?
Jürgen
Im laufe der Jahre sind bei Bascom immer mehr CRC-Routinen oberhalb der üblichen CRC8 hinzu gekommen, aber leider noch keine CRC-Routine die "beliebig modifizierbar" wäre.
Es scheitert weniger an dem Setzen andererer Generatorpolynome, als viel mehr solch Parameter wie Polynomlänge.
Aktuell geht es bei mir um bestehende Übertragungsprotokolle die ich nachbauen will, hier anhand von Pocsag:
Codewörter mit 32Bit Breite, davon 21Bit Nutzdaten, gefolgt von 10Bit CRC und zuletzt ein Parity-Bit.
Etliche solcher Codewörter werden in einem DWORD-Array gesammelt. Mein Test-Datensatz besteht z.B. aus 50 solcher Codewörter, die geprüft werden sollen.
Gebastelt habe ich mir folgendes:
BASCOM Source Code
- Pruefen:
- Print "Es wurden ";Codewords;" Codewörter empfaangen, prüfe Parity:"
- i = 0 'i, j und k sind byte-Variablen für verschiedene Zwecke
- j = 0
- k = 0
- For i = 1 to Codewords
- Dwordbuffer = Codeword(i)
- Gosub Parity2
- If Parity = 0 then
- Print "CW ";i;" h";Hex(Dwordbuffer);" ist Even"
- k = k + 1
- else
- Print "CW ";i;" h";Hex(Dwordbuffer);" ist Odd"
- end If
- next
- Print "Die Parität ist über ";i;" Codewörter Even"
- For i = 1 to Codewords
- CRC = Codeword(i)
- Gosub PocCRC
- If CRC = 0 then
- Print "CW ";i;" h";Hex(Dwordbuffer);" CRC = ";CRC
- k = k + 1
- else
- Print "CW ";i;" h";Hex(Dwordbuffer);" CRC Fehler = ";CRC
- end If
- Next
- Print k;" Codewörter mit korrekter CTC"
- Daten = 0
- Return
- Parity2:
- 'Print "Parity2..."
- Pcheck = 0
- For j = 0 to 31
- If Dwordbuffer.j = 1 then Pcheck = Pcheck + 1
- Next
- ParitySingle = Pcheck / 2
- Parity = Frac(ParitySingle)
- Return
- PocCRC:
- Print "Codeword mit Parity = h";Hex(CRC);" und b";Bin(CRC)
- Shift CRC, Right, 1 'Entferne das Paritybit (LSB).
- 'Bit31 bleibt immer 0. das MSB (Adress/Nachrichtenbit) liegt nun auf Bit 30
- Print "Codewort ohne Parity = h";Hex(CRC);" und b";Bin(CRC)
- While CRC > 1024 'so lange Codeword > 10Bit groß...
- Select Case CRC
- Case &h00000000 to &h000007FF : L = 0
- Case &h00000800 to &h00000FFF : L = 1
- Case &h00001000 to &h00001FFF : L = 2
- Case &h00002000 to &h00003FFF : L = 3
- Case &h00004000 to &h00007FFF : L = 4
- Case &h00008000 to &h0000FFFF : L = 5
- Case &h00010000 to &h0001FFFF : L = 6
- Case &h00020000 to &h0003FFFF : L = 7
- Case &h00040000 to &h0007FFFF : L = 8
- Case &h00080000 to &h000FFFFF : L = 9
- Case &h00100000 to &h001FFFFF : L = 10
- Case &h00200000 to &h003FFFFF : L = 11
- Case &h00400000 to &h007FFFFF : L = 12
- Case &h00800000 to &h00FFFFFF : L = 13
- Case &h01000000 to &h01FFFFFF : L = 14
- Case &h02000000 to &h03FFFFFF : L = 15
- Case &h04000000 to &h07FFFFFF : L = 16
- Case &h08000000 to &h0FFFFFFF : L = 17
- Case &h10000000 to &h1FFFFFFF : L = 18
- Case &h20000000 to &h3FFFFFFF : L = 19
- Case &h40000000 to &h7FFFFFFF : L = 20
- End Select
- PolShift = Pocpolynom 'Generatorpolynom &h769 laden
- If L > 0 then
- Shift PolShift, Left, L 'Polynom an obersten Bit ausrichten
- end if
- Print "Shiftlänge = ";L;" und Ergebnis = b";Bin(Polshift)
- CRC = CRC XOR PolShift
- Print "Zwischenergebnis b";Bin(CRC)
- wend
- Return
Es wird also in der ersten Phase die Parity geprüft.
Im zweiten Schritt wird die CRC jedes DWORD's geprüft.
Im Prinzip funktioniert das auch....Protokollausdruck:
Source Code
- Codeword mit Parity = h7A89C197 und b01111010100010011100000110010111 Korrekt
- Codewort ohne Parity = h3D44E0CB und b00111101010001001110000011001011 Korrekt
- Shiftlänge = 19 und Ergebnis = b00111011010010000000000000000000 Korrekt
- Zwischenergebnis b00000110000011001110000011001011 Korrekt
- Shiftlänge = 16 und Ergebnis = b00000111011010010000000000000000 Korrekt
- Zwischenergebnis b00000001011001011110000011001011 Korrekt
- Shiftlänge = 14 und Ergebnis = b00000001110110100100000000000000 Korrekt
- Zwischenergebnis b00000000101111111010000011001011 Korrekt
- Shiftlänge = 13 und Ergebnis = b00000000111011010010000000000000 Korrekt
- Zwischenergebnis b00000000010100101000000011001011 Korrekt
- Shiftlänge = 12 und Ergebnis = b00000000011101101001000000000000 Korrekt
- Zwischenergebnis b00000000001001000001000011001011 Korrekt
- Shiftlänge = 11 und Ergebnis = b00000000001110110100100000000000 Korrekt
- Zwischenergebnis b00000000000111110101100011001011 Korrekt
- Shiftlänge = 10 und Ergebnis = b00000000000111011010010000000000 Korrekt
- Zwischenergebnis b00000000000000101111110011001011 Korrekt
- Shiftlänge = 7 und Ergebnis = b00000000000000111011010010000000 Korrekt
- Zwischenergebnis b00000000000000010100100001001011 Korrekt
- Shiftlänge = 6 und Ergebnis = b00000000000000011101101001000000 Korrekt
- Zwischenergebnis b00000000000000001001001000001011 Korrekt
- Shiftlänge = 5 und Ergebnis = b00000000000000001110110100100000 Korrekt
- Zwischenergebnis b00000000000000000111111100101011 Korrekt
- Shiftlänge = 4 und Ergebnis = b00000000000000000111011010010000 Korrekt
- Zwischenergebnis b00000000000000000000100110111011 Korrekt
- Shiftlänge = 1 und Ergebnis = b00000000000000000000111011010010 Korrekt
- Zwischenergebnis b00000000000000000000011101101001 Korrekt
- Shiftlänge = 0 und Ergebnis = b00000000000000000000011101101001 Korrekt
- Zwischenergebnis b00000000000000000000000000000000 Perfekt
- CW 1 h00000000 CRC = 0
Soweit funktioniert alles, allerdings mit etwas suboptimaler Effizienz:
Während der Parity-Check der 50 Dwörter gefühlt im einstelligen ms-Bereich durchrast, dauert die CRC-Berechnung über alle 50 Testdatensätze gefühlt 20 Sekunden.

Läuft auf einem ATMEGA324PB mit Baudquarz auf 3,6864MHz.
Freilich: Die UART-Ausgaben (115200Bd) mögen etwas bremsen und können freilich raus genommen werden.
Aber die Rechenzeit ist derart brutal das es m.E. kaum was mit dem UART zu tun hat.
Und in der Phase wo diese Routine oben läuft, macht der µC sonst nichts anderes nebenher.
Ergo: Das DWORD-Array, das Kopieren von DWORD und die Parity prüfen läuft fix,
Das was bremst muss irgendwas im unteren Teil, dem Label "PocCRC" sein.
Also die Select Case-Funktion, die Verschiebug des Generatorpolynoms in DWORD PolShift, oder die XOR.Berechnung.
Das solch eine CRC-Prüfung zufuß nicht im µs geht ist klar. Aber wünschenswert wäre in jedem Fall etwas im Bereich 10-100ms maximal statt knappe 20 Sekunden.
Allerdings sehe ich den Flaschenhals gerade nicht...wo dran harkt es?
Jürgen