AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Problem mit Kommunikation mit Comport über WinApi
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit Kommunikation mit Comport über WinApi

Ein Thema von hlware · begonnen am 22. Jul 2010 · letzter Beitrag vom 5. Okt 2011
Antwort Antwort
Seite 1 von 2  1 2      
hlware

Registriert seit: 2. Jul 2010
Ort: Würzburg
5 Beiträge
 
Turbo Delphi für Win32
 
#1

Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 19:48
Hallo,

ich habe folgendes Problem:
Ich möchte ein Märklin-Interface über einen Comport mittels Win-Api ansteuern. Das funktioniert soweit einwandfrei, aber nur, wenn ich zuvor einmal eine Verbindung mit einem alten C++ Programm hergestellt und wieder geschlossen habe. Bis zu einem Windows-Neustart gibt es dann keine Probleme mehr.

Hier mal der Code für ein kleines Testprogramm. (Der Code ist aus dem eigentlichen Programm herauskopiert, es besteht aber dasselbe Problem)

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Port : String;
befehl : Char;
ComHandle : THandle;
DCB : TDCB;
TimeOut : TCommTimeouts;
i1,i2 : integer;
begin
  Port := 'Com2';
  ComHandle := CreateFile(pChar(Port), GENERIC_READ OR GENERIC_WRITE,
                              0, nil, OPEN_EXISTING, 0, 0);
  if ComHandle > 0 then begin

      DCB.DCBlength := SizeOf(DCB);
      DCB.ByteSize := 8;
      DCB.Parity := NoParity;
      DCB.StopBits := TWOSTOPBITS;
      DCB.BaudRate := 2400;
 
      GetCommTimeOuts(ComHandle, TimeOut);

      TimeOut.ReadIntervalTimeOut := 100;
      TimeOut.ReadTotalTimeoutMultiplier := 0;
      TimeOut.ReadTotalTimeoutConstant := 1;

      TimeOut.WriteTotalTimeoutMultiplier := 0;
      TimeOut.WriteTotalTimeoutConstant := 0;
      SetCommTimeouts(ComHandle, TimeOut);

  end;

  befehl := chr(97); // Befehl für globales Abschalten der Gleisspannung
  i1 := FileWrite(ComHandle, befehl, 1);
  sleep(2000); // Damit Meine langsamen Augen die Anzeige auf der Control Unit auch sehen
  befehl := chr(96); // Gleisspannung wieder freigeben
  i2 := FileWrite(ComHandle, befehl, 1);
  ShowMessage(IntToStr(ComHandle) + ', ' + IntToStr(i1) + ',' + IntTostr(i2)); // Nur zur Überprüfung

  FileClose(ComHandle);
  ComHandle := 0;
end;
Die Werte von DCB und TimeOut sind identisch mit denen des C++ Programmes.
Woran kann das liegen?

Gruß
Hlware
  Mit Zitat antworten Zitat
Reinhard Kern

Registriert seit: 22. Okt 2006
772 Beiträge
 
#2

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 20:00
Die Werte von DCB und TimeOut sind identisch mit denen des C++ Programmes.
Woran kann das liegen?
Hallo,

das kann garnicht sein: DCB umfasst 28 Felder, nur 5 davon setzt du neu. Ähnlich bei Timeout. Der Unterschied liegt also wohl in den 23 Feldern, die C++ setzt und dein Programm nicht. Z.B. sagst du garnichts über Handshaking.

Also vergleiche die Werte in C++ und in deinem Programm.

Gruss Reinhard
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.620 Beiträge
 
Delphi 12 Athens
 
#3

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 20:02
Außerdem gehört IMO das end; zu
Zitat:
if ComHandle > 0 then begin
ganz an den Schluss, denn das Handle muss ja gültig sein, damit man darauf zugreifen kann.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
hlware

Registriert seit: 2. Jul 2010
Ort: Würzburg
5 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 20:17
Zitat:
das kann garnicht sein: DCB umfasst 28 Felder, nur 5 davon setzt du neu. Ähnlich bei Timeout. Der Unterschied liegt also wohl in den 23 Feldern, die C++ setzt und dein Programm nicht. Z.B. sagst du garnichts über Handshaking.
Das stimmt. Aber im C++ Programm habe ich auch nur diese Felder gesetzt.
Leider kann ich die anderen Felder dort nicht überprüfen, da ich den Turbo C++ Explorer 2006 nicht mehr zum laufen bekomme und mir so nur der vorhandene Code und eine Alte .exe geblieben sind.

