Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Datentyp "ASCII -> Hex" >COM Schwierigkeit


Shyran - Mo 29.10.12 16:35
Titel: Datentyp "ASCII -> Hex" >COM Schwierigkeit
Guten Tag, liebe Gemeinde,

anbei folgendes Problem:

In einer Text-Datei befindet sich ein String vom Format "8F 10 13 13 00 08 10 4D 30 30 33 2D 32 2D 46 5F 4D 30 30 30 32 30 32 02 07"

Also Binärdaten im HEX-Format. Ich lese die Zeile ein und möchte nun EXAKT diese Zeichen über meine ser. Schnittstelle ausgeben.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
..blabla
function hextochar(ein:string):string;
var
   i: integer;
begin
   result:='';
   for i:=0 to trunc(length(ein)/3do
      try
          result:=result+chr(StrToInt('$'+copy(ein,(3*i)+1,2)));
      except
          result:='Fehler';
      end;
end;

....BLABLA.....


Readln(f, s);
COMSend(HexToChar(s));


Als Ergebnis auf der Gegenseite empfange ich hier interessanterweise folgenden String (HEX):

"3F 10 13 13 00 08 10 4D 30 30 33 2D 32 2D 46 5F 4D 30 30 30 32 30 32 02 07"

Das erste Byte ist also inkorrekt. Ähnlich verhält es sich mit: 80 -> 3F; 8F aber bleibt 8F.

Wald Bäume ... Hilfe?

Hab auch folgendes simples mal gesendet:


Delphi-Quelltext
1:
  Comsend(chr(136));                    


Ich hätte also das ASCII Zeichen "^" erwartet, empfangsseitig, aber ebenso dort kommt ein "3F".

Vielen Dank für's Reindenken im Vorraus!

Liebe Grüße

-Shyran


JDKDelphi - Mo 29.10.12 17:24

Hallo,

kann es sein, daß Deine COM-Schnittstelle auf 7Bit konfiguriert ist?


Gruß


Oliver Maas - Mo 29.10.12 17:48

Hm. Das Ding kommt aus einer Textdatei. Kann es so etwas wie BOM sein (Byte Order Mark)?
http://de.wikipedia.org/wiki/Byte_Order_Mark


mandras - Mo 29.10.12 20:19

Ich tippe auf folgendes: Irgendwer in der Kette ersetzt Zeichen die er nicht kennt durch $3f (also das Fragezeichen). Evtl wirklich ein Problem mit Schnittstelle auf 7 Bit?

Was ich nicht verstehe: Erst schriebst Du, daß $8F beim Empfänger als $3F ankommt, weiter unten aber: $80 wird auf $3F abgebildet, $8F bleibt $8F. ???


Shyran - Di 30.10.12 07:57

Guten Morgen!

Zunächst schönen Dank für die Ideen - Einstellung auf 7Bit ist es definitiv nicht, es sind 8 Datenbits konfiguriert (9K6,8N1).

@Mandras:
Wenn ich das Zeichen $8F sende, kommt beim Empfänger $3F an, ganz exakt. Ebenso wird $80 als $3F übertragen. Aber als Gegenbeispiel wollte ich auch zeigen, daß das Zeichen $8F auch tatsächlich und nachweislich als $8F auf der Gegenseite erscheint. Das wollte ich damit darstellen.

@Oliver Maas:
Die Textdatei wird zuvor an anderer Stelle auch "von mir" erzeugt, insofern kann ich das ausschließen - ich verwende keine UTF-8 Erkennung oder so. Im wesentlichen beginnen die Zeichenketten alle mit $AA, aber einige Zeichen der möglichen 256 scheinen eben nicht korrekt übertragen zu werden.


Allgemein kann ich ein Hardwarepegelproblem auch ausschließen, hab prima RS232 Pegel bei -12V/+12V.

Als RS232 Komponente nutze ich übrigens AsyncPro v5.00 [http://sourceforge.net/projects/tpapro/], vlt hilft auch das noch als Hinweis, ggf. kennt jemand von euch Helferlis da noch etwas wie "ja klar, da musst Du noch das-und-das parametrieren!".

Liebe Grüße

-Shyran


chrisw - Di 30.10.12 16:16

Die Function/Procedure COMSend() kenne ich gar nicht von AsyncPro oder ist das ein Wrapper von dir ?
Ich kenne nur die PutString, PutChar ..... Methoden oder das OutPut property um Daten zu senden.

Christian


Shyran - Di 30.10.12 16:46

Lieber Christian,

präzise richtig. Im Grunde bastel ich noch in das ein oder andere Terminalfenster einiges hinein, im wesentlichen aber benutze ich folgenden Aufruf nur:


Delphi-Quelltext
1:
ApdComPort1.OutPut := TxString;                    


Also beinahe schon banal ...

Liebe Grüße


Martok - Di 30.10.12 20:31

Das mit der $80-$8E kenn ich, Minecraft-Server haben den gleichen Bug. Da funktioniert das Query-Protokoll [https://github.com/martok/MCStatus-php] auch nicht, wenn man diese Bytes in der Session-ID verwendet :D

Irgendwo verwendest du etwas, was eine CodePage-Konvertierung macht. Wie ich neulich hier gelernt hab, macht Unicode-Delphi das auch, wenn man nur von AnsiString nach AnsiString will. Was hast du denn überhaupt für ein Delphi?


GuaAck - Mi 31.10.12 00:25

Hallo Shyran,

bei Verbindungen über den COM-Port (RS232 usw.) werden oft einige Steuerzeichen ausgeblendet. Im XON/XOFF-Protokoll dienen z. B. die Zeichen $11 und $13 dazu, dass der Empfänger den Sender bitten kann, mal etwas Pause zu machen. Bei den meisten Programmen gibt es eine Schalter 'Transparent-Mode' o.ä., der die Sonderbehandlung aller Steuerzeichen abschaltet. Dein Problem könnte auch am Empfangsprogramm liegen.

Das ComSend kenne ich leider auch nicht.

Gruß
GuaAck


Shyran - Do 01.11.12 08:56

Ich denke, Sebastian liegt da schon auf der richtigen Spur... irgendwie vermute ich den Bug durchaus auch im Unicode-Bereich, allerdings bin ich nicht wirklich in der Lage, das Problem so "zu lösen", auf für mich logische Art & Weise. Ich hab' denselben Code mal in ein steinaltes Delphi 3 reingetüddelt und siehe da, dort klappt das einwandfrei! D.h., WENN ich eine Codepage-Konvertierung mache, dann "unabsichtlich" oder unbewusst, da ich quasi nur als dummer User, die Komponente von AsyncPro nutze ...

Ggf. gibt's noch eine lustige Einstellung im Delphi XE selbst?

Das Empfangsprogramm kann ich ausschließen, da es, wenn ich ein herkömmliches Terminalprogramm nutze, tadellos empfängt.

@GuaAck:
Die Frage zum ComSend hatte ich in meinem zweiten Beitrag zu diesem Thread beantwortet. Einen TransparentMode oder etwas, das so ähnlich klingt kann ich im AsyncPro allerdings nicht finden. Flusskontrolle ist ebenso deaktiviert bei mir, ich fürchte daher, das ist es nicht.

Liebe Grüße,

-Frank

PS: Ich hab in den Profileinstellungen anch der Frage der Entwicklungsumgebung eben diese mal "links" hinzugefügt, danke für den Hinweis!

PPS: Durch den Hinweis der Codepage durch Sebastian habe ich Google bemüht und bin auf diesen Beitrag dazu [http://delphipraxis.net/163806-asyncpro-delphi-apdcom1-putstring-chr-128-a.html] gestoßen, der recht vielversprechend aussieht!


Shyran - Do 01.11.12 09:40

Okay, Problem gelöst!

Letztlich war es - wie so oft - ein klassisches Unicode-Problem...

Lösungsweg:

Zunächst also (Beispiel) "8F 8E 8D 8C 8B 8A 80 88" aus der Datei einlesen.

Vorher (FALSCH!):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function HexToChar(ein:string):string;
var
   i: integer;

begin
   result:='';
   for i:=0 to trunc(length(ein)/3)-1 do
      begin
          result:=result+ansichar(StrToInt('$'+copy(ein,(3*i)+1,2)));
      end;
end;


Nachher (Richtig):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function HexToChar(ein:string):string;
var
   i: integer;

begin
   result:='';
   for i:=0 to trunc(length(ein)/3)-1 do
      begin
          result:=result+ansichar(StrToInt('$'+copy(ein,(3*i)+1,2)));
      end;
end;


Im Anschluss konnte ich dann durch draufloslassen der obigen Funktion auf meinen eingelesenen String ganz simpel auch AsyncPro wie gehabt nutzen:


Delphi-Quelltext
1:
2:
  HextoChar(s);
  ApdComPort1.OutPut := s;


Auf meiner Gegenstelle kam dann einwandfrei "8F 8E 8D 8C 8B 8A 80 88" an - Hurra!

Vielen Dank für die Ideen & Schubse an alle! Vielleicht profitiert der ein oder andere auch noch von meinem Lernprozess :)

-Frank