ausgabe in intel hex format
-
Hello,
ich habe in diesem Forum schon ein paar hilfreiche Informationen gefunden und bin mir sicher, dass ihr die Problemstellung mit Leichtigkeit lösen könnt.Ich soll ein c Programm entwickeln, dass einen Mikrokontroller steuert.
Der Mikrokontroller steuert 8 Leuchten die jeweils 2 LEDs installiert haben. Aufgrund der intensität ergeben sich dann ein paar Farben in hübscher Reihenfolge. Soviel zur Theorie.Die Infos werden aus einer .csv ausgelesen. D.h. die Farbwerte sind durch ';' getrennt. Das Problem ist aber nicht das Zeilenweise auslesen, sondern das richtige Schreiben der intel hex Datei:
http://de.wikipedia.org/wiki/Intel_HEX
Es gibt also Zeilenweise ein paar Header infos und ein Datenfeld und eine CRC Prüfsumme.
So sieht mal mein code aus:#include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]){ char text[160]; /*Puffer Array fürs Lesen*/ char Zeile[22]; /*Puffer Array fürs Lesen*/ FILE* fr; /*Pointer für Lesedatei*/ FILE* fw; /*Pointer für Schreibdatei*/ int i, j, Adresse=0; fr = fopen(argv[1], "r"); if (fr == NULL) { printf("Datei %s kann nicht geoeffnet werden!\n", fr); return NULL;} fw = fopen(argv[2], "w"); if (fw == NULL) { printf("Datei %s kann nicht geoeffnet werden!\n", fw); return NULL;} fgets(text,sizeof(text),fr); /*Einlesen der 1. Zeile*/ fprintf(fw, ":020000021000EC\n"); fprintf(fw,":"); //Schreiben des Startcodes while(!feof(fr)){ /*Zeile für Zeile einlesen*/ /*feof liefert 1 wenn Dateiende erreicht ist*/ fgets(text,sizeof(text),fr); /*Im Puffer Array ist alles gespeichert. Wir könnten mit einer Schleife die einzelnen Werte durchgehen und in einen neuen Array speichern der die Zeile für die .txt Datei enthält. Wahrscheinlich hilft eine Stringfunktion.*/ /*Intel Hex Header: 2 Länge der Daten in Byte 4 Adresse: Beginnt bei 0000 dann + 8 dann +2 2 Typ xx Daten 2 CRC: braucht schon 2hex Werte in einem Byte*/ /*Header wird hier eingefügt*/ if (i%2 ==1){ Adresse += 8;} else { Adresse += 2;} Zeile[1]=Adresse; /*Das stimmt natürlich nicht, weil Adresse genau 2 Byte lang ist. Zeile[1] ist aber nur 1 Byte lang.*/ j=4; /*Überspringen der Headerinfo*/ for (i=0; text[i]=='\n'; i++){ /*Datenfeld*/ if (text[i]!=';'){ /*entfernt ;*/ Zeile[i] = text[j]; j++; } } /*CRC: alle Bytes (2 hex Ziffern) werden addiert das wird mit FF hex xor verbunden das wird mit 01 hex addiert und das ist das gesuchte CRC = 1 Bytelang*/ fputs(text,fw); /*fraglich ob die Ausgabe von chars reicht oder ob mit fprintf("%2x") formatiert werden muss*/ /*in fw kommt noch ein \n nach jeder Zeile rein!*/ } puts(text); /*letzte Zeile händisch schreiben*/ fclose(fr); getchar(); return 0;}
Was ich nicht verstehe ist, wie ich char informationen (weil das das kleinste Zeichenformat in C ist [1 Byte]) noch halbieren kann. Denn hex Zahlen brauchen nur 4 Bits.
Um die CRC Prüfsumme für jede Zeile zu berechnen, muss ich die Werte schon im C Programm als hex Paare betrachten.
Aber wie mach ich das??
-
Der Compiler/IDE für deinen Mikrokontroller sollte das Hexfile schon erstellen können.
Ansonsten nutzt auch der µC 1 Byte und die Ausgabe kannst du mit printf("%02x",...) machen.
-
DirkB schrieb:
Der Compiler/IDE für deinen Mikrokontroller sollte das Hexfile schon erstellen können.
Ansonsten nutzt auch der µC 1 Byte und die Ausgabe kannst du mit printf("%02x",...) machen.
Aber würden durch diese 0 nicht alle höherwertigen Bits im Byte als 0 gesetzt werden?
-
%02x bedeutet Hex-Ausgabe, mindestens 2 stellig mit führenden Nullen auffüllen
Dann steht da 0f statt f
Und wo ist denn der Unterschied dazwischen?
-
toe schrieb:
DirkB schrieb:
Der Compiler/IDE für deinen Mikrokontroller sollte das Hexfile schon erstellen können.
Ansonsten nutzt auch der µC 1 Byte und die Ausgabe kannst du mit printf("%02x",...) machen.
Aber würden durch diese 0 nicht alle höherwertigen Bits im Byte als 0 gesetzt werden?
Wenn aufgefüllt werden muss, sind die höherwertigen Bits sowieso 0...
-
Es soll aber nicht mit 0 aufgefüllt werden. Das ist ja mein Problem. Ich muss irgendwie zwei Ziffern in ein Byte reinpacken.
-
Meinst du das so? (V ist im Idealfall 8Bit groß, also
char
)/* untere 4 Bits von V auf X setzen */ #define SET_LOW(V,X) do { (V) & 0x0F; (V) |= (X); } while (0) /* untere 4 Bits von V */ #define GET_LOW(V) ( (V) & 0x0F) /* obere 4 Bits von V auf X setzen */ #define SET_HIGH(V, X) do { (V) & 0xF0; (V) |= (X) << 4;} while (0) /* obere 4 Bits von V */ #define GET_HIGH(V) (((V) & 0xF0) >> 4) /* untere 4 Bits von V mit den oberen 4 Bits vertauschen */ #define SWAP(V) do { (V) = (GET_LOW(V) << 4) | GET_HIGH(V); } while (0)
-
Noch als Ergänzung:
/* obere 4 Bits von V auf H und untere 4 Bits auf L setzen */ #define SET(V,H,L) do { (V) = 0; SET_HIGH(V,H); SET_LOW(V,L); } while (0)
-
Ich verstehe nicht, was du meinst mit "2 Hex-Werte werden in einem Byte benötigt". Es geht doch um die Prüfsumme, richtig? Die bildest du einfach, indem du byteweise die Summe des Datensatzes bildest (dabei darf ruhig ein Überlauf stattfinden; deine Prüfsumme ist vom Typ unsigned char, also 1 Byte groß), das Ergebnis mit 0xff ver-xor'st (welch Wortkonstruktion!
) und dann 1 addierst. Schau dir das Beispiel auf wikipedia an. Der erste Datensatz sieht so aus:
:020000021000
(noch ohne Prüfsumme)Du addierst also folgendermaßen:
//das ist natürlich nur exemplarischer Code, das machst du dann in einer schönen Schleife unsigned char crc=0; crc+=0x02; crc+=0x00; crc+=0x00; crc+=0x02; crc+=0x10; crc+=0x00;
Dann wendest du den xor-Operator an:
crc^=0xff;
Und dann addierst du 1:
crc+=0x01;
Dabei kommt dann 0xec raus. Der Datensatz muss also so aussehen (siehst du ja in dem Wikipedia-Artikel):
:020000021000EC
EDIT: Und die Prüfsumme musst du auf 2 Stellen aufgefüllt in die Datei schreiben (hier wurde ja schon gesagt, wie du das machen kannst). Bei einer Prüfsumme 0xd musst du also "0D" schreiben.
-
Meinst du sowas wie zahl1 * 16 + zahl2?
Ich werde den Verdacht nicht los, dass du auf einer falschen Spur bist.
Um einen Zahlenwert Hexadezimal auszugeben gibt es %x bei printf.
In der Variablen selber steht doch nur ein Wert. Der kann dann bei der Ausgabe 65 oder 'A' oder 0x41 oder 0101 (oder 0b0100001) sein.
Wie sieht denn eine Eingabezeile aus und wie soll die Ausgabe dazu aussehen?
Zudem kannst du die CRC einfacher rechnen durch: crc = -(summe_der-Zeile & 0xff);
-
toe schrieb:
Was ich nicht verstehe ist, wie ich char informationen (weil das das kleinste Zeichenformat in C ist [1 Byte]) noch halbieren kann. Denn hex Zahlen brauchen nur 4 Bits.
Um die CRC Prüfsumme für jede Zeile zu berechnen, muss ich die Werte schon im C Programm als hex Paare betrachten.
Aber wie mach ich das??Da bist du irgendwie auf dem falschen Dampfer.
Eine hexadezimale Ziffer braucht nur 4 Bits, ja. Könnte man so sagen. Eine dezimale Ziffer aber auch (die größte, also 9, ist binär 1001, das kommt also hin mit den 4 Bits). Diese Überlegung ist aber völlig irrelevant. Was du addieren musst, sind Bytes. Speichern musst du in einer 1 Byte großen Variable. Du brauchst dir also keine Gedanken zu machen, wie du 2 kleine Werte in ein Byte packen kannst (nebenbei: kann man mit Bitshifts ganz einfach machen). Mach es so, wie ich beschrieben habe. Die alternative Berechnung, wie von DirkB genannt, geht natürlich auch (macht aber für deinen Denkfehler keinen Unterschied).
-
Erstmal, vielen Dank für Eure Unterstützung!!!
Eine Zeile aus der .csv Datei, die ausgelesen wird, lautet:0;0;f;0;0;f;0;0;0;0;0;0;0;0;0;0
Und das Ergebnis im intel Hex Format sollte so ausschauen:
:08000000FF00000000000000F9
Die Berechnung des CRC ist mir, im Allgemeinen, eh schon klar. Dabei ist wichtig, dass die beiden Hexpaare als ganzes Byte betrachtet und aufsummiert werden. (dann xor-en und addieren 00000001b)
Wenn ich die Zeile mit fgets() auslese, habe ich in einem char Array den Text gespeichert. Nach meinem Verständnis heißt das, dass unter Array[0] = '0' = 48 (lt. Ascii Tabelle) = 00110000b = 30h gespeichert.
Seht ihr das auch so? Oder bin ich hier schon falsch?
-
Wie ist denn die Zuordnubg von den cvs Daten zu dem Hexfile?
Denn im Cvs stehen die F's durch Nullen getrennt.Nach meinem Verständnis heißt das, dass unter Array[0] = '0' = 48 (lt. Ascii Tabelle) = 00110000b = 30h gespeichert.
Seht ihr das auch so? Oder bin ich hier schon falsch?
Wenn du die Daten aus dem cvs-Beispiel meinst, liegst du richtig.
Aber das kannst du mit ein paar printf auch überprüfen.