Zitat:
Außerdem gehört IMO das end; zu
if ComHandle > 0 then begin ganz an den Schluss, denn das Handle muss ja gültig sein, damit man darauf zugreifen kann.
Der Handle ist gültig, jedenfalls zeigt er mir in ShowMessage eine Zahl > 0 an. Im eigentlichen Programm hab ich noch eine if ComHandle = INVALID_HANDLE_VALUE then ShowMessage(... eingebaut bevor DCB und TimeOuts gesetzt werden.

Gruß
Hlware
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#5

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 23:03
... einen Comport mittels Win-Api ansteuern.
Du macht einen Fehler, denn du hast keinerlei Trennung zwischen "Eisenbank-Logik" und der Ansteuerung der seriellen Schnittstelle.
Ohne diese Trennung entsteht der berüchtigte Big Ball of Mud (auch bekannt als Spaghetticode) - die Software mutiert zur
einen unentwirrbaren Klumpen aus Code.
Ein kleine Änderung kann dann an anderer Stelle zu unerwünschten Nebeneffekten führen
und man verbringt mehr Zeit mit Debuggen als mit Programmieren.

Es gibt nur eine saubere Lösung:
Du brauchst eine eigene Klasse oder Komponente, die sich nur um die Ansteuerung der seriellen Schnittstelle
kümmert.
Glücklicherweise gibt es einige gute Komponenten für die serielle Schnittstelle.
Du findest sie über die Suchfunktion oder vielleicht hat auch einer der Mitleser eine Empfehlung.
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#6

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 22. Jul 2010, 23:19
Empfehlen kann ich dafür die TurboPower Async Pro Komponenten.
Ich habe die serielle Komponente (TAPDPort) in einigen Projekten am Laufen (darunter eins mit ~1500 Installationen) und es gab damit eigentlich noch nie Probleme.
  Mit Zitat antworten Zitat
hlware

Registriert seit: 2. Jul 2010
Ort: Würzburg
5 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 23. Jul 2010, 01:24
Hallo,

Ich hab die Lösung für das Problem gefunden. Nach einigem Auslesen der DCB Felder vor und nach dem Setzen der Eigenschaften bin ich darauf gekommen.
Es fehlte einfach ein
SetCommState(ComHandle,DCB); Damit ist natürlich klar warum es nicht gehen konnte.


Zitat:
Es gibt nur eine saubere Lösung:
Du brauchst eine eigene Klasse oder Komponente, die sich nur um die Ansteuerung der seriellen Schnittstelle
kümmert.
Ich habe mir eine eigene Klasse geschrieben, die sich auf das für mich nötigste beschränkt und auch gut funktioniert. Den Codeschnipsel habe ich nur schnell zusammenkopiert, die Eisenbahnbefehle habe ich nur eingefügt, damit ich das Ergebnis überprüfen kann.

Eine Komponente benötige ich im Moment nicht, da mit meiner Klasse alles funktioniert was ich brauche, wenn ich halt das SetCommState nicht vergessen hätte.

Vielen Dank für die Hilfe,
Gruß

Hlware
  Mit Zitat antworten Zitat
sneumann
(Gast)

n/a Beiträge
 
#8

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 5. Okt 2011, 10:50
Hallo,

Ich hab die Lösung für das Problem gefunden. Nach einigem Auslesen der DCB Felder vor und nach dem Setzen der Eigenschaften bin ich darauf gekommen.
Es fehlte einfach ein
SetCommState(ComHandle,DCB); Damit ist natürlich klar warum es nicht gehen konnte.


Zitat:
Es gibt nur eine saubere Lösung:
Du brauchst eine eigene Klasse oder Komponente, die sich nur um die Ansteuerung der seriellen Schnittstelle
kümmert.
Ich habe mir eine eigene Klasse geschrieben, die sich auf das für mich nötigste beschränkt und auch gut funktioniert. Den Codeschnipsel habe ich nur schnell zusammenkopiert, die Eisenbahnbefehle habe ich nur eingefügt, damit ich das Ergebnis überprüfen kann.

Eine Komponente benötige ich im Moment nicht, da mit meiner Klasse alles funktioniert was ich brauche, wenn ich halt das SetCommState nicht vergessen hätte.

Vielen Dank für die Hilfe,
Gruß

Hlware

Könntest du vielleicht mal deinen Code hier poste zum ansteuern auslesen und senden der Ports???
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.048 Beiträge
 
Delphi 12 Athens
 
#9

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 5. Okt 2011, 10:59
Falls er nicht antwortet (bedenke, hlware war seit über einem Jahr nicht mehr hier online/eingeloggt)

Entweder du nimmst eine der fertigen Komponenten (diese nehmen dir einiges/viel Arbeit ab).

Ansonsten stehn im MSDN die Infos zu den nötigen APIs, für die Konfiguration des COM-Ports.
Wenn man nur CreateFile und ReadFile/WriteFile nutzt, dann werden nur die Standardeinstellungen des entsprechenden Ports verwendet, welche nicht unbedingt passen müssen.

Hier findest du die Infos: (auch mal Links nachsehn, was es noch für APIs gibt)
http://msdn.microsoft.com/en-us/libr.../aa363436.aspx


Und nochmals was zum Code.
if ComHandle > 0 then begin ist falsch, denn CreateFile liefert INVALID_HANDLE_VALUE, wenn das Öffnen nicht funktionierte,
also if ComHandle <> INVALID_HANDLE_VALUE then begin gehört dort hin. (die zusätzliche Abfrage, mit der MessageBox, hilft da auch nichts)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu ( 5. Okt 2011 um 11:02 Uhr)
  Mit Zitat antworten Zitat
sneumann
(Gast)

n/a Beiträge
 
#10

AW: Problem mit Kommunikation mit Comport über WinApi

  Alt 5. Okt 2011, 11:43
Hallo,

Ich hab die Lösung für das Problem gefunden. Nach einigem Auslesen der DCB Felder vor und nach dem Setzen der Eigenschaften bin ich darauf gekommen.
Es fehlte einfach ein
SetCommState(ComHandle,DCB); Damit ist natürlich klar warum es nicht gehen konnte.


Zitat:
Es gibt nur eine saubere Lösung:
Du brauchst eine eigene Klasse oder Komponente, die sich nur um die Ansteuerung der seriellen Schnittstelle
kümmert.
Ich habe mir eine eigene Klasse geschrieben, die sich auf das für mich nötigste beschränkt und auch gut funktioniert. Den Codeschnipsel habe ich nur schnell zusammenkopiert, die Eisenbahnbefehle habe ich nur eingefügt, damit ich das Ergebnis überprüfen kann.

Eine Komponente benötige ich im Moment nicht, da mit meiner Klasse alles funktioniert was ich brauche, wenn ich halt das SetCommState nicht vergessen hätte.

Vielen Dank für die Hilfe,
Gruß

Hlware
Ich lese mir das mal kurz durch auf der Seite vielleicht kommt dann mehr Verständnis

Was bedeutet die Ausgabe?? 4294967295, -1, -1 das bekomme ich zurück : bei dem Code
ich brauche also nur Create, Read und Write für meine Aufgabe?

Code:
unit main;



interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SetupAPI;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var Port : String;
befehl : Char;
ComHandle : THandle;
DCB : TDCB;
TimeOut : TCommTimeouts;
i1,i2 : integer;
begin
  SetCommState(ComHandle,DCB);
  Port := 'Com5';
  ComHandle := CreateFile(pChar(Port), GENERIC_READ OR GENERIC_WRITE,
                              0, nil, OPEN_EXISTING, 0, 0);

  //if ComHandle = INVALID_HANDLE_VALUE then begin ShowMessage('INVALID HANDLE VALUE '); end;
  if ComHandle <> INVALID_HANDLE_VALUE then begin
  //if ComHandle > 0 then begin

      DCB.DCBlength := SizeOf(DCB);
      DCB.ByteSize := 8;
      DCB.Parity := NoParity;
      DCB.StopBits := TWOSTOPBITS;
      DCB.BaudRate := 2400;
 
      GetCommTimeOuts(ComHandle, TimeOut);

      TimeOut.ReadIntervalTimeOut := 100;
      TimeOut.ReadTotalTimeoutMultiplier := 0;
      TimeOut.ReadTotalTimeoutConstant := 1;

      TimeOut.WriteTotalTimeoutMultiplier := 0;
      TimeOut.WriteTotalTimeoutConstant := 0;
      SetCommTimeouts(ComHandle, TimeOut);
 
  end;

  befehl := chr(97); // Befehl für globales Abschalten der Gleisspannung
  i1 := FileWrite(ComHandle, befehl, 1);
  sleep(2000); // Damit Meine langsamen Augen die Anzeige auf der Control Unit auch sehen
  befehl := chr(96); // Gleisspannung wieder freigeben
  i2 := FileWrite(ComHandle, befehl, 1);
  ShowMessage(IntToStr(ComHandle) + ', ' + IntToStr(i1) + ',' + IntTostr(i2)); // Nur zur Überprüfung

  FileClose(ComHandle);
  ComHandle := 0;
end;

end.

Geändert von sneumann ( 5. Okt 2011 um 11:46 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 10:47 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