Forum: PC-Programmierung Hilfe bei RS232-Fkt in DLL


von TK (Gast)


Lesenswert?

Hallo zusammen,

ich brauch mal eure Hilfe. Ich habe eine DLL mit C++ erstellt, in der 
sich diverse Routinen für die RS232 befinden (z.B. send_data(), 
receive_data(), setup_comm() usw.). Von einem anderen Programm binde ich 
die DLL ein, bzw. nutze die Funktionen innerhalb der DLL. Alle 
Funktionen liefern hierbei ein Ergebnis zurück - meist eine BOOL (z.B. 
success = receive_data(Parameter)).
Da ich innerhalb der Funktion receive_data im Polling-Modus auf Daten 
warte, und gleichzeitig dort auch einen Timeout-Timer laufen habe, kommt 
es nun vor, dass der Timeout-Timer (ca. 3s) immer dann anspricht, wenn 
keine Daten über die RS232 von einem entsprechenden Device zurückkommen 
- soweit ist das ja OK. Aber jetzt ist es so, dass mein Hauptprogramm 
ca. 70 Devices, die über einen Bus vernetzt sind, in regelmäßigen 
Abständen abfragt (abfragen muss!)
Da es sich um eine Art TOKEN-RING-BUS handelt (HARDWARE ist fest 
vorhanden
und NICHT verhandelbar!) kann es in seltenen Ausnahmen vorkommen, dass 
eben
ein Device in dieser Kette nicht mehr reagiert und somit das 
Gesamtsystem lahmlegt. Dann spricht bei jeder Abfrage der Timeout-Timer 
an - bei 70 Devices a)3s kann man sich ja ausrechnen, wie lange das 
Gesamtsystem blockiert wird.
Soviel zum Vorgeplänkel.
Jetzt meine Frage: Welche Möglichkeit habe ich, dass z.B. die Daten 
nicht mehr im Polling-Modus abgefragt werden? Wie kann ich, solange noch 
kein Rückgabewert der Funktion vorhanden ist, im Hauptprogramm 
weitermachen, ohne dass das System blockiert wird. Als Parameter zum 
Aufruf der Funktion dient u.a. ein Pufferbereich, der die Daten 
aufnehmen soll, die Adresse des abzufragenden Devices usw.

Danke schon mal - auch fürs durchlesen
Gruß
TK

von Spess53 (Gast)


Lesenswert?

Hi

In deinem Fall wäre es günstiger der COM-Schnittstelle einen eigenen 
Thread zu spendieren. Die Kommunikation zwischen Hauptprogamm und Thread 
erfolgt dann nur noch auf der Message-Ebene. Wenn du wissen willst, wie 
so etwas aussieht, dann suche mal nach 'cport'. Version 3 oder höher.

MfG Spess

von TK (Gast)


Lesenswert?

Das mit einem eigenen Thread ist so eine Sache.
Ich benutze die DLL mit den 'Low-Level-Routinen' in fast allen 
Programmen,
die eine RS232 Kommunikation benötigen. Da müsste ich ja alle Programme 
umschreiben. Ist dann doch ein wenig zu viel. Ich komme um die DLL nicht 
herum. Mein erster Lösungsansatz war eigentlich die Timeout-Zeit von 3s 
auf z.B. 300ms zu reduzieren. Die Frage ist dann nur, ob die Devices 
nicht doch gerade in einer Interruptroutine irgendwas machen (z.B. Zeit 
verbraten). Wie könnte ich denn innerhalb der DLL einen Thread 
aktivieren, der die Daten von der RS232 einliest UND wie kann ich dann 
dem Hauptprogramm mitteilen, dass die Daten im Puffer stehen, wenn die 
DLL-Funktion bereits verlassen wurde?
Das ist hierbei mein größtes Problem. Kurz gesagt - ans Hauptprogramm 
möchte ich nicht ran. Aber wahrscheinlich komm ich wohl nicht darum.

Gruß
TK

von Spess53 (Gast)


Lesenswert?

Hi

Vorab erst mal : ich programmiere meine Programme mit Delphi. Aber die 
Verwendung von API-Funktionen verläuft genauso wie unter C++.
Hast du die die Routinen in eine eigene Class verpackt? Wenn nicht, 
gehst du am Konzept von C++ vorbei und da sind deine Schwierigkeiten 
vorprogrammiert.

MfG Spess

von TK (Gast)


Lesenswert?

Ich habe die Routinen nicht in eine Klasse verpackt. Ich sehe aber hier 
auch nicht das Problem. OK - nur weil ich den Borland C++ Compiler hab 
muss ich ja nicht unbedingt immer auf die C++ Konzepte zurückgreifen. Im 
übrigen versteht  der ja auch Delphi.
Wo wäre denn der Vorteil bei der Behebung meines Problems, wenn die 
Routinen in einer Klasse stecken würden?

Gruß
TK

von Spess53 (Gast)


Lesenswert?

Hi

