| Autor |
Beitrag |
Smartie
      
Beiträge: 205
|
Verfasst: Di 19.04.05 07:20
Servus!
Ich versuche gerade, ASCII-Dateien über Delphi zwischen meinem PC und dem LABOR-Laptop über die serielle Schnittstelle hin und her zu schicken.
Zum Test hatte ich auf dem Schlepptop erstmal nur über WIndows-Hyperterminal gearbeitet.
Mein Programm hatte folgenden Sourcecode:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| interface
uses WinTypes, WinProcs, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, AdPort, OoMisc;
type TForm1 = class(TForm) ApdComPort1: TApdComPort; Test: TButton; Label1: TLabel; Label2: TLabel;
procedure TestClick(Sender: TObject); procedure ApdComPort1TriggerAvail(CP: TObject; Count: Word); private public end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.TestClick(Sender: TObject); begin ApdComPort1.OutPut := ' Hier kommt ein String; end;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word); {Event OnTriggerAvail - Example how OnTriggerAvail works} var I : Word; C : Char; S : String; begin S := ''; for I := 1 to Count do begin C := ApdComPort1.GetChar; case C of #0..#31 : {Don't display} ; else S := S + C; end; end; Label1.Caption := S; ShowMessage('Got an OnTriggerAvail event for: ' + S + 'count= '+ Count); end;
end. |
Oki, so weit alles klar. Nur: Wenn ich eine ASCII-Datei vom Schlepptop mit Hyperterminal an PC schick, so schneidet er immer das erste Zeichen ab, und versendet es separat. Ich bekomme also immer zwei Datein. Wenn der Inhalt der Datei z.B. lautet "Dies hier ist ein Test"
So erhalte ich folgende zwei Strings raus:
s1 := 'D'
s2 := 'ies hier ist ein Test'
"Ok, ok, Windows", dacht ich mir "Ich muß zur späteren Komunikation eh ohne den Hyperterminal arbeiten". Also, einfach ein zweites sehr ähnliches Programsche geschrieben, für den Laptop, um einfach Zeichenketten zu senden.
Dieses sah wie folgt aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| interface
uses WinTypes, WinProcs, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, AdPort, OoMisc;
type TForm1 = class(TForm) ApdComPort1: TApdComPort; Test: TButton; Label1: TLabel; Edit1: TEdit; procedure TestClick(Sender: TObject);
private public end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.TestClick(Sender: TObject); var text : String; begin text := Edit1.Text; ApdComPort1.OutPut := text; label1.Caption := '"'+ text + '"' + ' wurde erfolgreich versendet.' end;
end. |
Gut, die gute Nachricht, er versendet es nicht mehr in zwei Teilen
Die schlechte Nachricht, er versendet immer nnur (maximal) 8 Zeichen
Wenn ich einfach im Textfeld "Hallo" eingabe, so bekomme ich auch Hallo raus.
Wenn ich aber "Hallo du schöne Welt" eingebe, so bekomme ich "Welt"
Wenn ich nur "Hallo Welt" eingebe, so bekomme ich "lt"
Bei "Hi Welt" kommt auch "Hi Welt" raus, sind ja auch nur 7 zeichen.
Also, wenn mein String <= 8 Zeichen ist, sendet er diesen komplett. Wenn dieser > 8 Zeichen ist, schneidet er die ersten 8 ab, und schreibt nur den Rest.
Kann mir hier einer bitte weiterhelfen?
Ich freu mich auf Antwort,
Fuß zum Gruß
Smartie
Moderiert von Gausi: Code- durch Delphi-Tags ersetzt.
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 08:33
Das Problem entsteht, da der UART Chip des Computers bei einem bestimmten Füllstand ein Interrupt auslöst und den PC damit auffordert den Buffer zu leeren (auszulesen).
Die Delphi Komponente liest nun über die Windows API's den Buffer der Schnittstelle aus und zeigt ihn an (das sind die 8 Zeichen, die vorherigen wurden dann überschrieben.
Es sind als Lösung zwei Vorgehensweisen üblich:
1. Einen Start- (am Anfang der Übermittlung) und Stopstring (am Ende der Übermittlung) senden und alles was dazwischen empfangen wird gehört zur Datei. (Bsp.: ##Start##Hallo Welt##Stop##)
Start- und Stopstring wieder entfernen.
2. Alles was innerhalb eines bestimmten Zeitabschnittes reinkommt gehört noch zur Datei (Bsp.: Wenn Pause zwischen den Zeichen < 2 Sekunden, dann anhängen, sonst neue Datei)
Dies lässt sich relativ einfach mit der Delphi Komponente TComPort realisieren, da sie bereits ein Object TDataPacket enthält, in dem man nur noch Start- und Stopstring angeben muss, um einen String zu erhalten.
Hoffe ich konnte helfen
Chris
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 08:43
Tausend Dank!
Ichdenke, ich versuche is mit Variante 2.
kannst du mir sagen wie genau ich das realisiere. (Bin noch Delphi-Newbie, und kenn mich auch mit der Syntax noch nicht ganz so gut aus, sorry).
Lieben Gruß
Smartie
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 09:10
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| RS232Active : Boolean;
RS232Active := False; procedure TForm1.Timer1Timer(Sender: TObject); begin RS232Active := False; end;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word); var I : Word; C : Char; S : String; begin RS232Active := True; Timer1.enabled := False; Timer1.enabled := True; S := ''; for I := 1 to Count do begin C := ApdComPort1.GetChar; case C of #0..#31 : ; else S := S + C; end; end; Label1.Caption := S; ShowMessage('Got an OnTriggerAvail event for: ' + S + 'count= '+ Count); end; |
So in etwa (nicht getestet, da ich eine andere RS232 Komponente nutze)
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 10:06
Danke schn.
Hm.. .sehr seltsam, aber ich komme glaub ich dank dir dem Problem näher:
Er zerstückelt immer noch, aber ands:
wenn ich das "showMessage" weglasse (nur über das label aberbeitend), so bleibt alles beim alten, er zeigt mir nur den letzten 8-Byte-Block
Wenn ich es lasse, so zerstückelt er es einfach in den dersten 8-Byte-Block plus den Rest.
Der code sieht ziemlich so aus, wie du ihn vorgeschlagen hast, muß ihn glaubi ch also nicht neu hier rein setzten.
Mir fällt nur grad ein, ich könnte versuchen, das ganze über ne weitere for-schleife laufen zu lassen "Sertze i = 0; Bis 's' 8 Zeichen hat, durchlaufe diese schleife, dann setzte s in stringar[i]. Wenn i = 4 breche schliefe ab, und setzte
string SX := Stringar[0] + Stringar[1] + Stringar[2] + Stringar[3]"
was meisnt du, wär das gut? Oder gibts da was eleganteres?
Lieben Gruß
Smartie
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 11:22
sry, aus Versehen "aktualisieren" gedrückt !
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 11:34
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| RS232Active : Boolean; tempBuffer : String;
RS232Active := False; procedure TForm1.Timer1Timer(Sender: TObject); begin RS232Active := False; showmessage(tempBuffer); tempBuffer := ''; end;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word); var I : Word; C : Char; S : String; begin RS232Active := True; Timer1.enabled := False; Timer1.enabled := True; S := ''; for I := 1 to Count do begin C := ApdComPort1.GetChar; case C of #0..#31 : ; else S := S + C; end; end; Label1.Caption := S; tempBuffer := tempBuffer + S; end; |
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 12:23
Ok, wir sind fast da *g*
also, ich hab zwar no n Bischen rumgespielt, mit String und buffer, aber hat nicht sooo viel genutzt. Also, bei dershowmessage zeigt er interessanter weise den tatsächlich übersendeten string komplett. nur im label zeigt ers nicht.
das mit meiner schleife hat übrigens nicht ganz so funktioniert wie es sollte, irgendwie hat er ein Problem damit, eine prozedur in der schleife zu haben.
Lieben Gruß
Smartie
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 13:06
Hallo,
ich hab da noch ein wenig mit meienr Schleifenlösung gespielt, und hab da folgendes gemacht:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91:
| interface
uses WinTypes, WinProcs, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, AdPort, OoMisc, ExtCtrls;
type TForm1 = class(TForm) ApdComPort1: TApdComPort; Test: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Timer1: TTimer; procedure TestClick(Sender: TObject); procedure ApdComPort1TriggerAvail(CP: TObject; Count: Word); procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private public end;
var Form1: TForm1; var RS232Activate : Boolean; j: integer = 1; sar : Array[0..3] of String; XS: String;
implementation
{$R *.DFM}
procedure TForm1.TestClick(Sender: TObject); begin ApdComPort1.OutPut := ' Schick mir was'; end;
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word); var I : Word; C : Char; S : String; begin
RS232Activate := True; Timer1.enabled := False; Timer1.enabled := True; S := ''; repeat repeat C := ApdComPort1.GetChar; case C of #0..#31 : ; else S := S + C; end; until length(s) = 8; sar[j] := s; j := j +1; ShowMessage('Got an OnTriggerAvail event for: ' + S); until j = 4; xs := sar[0] + sar[1] + sar[2] + sar[3];
Form1.Label1.Caption := xS; ShowMessage('Got an OnTriggerAvail event for: ' + xS); end;
procedure TForm1.FormCreate(Sender: TObject); begin RS232Activate := False; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin RS232Activate := False; end;
end. |
Aber da brignt er richtig "schöne" Fehlermeldungen (Buffer ist empty)
Kann ich da was machen, oder ist diese Idde zur Problemlösung ohnehin Müll, und ich habs einfach nicht bemerkt?
Lieben Gruß und Danke
Smartie
Moderiert von Christian S.: Code- durch Delphi-Tags ersetzt.
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 13:16
OK, den label hab ich bisher nicht betrachtet !
hier der code um das richtige in den Label zu bekommen:
ersetze "showmessage(tempBuffer)" durch "Label1.Caption := tempBuffer"
Jetzt sollte im Label das Richtige stehen !
Chris
(Vielen Dank für Deine PN  )
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 13:22
Hi,
hatte ich schon probiert, da kmmt NUr der letzte Block bei raus.
Fand ich auch seltsam, aber irgednwie scheint die showmessage irgendwie auf das programm zu wirken, frag mich nicht wie.
lieben Gruß
smartie
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 13:29
Du musst natürlich die Zeile "Label1.Caption := S; " Löschen bzw. als
Remark (//) markieren, ansonsten wird es ja immer wieder überschrieben !
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 19.04.05 13:31
Grundsätzlich würde ich aber ein MemoFeld(TMemo) anstatt des Labels benutzen und dann immer nur die empfangenen Zeichen anhängen (Memo1.Text := Memo1.text +S).
Dann müssen aber die Steuerzeichen für Carriage return (#13) und Linefeed(#10) auch durchgelassen werden, ansonsten steht alles in einer Zeile
Chris
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
Smartie 
      
Beiträge: 205
|
Verfasst: Di 19.04.05 13:37
Ok, super, danke!
Ich mußte nur den befehl tempBuffer := ''; auch rauswerfen, denn sosnt gäbs den string immer nur für die voreingestellten 2 sekunden. der nachteil nur, ich kann keine zweidateinen hintereinander absenden, ist aber nicht so wild, da ich eh mit nur dieser einen datei arbeiten muß.
interpretieren von daten etc.
also nicht wundern, wenn ich bald mal auch fragen zu konvertierung und auslesen sowie erstellen vin ini-dateien stelle
Danke nochmal und lieben Gruß
Smartie
|
|
|