Autor Beitrag
Lago
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Mi 04.01.06 13:41 
Hallo.. und schon wieder ein Thema von mir.. :roll:

Ich hoffe ich kann auch dieses mal auf eure hilfe zählen.
Folgendes

Ich habe ine Prorämmchen, welches Daten über eine RS232 empfangen soll.

Diese Procedure sieht so aus:

ausblenden volle Höhe Delphi-Quelltext
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:
procedure TForm1.CommPortDriver1ReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal);
var
i,check : integer;
begin
  repeat
  CommPortDriver1.ReadChar(ch);
  until ch = StartDelimiter;
  repeat
    checksum := 27;
    check:= 0;
    CommPortDriver1.ReadChar (ch);
    checksum := checksum + ord (ch);
         case ch of
          'Z':  begin
                n := 16;
                msgType := 'Position';
                end;
          'W':  begin
                n := 5;
                msgType := 'Druckknopf';
                end;
          'U':  begin
                n := 1;
                msgType := 'Zeitabgelaufen';
                end;
         end;
          SetLength (msg, n);
         for i := 1 to n do
          begin
            CommPortDriver1.ReadChar (ch);
            checksum := checksum + ord (ch);
            msg [i] := ch;
          end;
         for i:=1 to 3 do
         begin
         CommPortDriver1.ReadChar (ch);
         check:= check + strtoint(ch);
         end;
    until check = checksum mod 256;  
Label1.Caption:= msg;
end;


Manchmal geht sie, manchmal nicht... Ich habe au nur einmal die erste Repeat schleife probiert:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  repeat
  CommPortDriver1.ReadChar(ch);
  until ch = StartDelimiter;
  Label1.Caption:= ch;

Mein StartDelimiter wird IMMER angezeigt im Label... ab und zu macht das Programm dann keinen Wank mehr.. machmal geht es noch..

Meine Frage.. Wieso?

Kann es an meinem StartDelimiter liegen ( chr(2) )?
Wenn ich von der anderen Seite etwas Sende, dann sende ich es 5mal hinter einander. Kann das, dass Problem sein?

Danke jetzt schon....

Pascal
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mi 04.01.06 13:56 
Hallo,

ausblenden Delphi-Quelltext
1:
CommPortDriver1ReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal);					


Ich gehe mal davon aus, dass in Datasize die Anzahl der Bytes steht die jetzt verfuegbar sind. Mehr kannst Du dann auch nicht mit readchar abrufen. Wahrscheinlich kannst Du die Daten in einem Rutsch in einen String s packen.
ausblenden Delphi-Quelltext
1:
2:
setlength(s,DataSize);
Move(DataPtr^,s[1],DataSize);

und dann weiterverarbeiten.

Gruss Horst

Moderiert von user profile iconTino: Delphi-Tags hinzugefügt
Lago Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Mi 04.01.06 15:57 
Das könnte klappen... nur sende ich die Daten etwa 5mal hintereinander... jetzt will ich, dass er nach einer bestimmten anzahl zeichen (hängt vom 2.Char ab) in diesen String packt. Mal 3, mal 5, mal 16...

Besteht hier auch die möglichkeit, dass ich einmal abklemmen kann?

Muss ich ein Sleep beim anderen Teil einbauen, dass er das merkt, dass die Sendung komplett ist? Habe gedacht ich könnte dies mit einer Cecksumm beenden... geht aber so in dieser Form eher nicht


Gruss

Pascal
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mi 04.01.06 16:32 
Hallo,

Du benutzt wohl TCommPortDriver component CPDrv.pas www.coding-board.de/...165&d=1044219216

Vielleicht ist es besser beim Onreceive Ereignis die Daten der per

ausblenden Delphi-Quelltext
1:
2:
3:
setlength(s,DataSize);//oder ???.CountRX
//ReadData( DataPtr: pchar; MaxDataSize: DWORD ): DWORD;
WahreLaenge := ???.ReadData(pchar(s),DataSize);


einzulesen und anschliessend den RX Buffer zu loeschen.
ausblenden Delphi-Quelltext
1:
2:
3:
???.PausePolling;
???.FlushBuffers( true,false);
???.ContinuePolling;


Ich weiss aber nicht, ob man dann nicht einzelne Bytes verliert, falls zwischen ReadData und PausePolling ein Byte eintrifft.

Gruss Horst

Moderiert von user profile iconTino: Delphi-Tags hinzugefügt
Lago Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 05.01.06 10:10 
Morgen.

Ich hab jetzt deine Variante Probiert... es stürzt wenigstens nicht mer ab jetzt... Es ist dafür nicht mehr sicher, dass all die von mir gesendeten Daten ankommen.

Jetzt macht es sicherlich sinn, eine abfrage zu machen und den string auszuwerten.

Ich werde dies mit einer Repeat schleife realisieren. Mal sehen wies aussieht nachher... ;-)

Was meinst du dazu? Hast du eine bessere möglichkeit?


Gruss
Pascal
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 05.01.06 10:32 
Hallo,

