Hallo zusammen,
ich möchte ein Intelhex-File Zeile für Zeile einlesen. Das klappt auch
soweit, aber er liest jedes Zeichen als char. Wie kann ich denn die
Datenbytes gleich als Hexzahlen einlesen?
Ich habe versucht jedes Char-Paar über eine switch-Anweisung wieder
zurück zu wandeln. Geht auch. Aber das muss doch auch einfacher gehen -
oder?
Gruß
Markus
Das habe ich bisher verbrochen:
FILE *fil;
char buffer[16];
fil = fopen("test.hex", "r");
if (fil == NULL) {
printf("\nDatei test.txt kann nicht geöffent werden\n");
exit(-1);
}
while(!feof(fil)) {
fgets (zeichen, LINE_LENGTH, fil);
if (!feof(fil)) printf("%.*s",LINE_LENGTH, zeichen);
}
fclose (fil);
Ziel soll sein, dass ich aus jeder Zeile die 16 Datenbytes herausziehe
und in einen Array (buffer) schreibe.
Markus schrieb:> Das habe ich bisher verbrochen:>> FILE *fil;> char buffer[16];
nicht char.
char benutzt du ausscchliesslich für Buffer die reinen Text enthalten.
Du willst letztendlich Bytes formen. Also nimmst du unsigned char.
> fil = fopen("test.hex", "r");>> if (fil == NULL) {> printf("\nDatei test.txt kann nicht geöffent werden\n");> exit(-1);> }>> while(!feof(fil)) {
Falsch.
feof ist ein Test mit dem man hinterher feststellt, warum eine
Leseoperation schief gelaufen ist. Die zentrale Einleseschleife wird
niemals von feof abhängig gemacht. In C liefert jede Lesefunktion einen
Returnwert, aus dem sich ablesen lässt, ob die Operation gut gegangen
ist oder nicht.
Achtung: Eine Leseoperation kann aus vielen Gründen schief gehen, nicht
nur EOF. NIcht zuletzt deshalb ist es auch unlogisch, die while Schleife
auf feof basieren zu lassen.
>> fgets (zeichen, LINE_LENGTH, fil);
ist schon mal ein guter Anfang.
> Ziel soll sein, dass ich aus jeder Zeile die 16 Datenbytes herausziehe> und in einen Array (buffer) schreibe.
Bleib bei der Strategie erst mal eine Zeile komplett einzulesen. Hast du
sie erst mal als String im Speicher, kannst du sie in aller Ruhe
zerlegen und analysieren. Vor allen Dingen in Fehlerfällen ist das
einfacher, als wenn man gleich beim Einlesen die Zeile zerlegen lassen
will
1
FILE*fil;
2
unsignedcharbuffer[16];
3
fil=fopen("test.hex","r");
4
5
if(fil==NULL){
6
printf("\nDatei test.txt kann nicht geöffent werden\n");
7
exit(-1);
8
}
9
10
while(fgets(zeichen,LINE_LENGTH,fil)){
11
printf("%.*s",LINE_LENGTH,zeichen);
12
}
13
14
if(!feof(fil))
15
printf("Fehler beim Einlesen der Datei!\n");
16
17
fclose(fil);
So sieht die klassische Leseschleife in C aus.
Als nächstes siehst du dir den Aufbau einer Zeile an.
Und du liest über sscanf (bzw.) scanf in deinem C-Buch nach, ob und wie
du mit dem Formatstring sscanf dazu bringen kannst, die ganze Arbeit für
dich zu machen.
> Ich habe versucht jedes Char-Paar über eine switch-Anweisung wieder> zurück zu wandeln.
Das ist ein bischen aufwändig. Das geht auch deutlich einfacher.
Wenn du mit sscanf nicht klar kommst, dann schreib dir eine Funktion,
die 2 Zeichen übernimmt, diese als ASCII Repräsentierung von Hex-Digits
interpretiert und daraus das Byte zusammensetzt.
Es gibt einen Zusammenhang zwischen dem ASCII Code von Ziffern und
Zeichen und dem was man binär daraus generieren will.
Das ASCII Zeichen für '0' hat den ASSCII Code 0x30
Das Zeichen '1' hat den ASCII Code 0x31, etc. für alle Ziffern.
Zieht man daher von einem Zeichen den ASCII Code von '0' ab, dann hat
man unmittelbar die Zahl die diesem Zeichen entspricht. Bei den
Buchstaben 'A' bis 'F' ist es ähnlich.
Dein erstes Ziel: SChreib eine Funktion, der du 1 Zeichen vorgibst,
welches entweder '0'..'9' oder 'A'..'F' sein kann, und welches dir
daraus eine Zahl 0..15 errechnet, je nach Zeichen.
Auch wenn es KHB sauer aufstößt, daß ich nicht erst eine Zeile
einlese (was sicher auch nicht falsch wäre), hier ein Beispiel
mit allen nötigen scanf-Formaten:
Klaus Wachtler schrieb:> Auch wenn es KHB sauer aufstößt, daß ich nicht erst eine Zeile> einlese
LOL
Stösst mir überhaupt nicht sauer auf.
Dein Programm wird sich nur hier
wohl war.
Du willst bestimmt drauf raus, daß man erst die ganze Zeile liest?
Wobei ich gar nicht weiß, ob es Sinn macht, bei anderen
Typen einfach stillschweigend weiter zu machen.
Wenn die vorkommen (?), müssen sie auch vrmtl. behandelt werden
Alles was bei mir momentan rauskommt ist folgendes:
Recordtyp unbekannt, ignoriert
Zeilenstart nicht lesbar in Zeile 2
Da werde ich wohl noch etwas anpassen müssen. ;-)
Der Start von meinem Hexfile sieht übrigens so aus:
:020000040000FA
:10000000EA00FF32EA0067FEEA006ECEEA0067E02F
:10001000EA0067C3EAFFFFFEEA006293EA006C4071
:1000200047D4AB7B000213380400002000106B059E
:10003000000000030003FFE0BDFA1FF77F352265D3
...
Schau doch mal den Link am Anfang von meinem Quelltext an!
Da ist das Format beschrieben.
Ich habe in meinem Beispiel nur die Typen 0 (Daten) und 1 (EOF).
Deshalb habe ich mein Beispielprogramm nur darauf abgestellt.
Bei dir ist die erste Zeile etwas ganz anderes: Typ 2
(Extended Segment Address Record/Real Mode-Adressierung).
Das heißt, du musst diesen Fall im if...else if... auch abfangen
und mehr oder weniger sinnvoll darauf reagieren.
Das kannst du bestimmt selber...
Klaus Wachtler schrieb:> wohl war.> Du willst bestimmt drauf raus, daß man erst die ganze Zeile liest?
Ich denke für jemanden (den TO) der das erste mal ein File einliest, ist
das gut genug. Das passt schon.
Für mich persönlich würde ich eine Kombi machen.
Ist doch simpel die Zeile zunächst mittels fgets einzulesen und dann im
Prinzip deinen Code zu nehmen, die fprintf durch sscanf ersetzen, noch
einen char-Pointer als 'File-Pointer' und läuft schon.
Aber das ist für den TO sicherlich jetzt noch nicht notwendig.
File-einlesen absolut abzusichern, so dass nichts passieren kann, ist
für uns Profis eine Notwendigkeit (egal was ein Kunde dieser Funktion
vorsetzt, sie darf Fehlermeldungen werfen so viele sie will, nur
abstürzen darf sie auf keinen Fall) für den Heimgebrauch kann man ruhig
die Ansprüche runterschrauben.
>> Wobei ich gar nicht weiß, ob es Sinn macht, bei anderen> Typen einfach stillschweigend weiter zu machen.
Kann ich nicht sagen.
Gibts im Intel-Hex Format überhaupt noch andere Codes?
Fass den Einwand, den ich da vorgebracht habe bloss nicht als Kritik um
der Kritik willen auf. So war das ganz sicher nicht gedacht.
Klaus Wachtler schrieb:> Bei dir ist die erste Zeile etwas ganz anderes: Typ 2> (Extended Segment Address Record/Real Mode-Adressierung).
Korrektur: du hast hier Typ 4 (Extended Linear Address
Record/32Bit-Adressierung).
Karl heinz Buchegger schrieb:> Kann ich nicht sagen.> Gibts im Intel-Hex Format überhaupt noch andere Codes?
Angeblich 6 Stück.
http://de.wikipedia.org/wiki/Intel_HEX> Fass den Einwand, den ich da vorgebracht habe bloss nicht als Kritik um> der Kritik willen auf. So war das ganz sicher nicht gedacht.
:-)
So sensibel bin ich nicht. Als Maschinenbauer eher gefühl- und
regungslos.
Karl heinz Buchegger schrieb:> ein Programm wird sich nur hier else if( recordtype!=0 )> {> fprintf( stderr, "Recordtyp unbekannt, ignoriert\n" );> continue;> }> schwer tun, sich wieder auf den nächsten Datensatz zu synchronisieren.> (Ich weiß, man kann das beheben)
Genau dieses Problem habe ich gerade noch... ;-)
den Typ 4 fange ich bereits ab... aber hier fehlt es mir noch.
Markus schrieb:>> schwer tun, sich wieder auf den nächsten Datensatz zu synchronisieren.>> (Ich weiß, man kann das beheben)>> Genau dieses Problem habe ich gerade noch... ;-)>> den Typ 4 fange ich bereits ab... aber hier fehlt es mir noch.
Und genau deswegen hab ich in letzter Zeit immer mehr Bauchweh, wenn
fertige Lösungen präsentiert werden.
Hand aufs Herz: Du hast noch nicht nachgelesen wie die Einzelteile, die
du noch nicht verstehst eigentlich funktionieren.
nein habe ich nicht... ich bin gerade dabei den Code Stück für Stück
auseinanderzunehmen. Und "fertige" Lösungen nehme ich trotzdem
auseinander - so viel Ehrgeiz habe ich, dass ich mir das anschaue und
verstehen möchte. Man lernt dabei unheimlich viel!
holger schrieb:>>den Typ 4 fange ich bereits ab... aber hier fehlt es mir noch.>> Schmeiß die Zeile weg, der Offset ist Null;)
Kann er nicht.
Er muss sie schon lesen, sonst geht die Synchronisierung verloren und er
findet den nächsten Zeilenanfang nicht.
Liest er sie aber, dann kann er auch gleich die Zahlenwerte rausholen.
Ob er damit was macht, ist eine andere Geschicht. Aber der einfachste
Weg ist es in diesem Fall tatsächlich, die Zeile zu ende zu lesen. Ist
ja nur noch eine 2 Byte Zahl und die Checksumme. Wenn er mit
Formatstrings umgehen kann (und sich bei den anderen Daten ansieht wie
Klaus ihm das vorgemacht hat), ist das nicht weiter schwer.
Klaus Wachtler schrieb:> Mit scanf kann man auch überlesen, ohne etwas zu nutzen (mit einem *).> Da kann man jetzt streiten, ob es "wegwerfen" ist oder "lesen".
Lass ihn mal die Standardsachen im Formatstring erlernen, ehe du mit den
Spezialitäten kommst :-)
Die 2 zusätzlichen Variablen, die er dann noch braucht, bringen ihn auch
nicht um :-) und der Rest ist Kontrolle, ob er den Aufbau eines
Formatstrings verstanden hat.
hab den Code recht schnell kapiert und das Problem mit folgender Zeile
gelöst:
fscanf( f, "%4x%2x", &storage_address, &checksum);
wie kann man mit "*" die 6 Zeichen überlesen? neugier
Hallo Ihr Lieben,
vor vielen, vielen Jahren habe ich mich ganz passabel in GFA-Basic
ausgekannt und damit so einiges programmiert. Nun mache ich meine ersten
Schritte in C++, trotz einiger Ähnlichkeiten sehe ich mich zwangsläufig
also darin noch als Anfänger.
Nun möchte ich für ein opensource Projekt www.opcar.de ein ganz
einfaches Tool entwickeln, mehrere in einer eep Datei gespeichertes CVs
ändern zu können, diese geänderten CVs anschließend wieder in eine eep
Datei zurück zuschreiben um diese dann mit dem AVRootloader in die
Fahrzeuge zu schreiben. Auf jegliche Grafik soll bewusst verzichtet
werden, ein reines Zweckwerkzeug.
Bei meinen Recherchen bin ich auf diesen Beitrag hier gestoßen und habe
den veröffentlichten Code an meine Bedürfnisse angepasst. Damit lassen
sich die CVs einlesen und bearbeiten. Für diejenigen, die damit
"spielen" wollen, ist eine erforderliche eep angehängt.
Nun möchte das Rückschreiben in die eep Datei schreiben, stoße dabei
aber an meine Grenzen. Wenn ich es richtig verstanden habe, muss ich
1) immer 15 CVs in einem String zusammenfassen
2) Zeilennummer ergänzen
3) Prüfsumme neu berechnen
4) Zeilenweise in Datei schreiben
Aber wie ? Könnt Ihr bitte helfen. Vielen Dank.
1
#include<iostream>
2
#include<stdlib.h>
3
#include<stddef.h>
4
#include<stdio.h>
5
#include<string.h>
6
#include<stdint.h>
7
#include<iomanip>
8
9
usingnamespacestd;
10
11
intmain(void)
12
{
13
intcv=0;
14
intmax_cv;
15
intcv_wert[255];
16
intcv_auswahl;
17
intcv_wert_neu;// Variablen für Datenübernahme einrichten
18
charpruefung;
19
20
//Den folgenden Code habe ich dem Beitrag von Klaus Wachtler auf der Seite http://www.mikrocontroller.net/topic/189911
21
//entnommen und in Teilen angepasst
22
23
FILE*f=fopen("open_car.eep","r");
24
unsignedlongiZeile=0;
25
uint8_tdata[128];// Platz für Daten aus einer Zeile