Hallo Leute, ich übertragen Daten über eine RS232 Verbindung zwischen 2 XMEGA µC. Beide µC besitzen einen Hardware CRC-Core. Bis vor einigen Stunden wollte ich eine Software CRC8 Checksumme mit Hilfe einer Tabelle berechnen. Nun habe ich jedoch gesehen das der XMEGA einen Hardware-Kern für die Berechnung der Checksumme besitzt. Allerdings besitzt der XMGEA nur eine CRC 16 und CRC32 Checksumme. Da ich aber nur wenige Bytes (so zwischen 3 und 6 Bytes) zwischen den beiden µC übertrage halte ich eine CRC 16 Checksummer schon für zu viel. Daher wollte ich auch die CRC8 Checksummer in Software umsetzen. 1. Hat es Nachteile wenn ich so wenige Bytes mit einer CRC16 Checksumme schütze? (außer das ich als Checksumme 1 Bytes mehr übertragen muss) 2. Oder kann ich mit dem XMEGA auf CRC8 Checksummen berechnen?
Dies ist mein 1. Code um die CRC Checksumme auf dem XMEGA zu berechnen. Allerdings habe ich den Code noch nicht getestet. ICH BIN MIR NICHT SICHER OB ICH DEN RESET WIEDER ZURCÜKNEHEMEN MUSS, DAMIT DER KERN STARTET
1 | unsigned short calculate_crc16_checksum(unsigned char *data, unsigned char count) |
2 | {
|
3 | unsigned char i = 0; |
4 | unsigned short crc16_checksum = 0; |
5 | |
6 | // Die 4 Checksum Register auf 0x00 zurücksetzen
|
7 | CRC.CTRL = (CRC.CTRL & (~CRC_RESET_gm)) | CRC_RESET_RESET0_gc; |
8 | |
9 | // Den CRC-Kern anhalten, indem keine Quellec angegeben wird
|
10 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_DISABLE_gc; |
11 | |
12 | // Den CRC-Kern auf CRC16 konfigurieren
|
13 | CRC.CTRL &= ~CRC_CRC32_bm; |
14 | |
15 | // IO als Quelle für den CRC-Kern auswhählen
|
16 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_IO_gc; |
17 | |
18 | //ACHTUNG IST RESET IMMER NOCH 1?
|
19 | |
20 | for(i=0; i<count; i++) |
21 | {
|
22 | CRC.DATAIN = data[i]; |
23 | }
|
24 | |
25 | // Das Busy Flag muss im CRC IO-Modus gelöscht werden, indem eine 1 in das Register geschrieben wird
|
26 | CRC.STATUS |= CRC_BUSY_bm; |
27 | |
28 | while((CRC.STATUS & CRC_BUSY_bm) == CRC_BUSY_bm) |
29 | {
|
30 | // Nichts machen solange der CRC-Kern noch beschäftigt ist
|
31 | }
|
32 | |
33 | crc16_checksum = ((unsigned short) CRC.CHECKSUM0 & 0x00FF); |
34 | crc16_checksum |= (((unsigned short) CRC.CHECKSUM1 << 8) & 0xFF00); |
35 | |
36 | // Den CRC-Kern anhalten, indem keine Quellec angegeben wird
|
37 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_DISABLE_gc; |
38 | |
39 | return crc16_checksum; |
40 | }
|
Wenn ich jetzt die Checksummer von z.B. 3 Bytes berechne, dann hänge ich die CRC16 Checksummer an die Bytes ran bevor ich diese über die RS232 an meinen anderen µC sende. Nun zu meiner Frage muss ich ich Checksummer nur über die Daten berechnen oder muss ich die Checksummer in der Checksummenberechnung mit einbeziehen?
Nabend, nur über die Daten. Wie soll ein noch zu berechnender und damit unbekannter Wert (die CRC16) mit einfließen? MfG
Hat denn schon jemand diesen CRC Kern von ATMEL benutzt? Wie ist denn das mit der Reset Leitung die setze ich ja zu Beginn auf '10' Danach disable ich ja die Quelle. Danach muss konfiguriere ich den Kern auf auf CRC16. Muss ich dach wieder die Reset Leitung auf '00' setzen Wie ist es denn mit der BUSY Signal im IO Modus. Muss ich dort eine '1' reinschreiben, damit der Kern angehalten wird oder benötige ich die busy Leitung nicht im IO-Modus?
So ich habe mal den Atmel Hardware CRC Kern ausprobiert. Leider funktioniert dieser nicht. Hier nocht mal mein Quellcode vielleicht sieht ja jemand sofort den Fehler:
1 | // CRC-16(CRC-CCITT) Polynom x^16 + x^12 + x^5 + 1 --> 0x1021
|
2 | |
3 | unsigned short calculate_crc16_checksum(unsigned char *data, unsigned char count) |
4 | {
|
5 | unsigned char i = 0; |
6 | unsigned short crc16_checksum = 0; |
7 | |
8 | // Die 4 Checksum Register auf 0x00 zurücksetzen
|
9 | CRC.CTRL = (CRC.CTRL & (~CRC_RESET_gm)) | CRC_RESET_RESET0_gc; |
10 | |
11 | // Den CRC-Kern anhalten, indem keine Quellec angegeben wird
|
12 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_DISABLE_gc; |
13 | |
14 | // Den CRC-Kern auf CRC16 konfigurieren
|
15 | CRC.CTRL &= ~CRC_CRC32_bm; |
16 | |
17 | // IO als Quelle für den CRC-Kern auswhählen
|
18 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_IO_gc; |
19 | |
20 | //ACHTUNG IST RESET IMMER NOCH 1?
|
21 | CRC.CTRL &= ~CRC_RESET_gm; |
22 | |
23 | for(i=0; i<count; i++) |
24 | {
|
25 | CRC.DATAIN = data[i]; |
26 | }
|
27 | |
28 | // Das Busy Flag muss im CRC IO-Modus gelöscht werden, indem eine 1 in das Register geschrieben wird
|
29 | CRC.STATUS |= CRC_BUSY_bm; |
30 | |
31 | while((CRC.STATUS & CRC_BUSY_bm) == CRC_BUSY_bm) |
32 | {
|
33 | // Nichts machen solange der CRC-Kern noch beschäftigt ist
|
34 | }
|
35 | |
36 | crc16_checksum = ((unsigned short) CRC.CHECKSUM0 & 0x00FF); |
37 | crc16_checksum |= (((unsigned short) CRC.CHECKSUM1 << 8) & 0xFF00); |
38 | |
39 | // Den CRC-Kern anhalten, indem keine Quellec angegeben wird
|
40 | CRC.CTRL = (CRC.CTRL & (~CRC_SOURCE_gm)) | CRC_SOURCE_DISABLE_gc; |
41 | |
42 | return crc16_checksum; |
43 | }
|
44 | |
45 | //Im Hauptprogramm erzeuge ich ein Array mit 8 Bytes (vorbelegt)
|
46 | |
47 | /*Dann rufe ich die Funktion auf und übertrage die Checksumme an den PC über eine RS232 Leitung. Jedoch kommt immer als Checksumme 0 raus. HIIILFE*/
|
48 | |
49 | unsigned char crc_testdata[8] = {0x43, 0x23, 0x83, 0x10, 0x82, 0x44, 0x92, 0x31}; |
50 | unsigned short crc16_checksum = 0; |
51 | |
52 | crc16_checksum = calculate_crc16_checksum(&crc_testdata[0], 8); |
53 | |
54 | printf("Die Checksumme lautet: %d", crc16_checksum); |
Scheint wohl keiner den CRC-Core von XMEGA zu benutzen :-) Da muss ich wohl selber das Problem lösen :-))))
Schonmal ins ASF reingeschaut? Dort müsste m.W. ein Treiber für das CRC-Modul rumliegen, vielleicht bringt das etwas Licht ins Dunkel?
Sebastian schrieb: > // Das Busy Flag muss im CRC IO-Modus gelöscht werden, indem eine 1 in das Register geschrieben wird > CRC.STATUS |= CRC_BUSY_bm; Ich kenne den XMEGA nicht, aber wenn flags gelöscht werden sollen durch schreiben einer 1 macht man das normalerweise so: CRC.STATUS = CRC_BUSY_bm; Denn deine |= Anweisung liest erst den Wert und überschreibt alle weiteren gesetzen Bits ebenfalls mit 1 und setzt diese zurück.
@ Gizmo2 Du hast recht damit würde ich auch die anderen überschreiben.
So ich habe mir meinen Quellcode mal mit dem Debugger angeschaut. Immer wenn ich CRC.DATAIN = 0xAA; ausführe wird nichts in das DATAIN Register des µC übernommen. Dadurch ändert sich auch nie die Checksummer und bleibt immer 0. Wenn ich mit dem Debugger ins DATAIN Register manuell einen Wert reinschreibe, dann ändern sich sofort die Checksum Register so wie es sein soll. Ist vielleicht die Adresse von dem DATAIN Register falsch?
1 | for(i=0; i<count; i++) |
2 | {
|
3 | //CRC.DATAIN = data[i];
|
4 | //CRC.DATAIN = testdata[i];
|
5 | CRC.DATAIN = 0xAA; |
6 | }
|
Ich habe den Fehler gefunden. Das H-File vom Compiler war fehlerhaft, so das die Adresse von dem DATAIN und den danach folgenden Registern falsch war. Nachdem ich das behoben hatt funktioniert die Checksummenberechnung. hier der alter Code aus dem H-File:
1 | typedef struct CRC_struct |
2 | {
|
3 | unsigned char CTRL; // CRC Control Register |
4 | unsigned char STATUS; // CRC Status Register |
5 | unsigned char DATAIN; // CRC Data Input |
6 | unsigned char CHECKSUM0; // CRC Checksum byte 0 |
7 | unsigned char CHECKSUM1; // CRC Checksum byte 1 |
8 | unsigned char CHECKSUM2; // CRC Checksum byte 2 |
9 | unsigned char CHECKSUM3; // CRC Checksum byte 3 |
10 | } CRC_t; |
1 | typedef struct CRC_struct |
2 | {
|
3 | unsigned char CTRL; // CRC Control Register |
4 | unsigned char STATUS; // CRC Status Register |
5 | unsigned char reserved_0x02; |
6 | unsigned char DATAIN; // CRC Data Input |
7 | unsigned char CHECKSUM0; // CRC Checksum byte 0 |
8 | unsigned char CHECKSUM1; // CRC Checksum byte 1 |
9 | unsigned char CHECKSUM2; // CRC Checksum byte 2 |
10 | unsigned char CHECKSUM3; // CRC Checksum byte 3 |
11 | } CRC_t; |
Durch die Korrektur befindet sich das DATAIN Register nun auf der Adresse D3. Zuvor war die Adresse vom DATAIN Register D2 und diese Adresse ist reserviert.
Als nächstes werde ich mal die Zeit messen, die ich für die Berechnung der Checksummer benötige :-)
Sebastian schrieb: > Ich habe den Fehler gefunden. Das H-File vom Compiler war fehlerhaft, so > das die Adresse von dem DATAIN und den danach folgenden Registern falsch > war. Nachdem ich das behoben hatt funktioniert die > Checksummenberechnung. Ärgerlicher Fehler. Welche Toolchain-Version? In der aktuellen Version (Atmel Studio 6) ist die Struktur korrekt.
Ich benutze den aktuellen Codevision Compiler und da ist die Struktur leider falsch. Ich werde morgen mal Codevision anschreiben, so das dies mal geändert wird.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.