Wie gesagt, ich komme aus der Delphi-Ecke. Der Vorteil für mich ist, 
dass ich  eine Serielle Schnittstelle als Komponente in ein Formular 
einfügen kann. Über die Schnittstellen der Komponente wird dann auf die 
Eigenschaften und Funktionen zugegriffen.
Zum Beispiel kann deine Komponente(class) einen eigenen Timer besitzen. 
Der fragt in bestimmten Abständen den COM-Port ab und liest ,wenn 
vorhanden, die Daten in einen internen Puffer. Danach wird eine 
Nachricht (message) an das Hauptprogramm geschickt. Das Hauptprogramm 
holt dann die Daten über eine Funktion der Class ab. Damit hast du die 
eigentliche Behandlung des COM-Ports vom Hauptprogramm abgekoppelt. Dein 
Hauptprogramm kann dann in aller Ruhe überprüfen, ob irgendwelche Sender 
ein Timeout haben, ohne blockiert zu werden.

MfG Spess

von TK (Gast)


Lesenswert?

Generell hab ich auch kein Problem mit Delphi. Ich hab AUCH in C++ eine
Komponente für die serielle Schnittstelle. Die kann ich hier aber nicht 
benutzen (Lizenzprobleme)! Deshalb hab ich ja die DLL geschrieben. Die 
kann ich nämlich weitergeben, OHNE Probleme mit anderen zu bekommen. Und 
selbst eine Komponente erstellen - so weit bin ich noch nicht in die 
Materie eingestiegen. Klar hat eine Komponente die Vorteile, die du 
angesprochen hast. Man kann dann schön auf Ereignisse reagieren usw.
Nur ist es bei diesem Projekt so, dass ich zwar das Hauptprogramm 
erstellt habe, aber dieses nur als "Demo" an einen Kunden rausging. Der 
hat jetzt sein eigenes Programm entwickelt und muss eben die DLL für die 
Kommunikation mit den Devices benutzen (da sind eben nicht nur RS232 
Routinen drin). Da liegt jetzt das Problem. Ich bzw. er kommt ohne die 
DLL nicht klar. Und die Routinen/Funktionen offen legen möchte ich dann 
auch nicht.
Vielleicht gibts ja eine Möglichkeit einen GLOBALEN Puffer zu 
deklarieren, den sowohl das Hauptprogramm, als auch die DLL benutzen 
können. Den könnte man ja dann füllen, wenn tatsächlich Daten da sind. 
Demnach müsste jede DLL Routine sofort wieder verlassen werden und das 
Hauptprogramm müsste dann zyklisch den Inhalt des Puffers prüfen. Aber 
auch hier seh ich eigentlich zu viel Aufwand für die DLL und das 
Hauptprogramm. Momentan bin ich echt ratlos.

Gruß
TK

von Ekkehard D. (ekkehard)


Lesenswert?

Hallo,
nur damit ich es verstanden habe:
- ca. 70 Geräte hängen am gleichen CommPort
- Dein Hauptprogramm ruft eine Funktion in der DLL auf um Daten an ein 
einzelnes Gerät zu senden oder von einem einzelnen Gerät zu empfangen.

Unter dieser Annahme, könntest Du in der DLL einen Thread bauen der von 
sich aus mit allen Geräten spricht und die Ergebnisse in ein einen 
Puffer ablegt.
Deine Funktionen die von Deinem Hauptprogramm aufgerufen werden lesen 
dann z.B. nicht mehr von der Schnittstelle sondern aus der 
Ergebnisliste. Da da z.B. drinnsteht, das ein Timeout aufgetreten ist 
muss der Funktionsaufruf nicht bis zum Timeout dauern, sondern kehrt 
sofort zurück.
Allerdings musst Du mit Threads in DLLs aufpassen. Z.B. darfst Du im 
Initialisierungsbereich keine Threads erzeugen oder im 
Zerstörungsbereich keine Threads beenden. Falls Dein Hauptprogramm eine 
Funktion "Öffen CommPort" aufruft kannst Du dort den Thread erzeugen 
(und bei "Schließe CommPort" beenden).
Und du musst den Zugriff auf Deine Ergebnisse mit z.B. Critical Sections 
schützen, damit nicht das Chaos losbricht wenn Dein Hauptprogramm und 
Dein Thread gleichzeitig auf diese Bereiche zugreifen.

Gruß Ekkehard

von TK (Gast)


Lesenswert?

@ Ekkehard
Genau so / so ähnlich hab ich mir das vorgestellt.
Jetzt mal zu meinem Verständnis: Also die DLL agiert autark und fragt 
dann
zyklisch alle Teilnehmer von sich aus ab, trägt die gesammelten Daten in 
einen Ereignispuffer und wartet nur noch darauf, dass das Hauptprogramm 
den Puffer ausliest.
OK - soweit verstanden.
Jetzt kommt allerdings eine Kleinigkeit dazu. Es gibt ja mehrere 
Funktionen innerhalb der DLL, die auch unterschiedliche Ereignisse an 
den Devices auslösen. Also z.B. Datenwerte abfragen, Parameter 
übergeben, Selbsttests durchführen lassen usw.
Und jede dieser Routinen benutzt letztendlich die Schnittstelle mit den
Timeoutvorgaben.
Durch den Thread könnte ich also z.B. die Hauptfunktion (nämlich 
Datenwerte abfragen) automatisieren. Alle anderen Funktionen würden ohne 
Threadsteuerung arbeiten wie bisher - also mit Timeout.
Aber ich denke, das wäre schon mal ein riesiger Schritt in die richtige 
Richtung. Ich mach mich dann mal an die Überlegungen für einen 
Threadaufbau und dann an die Programmierung.
Danke erst mal

Gruß
TK

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.