gehen tatsaechlich einige Bytes verloren?
Du koenntest vor dem Auslesen, ein paar ms warten, damit die maximale Byteanzahl (16 ?) eingetroffen ist.
bei 9600 Baud ~960 Byte/Sekunde also 16/960 ~ 17 ms.
Also bei Onreceive sleep(17) und anschliessend RXCount abfragen und diese Anzahl einlesen und RX loeschen.
Probier es mal so.

Gruss Horst
Lago Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 05.01.06 10:49 
Ich habe es jetzt einmal so Probiert... ich wusste nicht genau was du damit meinst, aber die Procedure sieht so aus:
ausblenden volle Höhe Delphi-Quelltext
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:
procedure TForm1.CommPortDriver1ReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal);
var
i,check : integer;
WahreLaenge: cardinal ;
begin
repeat
  repeat
  CommPortDriver1.ReadChar(ch);
  until ch = StartDelimiter;
    setlength(msg,DataSize);
    WahreLaenge := CommPortDriver1.ReadData(pchar(msg),DataSize);
    CommPortDriver1.PausePolling;
    checksum := 27;
    check:= 0;
    checksum := checksum + ord (msg[1]);
    case msg[1of
        'Z':  begin
        n := 16;
        msgType := 'Position';
        end;
        'W':  begin
        n := 5;
        msgType := 'Druckknopf';
        end;
        'U':  begin
        n := 1;
        msgType := 'Zeitabgelaufen';
        end;
    end;

    for i := 1 to n do        //Um Checksumme zu berechnen, werden hier die einzelnen Buchstaben umgewandelt
    begin
    checksum := checksum + ord (msg[i]);
    end;

    for i := 18 to 20 do       //Weil Theoretisch die letzten 3Zeichen der Message die Checksumme sind, probiere ich sie hier umzuwandeln...
    begin
    check:=strtoint(msg[i]);
    end;
checksum:= checksum mod 256;
until checksum  = check;
CommPortDriver1.FlushBuffers( true,false);
CommPortDriver1.ContinuePolling;
end;


Im ersten Teil wartet er, bis der von mir bestummene StartDelimiter ( chr(2) ) gefunden wird. Dann liest er ein... aber leider nicht immer genug, sondern manchmal 2Zeichen, manchmal 10Zeichen...

eigentlich sollte der empfang folgender massen aussehen nach dem StartDelimiter:

ZABCDEFGHIJKLMNOP253 (Wenn ein Z der erste Buchstabe ist, dann ist der String immer so lang)

W2164 (Wenn ein W der erste Buchstabe ist, siehts so aus)

U1161 (Nicht anderst beim U)

d.h. die Checksumme wird auch noch gleich angehängt

Diese Sachen möchte ich nun verarbeiten mit der oberen Procedure... Was stimmt dabei nicht?
Bin um jeden Input dankbar...

Gruss
Pascal
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 05.01.06 11:37 
Hallo,

ich dachte mehr an soetwas:
ausblenden volle Höhe Delphi-Quelltext
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:
procedure TForm1.CommPortDriver1ReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal);
var
i,check : integer;
WahreLaenge: integer;
Ausgabe : string;
begin
sleep(20);//Etwa 19 Zeichen warten
CommPortDriver1.PausePolling; // Abfrage Stopp
WahreLaenge :=CommPortDriver1.RXCOunt;//Anzahl der Empfangenen Bytes
setlength(msg,WahreLaenge);//msg ist wohl global
WahreLaenge := CommPortDriver1.ReadData(pchar(msg),WahreLaenge);//Daten nach msg kopieren
CommPortDriver1.FlushBuffers( true,false);//Empfangsspeicher leeren
CommPortDriver1.ContinuePolling;//Wieder auf Empfang gehen

Form1.Memo1.lines.add(Format('Empfangene Bytes %d',[WahreLaenge]);
Form1.Memo1.lines.add('Eingegangen '+msg);
For i := 1 to WahreLaenge do
  Ausgabe := Ausgabe+Format('%.3d '.[Ord(msg[i])]);
Form1.Memo1.lines.add(Ausgabe);
Ausgabe := '';
{
checksum := 27;
check:= 0;
checksum := checksum + ord (msg[1]);
case msg[1] of
   'Z':  begin
        n := 16;
        msgType := 'Position';
        end;
        'W':  begin
        n := 5;
        msgType := 'Druckknopf';
        end;
        'U':  begin
        n := 1;
        msgType := 'Zeitabgelaufen';
        end;
    end;

    for i := 1 to n do        //Um Checksumme zu berechnen, werden hier die einzelnen Buchstaben umgewandelt
    begin
    checksum := checksum + ord (msg[i]);
    end;

    for i := 18 to 20 do       //Weil Theoretisch die letzten 3Zeichen der Message die Checksumme sind, probiere ich sie hier umzuwandeln...
    begin
    check:=strtoint(msg[i]);
    end;
checksum:= checksum mod 256;
until checksum  = check;
}

end;


Gruss Horst
Lago Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 05.01.06 11:43 
Wollte ich gleich Probieren... RXCOunt gibt aber leider nicht für meine Komponente... :-(

Oder ist das eine Variable, die ich deklarieren muss? Nicht, oder?

Gruss Pascal