AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Auslesen der RS232

Offene Frage von "peter21"
Ein Thema von peter21 · begonnen am 24. Apr 2007 · letzter Beitrag vom 4. Mai 2007
Antwort Antwort
peter21

Registriert seit: 24. Apr 2007
Ort: Golm
18 Beiträge
 
Delphi 4 Standard
 
#1

Auslesen der RS232

  Alt 24. Apr 2007, 20:52
Hallo,

ich habe mich erst vor kurzem an Delphi 4 gewagt. Vor etlichen Jahren hatte ich viel in Turbo-Pascal programmiert und muss nun einige Programme, die noch im DOS-Fenster laufen, auf Delphi anpassen.

Ein Problem ist dabei die serielle Schnittstelle. Ich muss ein Temperaturmessgerät, das ohne Anforderungen im Sekundentakt die Werte versendet, auslesen.
Nach einigen Recherchen habe ich mich als Unit für SerialNG entschieden. Dort existiert auch ein Beispiel-Programm (SerialNGSpy), mit dem das im Prinzip gut klappt. Nehme ich die für mich überflüssigen Funktionen heraus, funktioniert das Auslesen nicht mehr (Na ja, man soll auch auch auf diese Weise nicht programmieren).

Ich habe dann noch ein Beispiel von Tino Teuber angepasst, auch dort liest er die Schnittstelle ebenfalls nicht aus. Was mache ich falsch? Habe ich etwas vergessen?

Das Programm springt einfach nicht in die Procedure SerialPortNGRxClusterEvent.

Delphi-Quellcode:
unit RS232Mar_Unit1;

(*Dieses Programm liest die Temperatur über eine RS232-Schnittstelle
aus einem Temperatur-Messsystem aus.*)


interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, ExtCtrls, ComCtrls, Menus,
  SerialNG,
  peterlib;

type
  TForm1 = class(TForm)
    Timer_Messung: TTimer;
    Messwerte: TRichEdit;
    MainMenuMessung: TMainMenu;
    Start1: TMenuItem;
    Ende1: TMenuItem;
    Datei: TMenuItem;
    Beenden1: TMenuItem;
    COM_1: TSerialPortNG;
    procedure Formactivate(Sender: TObject);
    procedure Start1Click(Sender: TObject);
    procedure SerialPortNGRxClusterEvent(Sender: TObject);
    procedure Timer_MessungTimer(Sender: TObject);
    procedure Messinterval1Click(Sender: TObject);
    procedure Ende1Click(Sender: TObject);
    procedure Beenden1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    COMStr: String;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
const
  n_messstellen = 1;

var
  messzeit, messzeit0: TDateTime;
  Messstellen_name: array [1 .. n_messstellen] of string;
  MesswerteArray: array [0..n_messstellen] of real;
  Messung: Boolean;

(*--------------Start-Proceduren-----------------------------------*)
procedure TForm1.FormActivate(Sender: TObject);
begin
  Messwerte.Text:= ' ';
  (* alles ausschalten *)
   Messung := False;
end;

procedure TForm1.Start1Click(Sender: TObject);
procedure start_rs232;
begin
   COM_1:= TSerialPortNG.Create(nil);
   with COM_1 do
     begin
        CommPort:= 'COM1';
        BaudRate:= CBR_2400;
        ParityType:= noparity;
        DataBits:= 8;
                StopBits:= 1;
      Active:= true;
    end;
  messstellen_name[1]:= 'Temperatur';
end; (*start_rs232 in start1click*)
begin (*Main of Start1Click*)
   Messung:= True;
  Messwerte.Text:= 'Startzeit = ' +
     DateToStr (date) + ' ' + TimeToStr(time) + ' '#13#10;
    start_rs232;
  messzeit0:= now;
end;

(*-----------------Messung-------------------------------------------*)
(*COM wird laufend in einen Test-String ausgelesen.*)
procedure TForm1.SerialPortNGRxClusterEvent(Sender: TObject);
begin
   if TSerialPortNG(Sender).NextClusterSize >= 0 then // Data available?
    begin
      if TSerialPortNG (Sender).NextClusterCCError = 0 then // Error during receiveing?
        COMStr:= '9999999'
      else
   COMStr:= TSerialPortNG(Sender).ReadNextClusterAsString;
    end;
end;

procedure TForm1.Timer_MessungTimer(Sender: TObject);
procedure messung_rs232;
var
   COMStr: String;
  messwert: real;
  zeit_ende: TDateTime;
  Daten_OK: Boolean;
  ftimeout_s: integer;
  ftimeout_d: real;
