Hexstream in Hexpaare zerlegen
-
Bekommst du wirklich ascii zeichen also "F' und "1" usw. Oder zeigt dir dein testprogramm einfach nur die daten in hex an?
Verstehst du meine frage 100%?
Es ist eher unueblich das hex zeichenfolgen ueber die leitung kommen und die richtige antwort ist davon abhängig wie es genau ist
-
DirkB schrieb:
Lucient schrieb:
DirkB schrieb:
Lies 2 Zeichen vom Comport, Mach daraus ein Byte, verändere es und schreibe es wieder raus.
Und dann von vorne.Nach soeiner Methode hab ich ja gefragt
Wo hast du denn da das Problem?
Wie gesagt, bin auf der C Ebene halt ein Neuling. Mir fällt es noch nicht so leicht eben eine Funktion zu schreiben. Bin auch noch daran, die Funktion von Wutz genau zu verstehen, wie ich die bei mir einsetzten könnte .
Bekommst du wirklich ascii zeichen also "F' und "1" usw. Oder zeigt dir dein testprogramm einfach nur die daten in hex an?
Verstehst du meine frage 100%?
Es ist eher unueblich das hex zeichenfolgen ueber die leitung kommen und die richtige antwort ist davon abhängig wie es genau ist
Wir haben die Comports mitgelogged und es sind wirklich einzelne Hexbefehle in einer Reihe aufgestellt.
Bsp.: Com 1 sendet " 5931, also 0x59 , 0x31 . Die 0x werden nicht mitgelogged oder auch garnicht erst gesendet, kann ich jetzt leider nicht genau sagen " Com 2 antwortet darauf mit " 5159" Das sind alles erstmal nur Steuerbefehle, worauf dann ein ganzes Datenpaket folgt wie z.B. "FB31F0102020202020FB31F0 ... usw."
Mir geht es jetzt auch erstmal nur darum was Com1 Sendet, mit den Steuerantworten befasse ich ich später.
Nun dachte ich mir ich lasse den Comport erstmal in ein großes Eingangs Array schreiben und jage dieses Array Stück für Stück durch eine Switch Anweisung, die einzelne Befehle manipulieren soll, so soll aus "43 also 0x43" dann "0x1B, 0x43,0x00" werden.
Die Switchanweisung bekome ich glaube noch selber hin aber ich hänge gerade bei der Mehtode immer wirklich nur 2 Werte aus dem Array zu nehmen und diese zu einer Hexzahl zu machen.
Vllt. denke ich auch einfach nur zu kompliziert
-
Hexbefehle
gibt es genau so wenig wie If-Schleifen - das sind ein paar Bits in Hexadezimal-Darstellung, manche Terminal-Programme können z.B. den Inhalt auch dezimal oder binär Ausgeben
Bsp.: Com 1 sendet " 5931, also 0x59 , 0x31 . Die 0x werden nicht mitgelogged oder auch garnicht erst gesendet, kann ich jetzt leider nicht genau sagen " Com 2 antwortet darauf mit " 5159" Das sind alles erstmal nur Steuerbefehle, worauf dann ein ganzes Datenpaket folgt wie z.B. "FB31F0102020202020FB31F0 ... usw."
0x ist ein Postfix um (z.B. in der Programmiersprache oder Ausgabe) klar zu machen zu das die folgende Zahl in Hex-Notation ist, Beispiele:
C/C++ => 0x33
Assembler => 33h
QBasic => &H33das wird nie gesendet - höchstens ein Idiot sendet/schickt Werte sinnfrei als Hex-Zeichenfolgen (also direkt lesbar) kodiert
wenn du Hochkommas verwendest denke alle da werden Zeichenketten geschickt - lass das am besten
schreibt lieber
"das ist eine Zeichenkette"
ansonsten
{FB, 31, F0, 10, ...}
oder
{0xFB, 0x31, 0xF0, 0x10, ...}
oder
"\xFB\x31normaler Text\F0\x10..."
char* paket = "\xFB\x31normaler Text\F0\x10...";
damit sagst du klar und deutlich aus was von deinen Bytes "lesbar"
und was "binär" istFRAGEN
1. du willst also ein Protokoll nachbauen - von welchem Gerät denn?
2. normalerweise gibt es längen-Angaben am Anfang wie lange du lesen muss bis ein Paket fertig ist, fixe Paketlängen, oder ein Terminate-Char ist vereinbart das ein Paket-Ende markiert kommt auf die Protokoll-Implementierung an
3. Stell hier mal so ein Log rein - mit Code-Tags dann sehen wir besser was du vor hast
-
Prefix sorry
-
Der Hexstring ist nur eine Darstellungsform, d.h. es werden binär die Daten gesendet, d.h. einzelne Bytes (char).
Du brauchst also nur ein char-Array:char buffer[SIZE];
oder eben dynamisch per malloc:
char *buffer = malloc(SIZE);
wobei SIZE dann eine entsprechende Konstante (oder Variable) ist, welche die Größe angibt.
Und dann einfach per Schleife die Daten ändern:if (buffer[i] == 0x43) { newbuffer[j++] = 0x1B; newbuffer[j++] = 0x43; newbuffer[j++] = 0x00; }
-
DirkB schrieb:
Sorry, aber das verstehe ich ja kaum.
ich hab mich auch verlesen bzw. so interpretiert, dass quasi ein bytearray gesendet wird und dann jeweils 2 byte verarbeitet werden sollen. tut mir wirklich leid für die verwirrung.
Lucient schrieb:
Wir haben die Comports mitgelogged und es sind wirklich einzelne Hexbefehle in einer Reihe aufgestellt.
ja das ist meistens so, bzw. diese hexbefehle sind einfach bytes.
Bsp.: Com 1 sendet " 5931, also 0x59 , 0x31 . Die 0x werden nicht mitgelogged oder auch garnicht erst gesendet, kann ich jetzt leider nicht genau sagen " Com 2 antwortet darauf mit " 5159" Das sind alles erstmal nur Steuerbefehle, worauf dann ein ganzes Datenpaket folgt wie z.B. "FB31F0102020202020FB31F0 ... usw."
ja genau so läuft das. irgendwo im programm wird das dann irgendwie interpretiert, aber in der regel schiickst du über den comport keine "hexstrings", sondern binärdaten.
die 1. frage lautet dann, wie viele bytes breit diese befehle sind. bei einem byte kannst du das dann ganz normal mit char auswerten, bei zwei bytes sind wir dann wieder beim short, bei vier bytes (meistens) beim int usw.
Nun dachte ich mir ich lasse den Comport erstmal in ein großes Eingangs Array schreiben und jage dieses Array Stück für Stück durch eine Switch Anweisung, die einzelne Befehle manipulieren soll, so soll aus "43 also 0x43" dann "0x1B, 0x43,0x00" werden.
also unter unix gibt es die funktionen read() und write(), unter windows die funktionen readfile() und writefile(). bei dir muss das auch irgendwie so gehen.
du übergibst der funktion ein array von z.b. 500 byte und die information, dass 500 byte gelesen werden sollen, z.b. read(com, array, 500).wenn das ganze dann erfolgreich war, hast du dein array und kannst mit *(arrayname + index) oder arrayname[index] auf die einzelnen bytes zugreifen.
Die Switchanweisung bekome ich glaube noch selber hin aber ich hänge gerade bei der Mehtode immer wirklich nur 2 Werte aus dem Array zu nehmen und diese zu einer Hexzahl zu machen.
bist du dir sicher, dass du 2 werte haben willst? das wären z.b. 0xffff oder 0x0000, da sind wir dann wieder beim pointer auf (unsigned) short.
-
Lucient schrieb:
... aber ich hänge gerade bei der Mehtode immer wirklich nur 2 Werte aus dem Array zu nehmen und diese zu einer Hexzahl zu machen.
Vllt. denke ich auch einfach nur zu kompliziert
Du wirst nur ein Byte lesen müssen. Das brauchst du auch nicht wandeln, da es schon der Wert ist
Wade1234 schrieb:
also unter unix gibt es die funktionen read() und write(), unter windows die funktionen readfile() und writefile(). bei dir muss das auch irgendwie so gehen.
du übergibst der funktion ein array von z.b. 500 byte und die information, dass 500 byte gelesen werden sollen, z.b. read(com, array, 500).In Standard-C gibt es
fread
undfwrite
-
Vielen Dank schonmal für die umfangreiche Antworten, die Tipps werd ich zu Herzen nehmen .
Hierbei handelt es sich um ein Schulprojekt, indem man natürlich darauf achten sollte nicht alles aus fremden Quellen zu fischen sondern eher nur Hilfestellungen zu suchen.
In unserem Projekt soll ein Thermo-Drucker durch einen anderen Thermo-Drucker ersetzt werden. Zur Ansteuerung des neuen Druckers haben wir schon eine WinForm in C# entwickelt. Mein Part ist nun in nativem C ein Programm zu schreiben, dass die Befehle des alten Druckers in die des neuen umsetzt ( Der sendende Automat ist in C programmiert, deswegen hier der C Part).
Dieses C programm soll später dann in den Automaten implementiert werden sodass je nach genutztem Drucker der Automat das Programm nutzt oder nicht.
Da in unserer C# Anwendung auch immer in Hex gesendet und Empfangen wird, wollte ich das hier in dieser C Anwendung so beibehalten.
Nun wollte ich erstmal einhergehen und anfangen das Grundgerüst der Anwendung zu erstellen.
Zuerst hab ich 2 Arrays angelegt
char Eingang[]; char Ausgang[];
Sodass man zur Weiterverarbeitung später nurnoch auf die Beiden Zugreifen braucht.
Dann eine Switch-Anweisung in der nach bestimmten Befehlen Seitens des Automaten gesucht wird und diese in die Befehle des neuen Druckers umgesetzt werden ( wie Oben schon beschrieben ).
Nur kam mir dann der Gedanke, dass im {Eingang[]} ne ganze Kette an Werten befinden müsste, die direkt in eins in die Switch Anweisung geladen wird und dementsprechend in die einzelnen Werte zerlegt werden muss.
-
mit Eingang[0] oder *(Eingang + 0) kannst du auf das 1. element zugreifen, mit Eingang[1] oder *(Eingang + 1) auf das 2. element usw.
-
Lucient schrieb:
( Der sendende Automat ist in C programmiert, deswegen hier der C Part).
...
Da in unserer C# Anwendung auch immer in Hex gesendet und Empfangen wird, wollte ich das hier in dieser C Anwendung so beibehalten.[/quote]Das ist sowas von egal, welche Sprache auf jeder Seite benutzt werden.Lucient schrieb:
Da in unserer C# Anwendung auch immer in Hex gesendet und Empfangen wird, wollte ich das hier in dieser C Anwendung so beibehalten.
Ich denke, du hast ein Begriffsproblem mt HEX.
-
Wade1234 schrieb:
mit Eingang[0] oder *(Eingang + 0) kannst du auf das 1. element zugreifen, mit Eingang[1] oder *(Eingang + 1) auf das 2. element usw.
Nur wie kann ich diese Elemente zu einem machen ?
Das ich dann immer Eingang 1 und 2 direkt aneinander Reihe.
Ich denke, du hast ein Begriffsproblem mt HEX.
Schon möglich, ich wusste mich nur nicht besser auszudrücken
-
Ich hoffe ich blamiere mich nun nicht allzusehr, aber ich habe mal versucht mein Poblem zu lösen.
char Eingang[1024]; char Ausgang[1024]; char Fullcut[3] = { 0x1B, 0x43, 0x00 }; char Halfcut[3] = { 0x1B, 0x43, 0x01 }; int i,u,o,count; char a, b; for (i = 0; i < 512; i=i+2) { a = Eingang[i]; b = Eingang[i + 1]; if (a == 4 && b == 3) { for (u = 0; u < 3; u++) { Ausgang[count + u] = Fullcut[u]; count = count + 3; } } if (a == 5 && b == 0) { for (o = 0; o < 3; o++) { Ausgang[count + o] = Halfcut[o]; count = count + 3; } } else { Ausgang[count] = Eingang[count]; count++; } }
Wäre dies nun eine machbare Lösung, oder ist diese Schreibweise komplett daneben gegriffen ?
Immerhin geht es in diesem Projekt sich seine Lösungen zu erarbeiten und daraus zu lernen
-
arbeite ganz schnell an deiner Kommunikation:
1. du ignorierst Fragen oder antwortest nur wenn du die Frage verstehst, das ist
nicht richtig2. die meisten deiner Posts sind ohne Kontext nicht zu verstehen
siehe dein letzter Quelltext Post - wie sollen wir verstehen was du da machst?btw: welche Drucker-Modelle, Betriebssystem, Kompiler Versionen genau?
-
Lucient schrieb:
Wade1234 schrieb:
mit Eingang[0] oder *(Eingang + 0) kannst du auf das 1. element zugreifen, mit Eingang[1] oder *(Eingang + 1) auf das 2. element usw.
Nur wie kann ich diese Elemente zu einem machen ?
Das ich dann immer Eingang 1 und 2 direkt aneinander Reihe.
unsigned short int *input = (unsigned short int *) &Eingang;
damit greifst du dann quasi auf 2 elemente gleichzeitig zu.
-
Gast3 schrieb:
arbeite ganz schnell an deiner Kommunikation:
1. du ignorierst Fragen oder antwortest nur wenn du die Frage verstehst, das ist
nicht richtig2. die meisten deiner Posts sind ohne Kontext nicht zu verstehen
siehe dein letzter Quelltext Post - wie sollen wir verstehen was du da machst?btw: welche Drucker-Modelle, Betriebssystem, Kompiler Versionen genau?
Das werde ich versuchen, nur hier schreiben einige Leute mit deren Antworten ich mich erstmal auseinander setzten muss. Es ist ja so, dass ich hier als Anfänger bzw. eher Laie unter fachkundigen Leuten schreibe, ist nicht alles so einfach.
Ich hatte auch garnicht damit gerechnet, dass das für mich klein erscheindende Problem solche auswirkungen haben könnte und möchte mich für die Verwirrung entschuldigen.
Nur hadere ich damit zuviel von unserem Projekt preiszugeben, da es sich immerhin um eine Schularbeit handelt worum es geht die Probleme selbst zu erörtern und nicht am ende alles aus dem Internet per Copy Paste zu holen.
Nur meine Erörterung scheitert größtenteils daran zu wissen nach was genau man suchen muss.
Wie gesagt vor diesem Thread hab ich google durchstöbert nach " String auswerten " , " ComPort auslesen" und so weiter.
Zu deinen Fragen :
Ich möchte ungern hier den Log posten.
Meine Maschine auf der ich schreibe hat Win7 mit Visual Studio 2017.Ich wollte eigendlich nur wissen, wie man die von einem ComPort gesendeten Daten in ein Char Array speichert um sie dann vereinzelnt weiterverarbeiten zu können und keinen ganzen Quellcode des gesamten Programms .
-
Mal ein Beispiel:
#include <stdio.h> int main (void) { char eingang[] = "Hallo Welt\n"; int i; puts("Als char: "); for(i=0;eingang[i]!= 0;i++) printf("%c", eingang[i]); puts("\ndezimal: "); for(i=0;eingang[i]!= 0;i++) printf("%d ", eingang[i]); puts("\nhex: "); for(i=0;eingang[i]!= 0;i++) printf("%x ", eingang[i]); puts("\nhex ohne Zwischenraum: "); for(i=0;eingang[i]!= 0;i++) printf("%x", eingang[i]); }
Ausgabe:
Als char: Hallo Welt dezimal: 72 97 108 108 111 32 87 101 108 116 10 hex: 48 61 6c 6c 6f 20 57 65 6c 74 a hex ohne Zwischenraum: 48616c6c6f2057656c74a
Wie du siehst, werden dieselben Daten verschieden dargestellt.
Bei Hex werden zwei Zeichen benutz, obwohl nur ein Zeichen codiert wird.
Die Hexausgabe ist eine Darstellungsmethode eures Loggers. Mehr nicht.
Du brauchst da nicht zwei Zeichen zusammen basteln.Und wenn, ist 3 etwas anderes als '3'
-
DirkB schrieb:
Mal ein Beispiel:
#include <stdio.h> int main (void) { char eingang[] = "Hallo Welt\n"; int i; puts("Als char: "); for(i=0;eingang[i]!= 0;i++) printf("%c", eingang[i]); puts("\ndezimal: "); for(i=0;eingang[i]!= 0;i++) printf("%d ", eingang[i]); puts("\nhex: "); for(i=0;eingang[i]!= 0;i++) printf("%x ", eingang[i]); puts("\nhex ohne Zwischenraum: "); for(i=0;eingang[i]!= 0;i++) printf("%x", eingang[i]); }
Ausgabe:
Als char: Hallo Welt dezimal: 72 97 108 108 111 32 87 101 108 116 10 hex: 48 61 6c 6c 6f 20 57 65 6c 74 a hex ohne Zwischenraum: 48616c6c6f2057656c74a
Wie du siehst, werden dieselben Daten verschieden dargestellt.
Bei Hex werden zwei Zeichen benutz, obwohl nur ein Zeichen codiert wird.
Die Hexausgabe ist eine Darstellungsmethode eures Loggers. Mehr nicht.
Du brauchst da nicht zwei Zeichen zusammen basteln.Und wenn, ist 3 etwas anderes als '3'
Okay, vielen dank für das Beispiel.
Nur entfernt mich das immer mehr von einer Idee der Herangehensweise .
Kann ich denn dann überhaupt den COM-Port alles in ein Array schreiben lassen ? Wenn ja, was für eines?
Und wie kann ich daraus einen Hexadezimalen Code machen, da ich mir die ganzen Steuerbefehle nun in einer Liste mit hexadezimalen Werten angelegt habe.
-
Lucient schrieb:
Kann ich denn dann überhaupt den COM-Port alles in ein Array schreiben lassen ? Wenn ja, was für eines?
Ja.
Ein char-ArrayLucient schrieb:
Und wie kann ich daraus einen Hexadezimalen Code machen, da ich mir die ganzen Steuerbefehle nun in einer Liste mit hexadezimalen Werten angelegt habe.
Kannst du doch benutzen. Es sei denn, du hast sie völlig falsch aufgebaut.
Du kannst die Konstanten bei switch auch als Hexwert angeben. Oder als Zeichen. Oktal geht auch.char ausgang[200]; char neuer_Wert; int j; for(i=0,j=0;eingang[i]!= 0;i++,j++) { switch (eingang[i]) { case 0x20 : ausgang[j] = '.'; break; case 'H' : ausgang[j] = W ; break; case 97 : ausgang[j++] = 0x1b; ausgang[j++] = 0x41; ausgang[j] = 0x1; break; default : ausgang[j] = eingang[i]; break; } ausgang[j] = neuer_Wert; } ausgang[j] = '\0'; puts(ausgang);
Oder gleich auf die Ausgabe for(i=0;eingang[i]!= 0;i++) { switch (eingang[i]) { case 0x20 : printf("__SPACE__"); break; case 'H' : putchar('W'); break; case 97 : putchar(0x1B);putchar(0x41);putchar(1); break; default : putchar(eingang[i]); break; } }
-
DirkB schrieb:
Lucient schrieb:
Kann ich denn dann überhaupt den COM-Port alles in ein Array schreiben lassen ? Wenn ja, was für eines?
Ja.
Ein char-ArrayLucient schrieb:
Und wie kann ich daraus einen Hexadezimalen Code machen, da ich mir die ganzen Steuerbefehle nun in einer Liste mit hexadezimalen Werten angelegt habe.
Kannst du doch benutzen. Es sei denn, du hast sie völlig falsch aufgebaut.
Du kannst die Konstanten bei switch auch als Hexwert angeben. Oder als Zeichen. Oktal geht auch.char ausgang[200]; char neuer_Wert; int j; for(i=0,j=0;eingang[i]!= 0;i++,j++) { switch (eingang[i]) { case 0x20 : ausgang[j] = '.'; break; case 'H' : ausgang[j] = W ; break; case 97 : ausgang[j++] = 0x1b; ausgang[j++] = 0x41; ausgang[j] = 0x1; break; default : ausgang[j] = eingang[i]; break; } ausgang[j] = neuer_Wert; } ausgang[j] = '\0'; puts(ausgang);
Oder gleich auf die Ausgabe for(i=0;eingang[i]!= 0;i++) { switch (eingang[i]) { case 0x20 : printf("__SPACE__"); break; case 'H' : putchar('W'); break; case 97 : putchar(0x1B);putchar(0x41);putchar(1); break; default : putchar(eingang[i]); break; } }
Das sieht genau nach dem aus, was ich gesucht hab .
Vielen, vielen Dank für die Hilfe und die Geduld.