begin
   COMStr:= '';
  Daten_OK:= False;
  ftimeout_s:= 500; (*TimeOut in ms*)
  ftimeout_d:= ftimeout_s / 1000 / 60 / 60 / 24;
  (*Zeit berechnen, wann timeout erreicht wird.*)
   zeit_ende:= now + ftimeout_d;

(*  While (now < zeit_ende) and (not Daten_OK) do
     begin
       if COM_1.nextClusterSize > 0 then
         COMStr:= COMStr + COM_1.ReadNextClusterAsString;
      if copy (COMStr, length (COMStr), 1) = #13 then
         Daten_OK:= true;
      sleep (50);
    end; (*while (getTime() ... *)


  messwert:= COMtoReal (COMStr); (*Extrahiert die Werte aus dem String*)
  COMStr:= '';
  messwerte.text:= Messwerte.Text +
  messstellen_name [1] + '= '
    + FloatToStrF (messwert, ffFixed, 7, 2) + #13#10;
end; (*messung_rs232 in in Timer_MessungTimer*)
begin (*Main in Timer1Timer*)
   IF Messung Then
    BEGIN
      messzeit:= now;
      MesswerteArray[0]:= (messzeit - messzeit0)*24*60*60;
      Messwerte.text:= 'Zeit / s: '
         + FloatToStrF (MesswerteArray[0],ffFixed,7, 0) + #13#10;
        messung_rs232;
    END; (*IF Messung*)
end; (*Timer_MessungTimer*)

(*-------------------------------------Parameter verändern--------------*)

procedure TForm1.Messinterval1Click(Sender: TObject);
var
  str_zeitkonstante: String;
begin
  str_zeitkonstante:= inttostr (form1.timer_Messung.interval DIV 1000);
   str_zeitkonstante:= inputbox ('Zeitkonstante', 'Zeitkonstante in s:',
        str_zeitkonstante);
  form1.timer_Messung.interval:= StrToInt (str_zeitkonstante) * 1000;
end;

(*----------------------Messung beenden-------------------------------*)

procedure TForm1.Ende1Click(Sender: TObject);
begin
  (* alles ausschalten *)
   Messung := False;
end;

(*-----------------------------Programm beenden------------------------*)

procedure TForm1.Beenden1Click(Sender: TObject);
begin
  IF not messung then
    application.terminate;
end;

end.
Vielen Dank für Eure Hilfe.

Peter
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: Auslesen der RS232

  Alt 25. Apr 2007, 00:29
1. Du hast COM_1 bei der Komponentenliste der Form deklariert und instanziierst die gleichzeit nochmal (COM_1:= TSerialPortNG.Create(nil); ) Warum?
2. Wenn die Komponente auf der Form liegt, dann brauchst du keine Instanz erzeugen, sondern sie existiert schon.
3. Owner von Nil könnte für die Komponente nachteilig sein, da sie vllt. das Fenster ihres Owners nutzt.
4. COMStr wurde in der Klasse TForm1 und lokal deklariert. Welches gilt nun?
5. Application.Terminate ist die Holzhammermethode. Rufe lieber einfach nur Close; auf
  Mit Zitat antworten Zitat
peter21

Registriert seit: 24. Apr 2007
Ort: Golm
18 Beiträge
 
Delphi 4 Standard
 
#3

Re: Auslesen der RS232

  Alt 25. Apr 2007, 17:22
Zitat von Muetze1:
1. Du hast COM_1 bei der Komponentenliste der Form deklariert und instanziierst die gleichzeit nochmal (COM_1:= TSerialPortNG.Create(nil); ) Warum?
Das habe ich aus dem Beispiel von Tino Teuber. Habe ich aber erst eingebaut, nach dem das Auslesen nicht funktioniert hat.
Zitat:
2. Wenn die Komponente auf der Form liegt, dann brauchst du keine Instanz erzeugen, sondern sie existiert schon.
3. Owner von Nil könnte für die Komponente nachteilig sein, da sie vllt. das Fenster ihres Owners nutzt.
Habe den Teil wieder rausgenommen.
Zitat:
4. COMStr wurde in der Klasse TForm1 und lokal deklariert. Welches gilt nun?
OK ist bei der Fehlersuche passiert, ist aber nicht das eigentliche Problem.
Zitat:
5. Application.Terminate ist die Holzhammermethode. Rufe lieber einfach nur Close; auf
Danke, habe ich entsprechend geändert.

Vielen Dank für die Hilfe. Leider hat das das Problem noch nicht gelöst.

Wäre für weitere Hilfestellung dankbar.

Peter
  Mit Zitat antworten Zitat
Nuclear-Ping
(Gast)

n/a Beiträge
 
#4

Re: Auslesen der RS232

  Alt 26. Apr 2007, 00:58
Kenne die Komponenten nicht, die du verwendest.

Aber ich kann dir persönlich "TurboPower AsyncProfessional" (oder kurz TPAPro) empfehlen. http://sourceforge.net/projects/tpapro/
Die "TApdComPort"-Komponente hat verschiedene Trigger-Events. Die solltest du dir mal anschauen.
  Mit Zitat antworten Zitat
peter21

Registriert seit: 24. Apr 2007
Ort: Golm
18 Beiträge
 
Delphi 4 Standard
 
#5

Re: Auslesen der RS232

  Alt 26. Apr 2007, 20:13
Vielen Dank für die Antwort. Ich habe mir TPAPro angeschaut. Ich finde es unübersichtlich und recht kompliziert.
Zu TurboPascal-Zeiten hatte eine RS232-Unit genau 3 Proceduren und 4 Funktionen:

procedure InitRS232 (Kanal: byte; Baudrate: INTEGER;
Parity, StopBits, DataBits : byte);
procedure SendRS232(Kanal: byte; ch: char);
procedure ReadRS232(Kanal: byte; var ch: char);
function RS232Status(Kanal: byte): integer;
function Bit(Stelle, Zahl: integer): boolean;
function ZeichenVorhanden : boolean;
function DarfSenden : boolean;

und man konnte alles damit machen. Warum ist das jetzt so kompliziert?

Peter
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: Auslesen der RS232

  Alt 28. Apr 2007, 14:16
Es ist nicht kompliziert. Es ist nur OOP, sonst ist alles gleich. Die Komponenten bieten dir das doch auch alles recht einfach aufbereitet an. Aber die Hintergründe haben sich geändert, aber da hattest du dich doch damals unter TP auch nicht drum gekümmert, wie der Portzugriff in deiner RS232 Unit funktionierte - genauso wenig wie heute, wie die Komponente mit den Windows COMM Routinen spielt...

Hast du dir das schonmal angeschaut?
  Mit Zitat antworten Zitat
peter21

Registriert seit: 24. Apr 2007
Ort: Golm
18 Beiträge
 
Delphi 4 Standard
 
#7

Re: Auslesen der RS232

  Alt 4. Mai 2007, 21:11
Hallo Muetze1,

vielen Dank für Deine Antwort. Das von Dir verlinkte Beispiel kannte ich schon und hatte das in meine Programm eingebaut.
Inzwischen bin ich schon ein kleines Stück weiter. Ich hatte geglaubt, dass die Routinen Formcreate oder Formactivate automatisch angesprungen werden, was aber nicht der Fall ist. Wenn ich das entsprechende Ereignis in der Form1 verlinke, dann wird die Schnittstelle tatsächlich aktiviert. In der Folgezeit wird auch das Ereignis "TForm1.SerialPortNGRxClusterEvent" aufgerufen.

Ich habe mich dann mit dem Problem herumgeschlagen, warum immer ein "NextClusterCCError" mit 0 ausgegeben wird (Originalbeispiel von der SerialNG). Wird dort der Vergleich auf >0
Delphi-Quellcode:
   if TSerialPortNG(Sender).NextClusterSize >= 0 then // Data available?
    begin
       fehlercode:= TSerialPortNG (Sender).NextClusterCCError;
      if fehlercode > 0 then // Error during receiveing?
          COMStr:= '9999999';
      else
        COMStr:= TSerialPortNG(Sender).ReadNextClusterAsString;
    end;
geändert (was logisch erscheint), so kann nach der Beseitigung eines weiteren von mir gemachten Fehlers die serielle Schnittstelle problemlos ausgelesen werden.

Ich frage mich nur, warum das Programm SerialNGSpy funktioniert. Ich vermute, das liegt daran, dass dort 2 Schnittstellen abgefragt werden, und somit der Fehler kompensiert wird.

Ich danke für Eure Hilfe.

Peter
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: Auslesen der RS232

  Alt 4. Mai 2007, 21:58
Zitat von peter21:
Ich hatte geglaubt, dass die Routinen Formcreate oder Formactivate automatisch angesprungen werden, was aber nicht der Fall ist. Wenn ich das entsprechende Ereignis in der Form1 verlinke, dann wird die Schnittstelle tatsächlich aktiviert.
Oh, ok, an solche grundlegenden Dinge hatte ich nun wirklich nicht gedacht. Da hätte ich auch mal drauf hinweisen können. Das nächste mal...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz