Forum: PC-Programmierung Softwarertimer Windows Visual Studio


von Marr (Gast)


Lesenswert?

Hallo Freunde,
ich hole mir Daten von einem µC und Sensoren über eine serielle 
Schnittstelle.
Meine Betriebsart ist der sogenannte nonoverlapped-Betrieb.

Ich sage dem µC zB.. Schicke mir zwei Byte und dann tut er dies..
Problem ist, wenn er mir die nicht schickt, weil der Stecker rausgezogen 
wird, wartet mein Programm solange bis dann doch die Antwort kommt..

Nun möchte ich nach jedem Programmdurchlauf (500ms) sagen, dass der 
Softwarertimer zurrückgesetzt wird.. Erreicht der Timer im Hintergrund 
zB 1000ms stoppt mein Programm..
Wie bereits im Betreff steht Programmiere ich mit Visual Studio..

Wenn jemand eine bessere Idee hat...

Gruß
Marr

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

"Visual Studio" ist keine Programmiersprache, sondern eine 
Entwicklungsumgebung, mit der recht viele völlig unterschiedliche 
Programmiersprachen verwendet werden können.

Timer gibt in einigen davon "einfach so", in anderen muss man auf 
Betriebssystemfunktionen zurückgreifen, und die können z.B. über die 
Windows-Messagefunktionen WM_TIMER versenden, oder per Callback eine von 
Dir definierte Funktion aufrufen.

Ohne weitere Details über Dein Programm zu kennen (Programmiersprache? 
Verwendete Klassenbibliothek o.ä., Konsol- oder Windows-Anwendung?) 
lässt sich mehr nicht zum Thema sagen.

von bluppdidupp (Gast)


Lesenswert?


von Georg (Gast)


Lesenswert?

Marr schrieb:
> Erreicht der Timer im Hintergrund
> zB 1000ms stoppt mein Programm..

Wenn du damit als Fehlerbehandlung zufrieden bist, Ok. In Windows gibt 
es Timer, die bei Ablauf ein Event auslösen. Entweder du nimmst den 
Timer selbst für den Timeout, oder zu zählst damit z.B. eine Variable 
Timeout jede 100 ms herunter. Beim Start und bei bei jedem erfolgreichen 
Empfang setzt du den Wert wieder auf den gewünschten Start-(Timeout-) 
Wert. Erreicht der Timer oder der Zähler Null, so ist das dein 
Timeout-Ereignis, und du kannst ein Fenster mit Fehlermeldung anzeigen 
oder das Programm ganz beenden oder was immer du willst.

Es ist keine schlechte Idee, den Timeout-Wert programmierbar zu machen.

Georg

von Marr (Gast)


Lesenswert?

Georg schrieb:
> Marr schrieb:
>> Erreicht der Timer im Hintergrund
>> zB 1000ms stoppt mein Programm..
>
> Wenn du damit als Fehlerbehandlung zufrieden bist, Ok. In Windows gibt
> es Timer, die bei Ablauf ein Event auslösen. Entweder du nimmst den
> Timer selbst für den Timeout, oder zu zählst damit z.B. eine Variable
> Timeout jede 100 ms herunter. Beim Start und bei bei jedem erfolgreichen
> Empfang setzt du den Wert wieder auf den gewünschten Start-(Timeout-)
> Wert. Erreicht der Timer oder der Zähler Null, so ist das dein
> Timeout-Ereignis, und du kannst ein Fenster mit Fehlermeldung anzeigen
> oder das Programm ganz beenden oder was immer du willst.
>
> Es ist keine schlechte Idee, den Timeout-Wert programmierbar zu machen.
>
> Georg

Joa so möcht ich das machen..
Im Hintergrund läuft ein Timer von 10000ms runter... Wenn der Wert 0 
passiert ist möchte ich darauf reagieren.. Mein Programm setzt den Wert 
jedesma auf 10000 zurrück wenn es durchgelaufen ist..
Das kann doch eig. nicht so schwierig ein oder?

Habt ihr ev. ein Beispielprogramm?

von Halbaktproduzent (Gast)


Lesenswert?

Marr schrieb:
> Joa so möcht ich das machen..

Was du möchtest: Zuerst mal den Beitrag von Rufus lesen und verstehen 
...

von Rainer V. (rudi994)


Lesenswert?


von Marr (Gast)


Lesenswert?

Programmiersprache ist C..
Es soll eine Konsolanwendung werden..

Gibt es da dein fertiges Programm?
Bin grad von morgens bis abends auf Montage und habe ehrlich gesagt 
wenig Zeit mich darein zu arbeiten..

Möchte einfach das nen Timer am Zyklusende (1000ms) zurrückgesetzt 
wird..
Passiert das nicht, soll etwas passieren..

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Marr schrieb:
> Programmiersprache ist C..
> Es soll eine Konsolanwendung werden..

Aha. Das sind ja schon mal klare Aussagen.

Dann ist für Dich die Win32-API die richtige Baustelle.

Mit der Funktion SetTimer kannst Du einen solchen Timer erzeugen. 
Diese Funktion ist zwar in erster Linie für die Fensterprogrammierung 
gedacht, kann aber auch in Konsolanwendungen genutzt werden.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx

Wie die Dokumentation beschreibt, kann diese Funktion auf vielfältige 
Weise verwendet werden; ich beschreibe Dir jetzt mal eine davon, nämlich 
den Gebrauch mit einer Rückruffunktion (Callback).
1
UINT_PTR WINAPI SetTimer(
2
  HWND hWnd,
3
  UINT_PTR nIDEvent,
4
  UINT uElapse,
5
  TIMERPROC lpTimerFunc
6
);

Der erste Parameter muss NULL sein; Du hast kein Fenster, und daher auch 
kein Fensterhandle. Auch der zweite Parameter sollte NULL sein, Du 
willst einen neuen Timer erzeugen. Wenn Du den Timer bereits erzeugt 
hast, ihn aber neu aufziehen willst, musst Du hier den Rückgabewert des 
vorhergehenden Aufrufs dieser Funktion angeben -- mehr dazu weiter 
unten.

Als dritter Parameter ist die Zeitdauer anzugeben, in Millisekunden.

Der vierte Parameter wiederum ist ein Funktionspointer. Hier gibst Du 
die Adresse einer Funktion an, die aufgerufen wird, wenn der Timer 
abgelaufen ist. Die Funktion muss den Aufrufkonventionen von TIMERPROC 
entsprechen, d.h. diesen Funktionsprototypen haben:
1
VOID CALLBACK TimerProc(
2
  HWND hwnd,
3
  UINT uMsg,
4
  UINT_PTR idEvent,
5
  DWORD dwTime
6
);

Der Name ist natürlich egal. Die der Funktion tatsächlich übergebenen 
Argumente sind bei Deiner Anwedung auch egal; entscheidend ist, daß die 
Funktion überhaupt aufgerufen wird -- was geschieht, wenn der Timer 
abgelaufen ist.

Wichtig aber ist, daß Du den Rückgabewert von SetTimer aufhebst. Den 
brauchst Du, wenn Du den Timer abbrechen willst, und der wird dafür 
Funktion KillTimer übergeben.

von Halbleiteravantgardist (Gast)


Lesenswert?

@Marr

Hast du dir "SetCommTimeouts" schon angesehen? Den Link hat bluppdidupp 
oben gepostet:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437%28v=vs.85%29.aspx

Hier auch noch ein paar Infos und etwas Code:
http://www.codeproject.com/Articles/3061/Creating-a-Serial-communication-on-Win

Zu Timern: Den gebräuchlichsten hat Rufus ja schon beschrieben; es 
existieren noch drei weitere Möglichkeiten (WinAPI), nämlich "Timer 
Queues", "Waitable Timer Objects" und "Multimedia Timers".

https://msdn.microsoft.com/de-de/library/windows/desktop/ms686796%28v=vs.85%29.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/ms687012%28v=vs.85%29.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/dd743609%28v=vs.85%29.aspx

"Multimedia Timers" soll man bei neuen Anwendungen allerdings nicht mehr 
verwenden.

Kurzbeschreibung der vier WinAPI-Timer:
http://www.codeproject.com/Articles/1236/Timers-Tutorial

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Halbleiteravantgardist schrieb:
> "Multimedia Timers" soll man bei neuen Anwendungen allerdings nicht mehr
> verwenden.

Warum? Und: Wer schreibt das?

von Jens (Gast)


Lesenswert?

Warum mit Kanonen auf Spatzen schießen?

VS ist .NET. Und das bietet eine Vielzahl von Funktionen auch für die 
serielle Schnittstelle an. Ich selber programmiere in VB, aber in C 
dürfte es die gleichen Funktionen geben, nur der Syntax ist anders. C 
ist allerdings kein Bestandteil von VS, vermutlich meinst du C#. Diese 
beiden Cs haben aber nichts miteinander zu tun.

Wenn ich etwas mit einem Timer laufen lassen will, starte ich einfach 
einen neuen Timer mit "meinTimer = New Timer". Im Timerevent zähle ich 
die für mich relevanten Hilfsvariablen hoch und mache die entsprechenden 
Auswertungen.

Serielle Schnittstelle geht aber noch einfacher. Entweder du setzt beim 
Programmstart die TimeOut-Bedingung und packst die Abfrage der 
Schnittstelle in einen Try-Catch-Block oder du fragst vorm Lesen der 
Daten von der Schnittstelle ab, ob es überhaupt was zu lesen gibt 
(myComPort.BytesToRead). Dritte Möglichkeit währe, dass du deiner 
seriellen Schnittstelle einen Event spendierst, der beim Empfang von 2 
Bytes auslöst. In der Event-Behandlungsroutine liest du dann die zwei 
Byte aus und machst die Auswertung. Möglickeit 4, 5 und 6 spare ich mir 
jetzt mal...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Jens schrieb:
> VS ist .NET.

Nein. VS enthält auch das .Net-Geraffel, aber auch einen echten C++- 
und C-Compiler.

Der C-Compiler ist etwas angestaubt, da er hartnäckig nur C89 
unterstützt, der C++-Compiler hingegen ist vorzüglich.

: Bearbeitet durch User
von Jens (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Nein. VS enthält auch das .Net-Geraffel, aber auch einen echten C++-
> und C-Compiler.

Oh, das ist mir neu. Aber von mir aus soll der TE sich mit seinem C 
abquälen während ich mit ein paar Zeilen in Visual Basic des ach so 
verpönten .Net zum Ergebnis komme. Beispiele siehe oben.

von Borislav B. (boris_b)


Lesenswert?

Rufus Τ. Firefly schrieb:
> der C++-Compiler hingegen ist vorzüglich.

Unterstützt ja nicht mal C++11 bzw. 17 vernünftig.
Dann lieber GCC.

Ansonsten ist für so ein Projekt .NET deutlich besser geeignet. Mit 
C/C++ tut man sich da keinen Gefallen...

von Halbwacher (Gast)


Lesenswert?

Rufus ?. Firefly schrieb:
>> "Multimedia Timers" soll man bei neuen Anwendungen allerdings nicht mehr
>> verwenden.
>
> Warum?

Weil es Probleme mit PulseEvent geben kann (und timeSetEvent PulseEvent 
verwendet).

> Und: Wer schreibt das?

Microsoft:
https://msdn.microsoft.com/en-us/library/dd757634%28v=vs.85%29.aspx

Indirekt deswegen:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684914%28v=vs.85%29.aspx

Siehe auch
http://blogs.msdn.com/b/larryosterman/archive/2005/09/08/462477.aspx
(Larry Osterman gehörte zum Team, das die API enwickelt hat)

@Marr

Hier ist auch noch etwas zur seriellen Schnittstelle und Timeouts:
http://www.codeproject.com/Articles/8860/Non-Overlapped-Serial-Port-Communication-using-Win

@Jens

>> VS enthält auch das .Net-Geraffel, aber auch einen echten C++-
>> und C-Compiler.
> Oh, das ist mir neu.

Visual Studio gab es schon lange vor .NET; erst in VS 2002 ist .NET 
dazugekommen.

> Aber von mir aus soll der TE sich mit seinem C
> abquälen während ich mit ein paar Zeilen in Visual Basic des ach so
> verpönten .Net zum Ergebnis komme.

Da Marr vermutlich nicht viel Erfahrung mit der WinAPI und offenbar auch 
wenig Zeit hat, ist das nicht so abwegig. Falls es doch mal unter Linux 
laufen soll: Auch in Mono gibt es "SerialPort". Wobei ich wegen der 
Syntax - falls der TO schon länger in C programmiert - und der größeren 
Anzahl von Beispielen im Netz eher C# empfehlen würde.

von Jens (Gast)


Lesenswert?

Halbwacher schrieb:
> Visual Studio gab es schon lange vor .NET; erst in VS 2002 ist .NET
> dazugekommen.

Wenn ich mich recht erinnere, gab es Funktionen für die serielle 
Schnittstelle schon in den frühen Versionen von VB, noch ohne .NET.

Was ich eigentlich damit sagen will, dass es in den meisten 
Programmiersprachen umfangreiche Funktionssammlungen aka. Framework 
gibt, die solche Sachen wesentlich vereinfachen. Zur Not gibt es meist 
auch ein OS-API. Ich denke mal, dass es Funktionen, welche die Anzahl 
von Bytes im Empfangspuffer zurückgeben auch in C++ oder was auch immer 
gibt. Damit dürfte der TE am schnellsten zum Ziel kommen.

von Halbmeterbreiter (Gast)


Lesenswert?

Jens schrieb:
> Wenn ich mich recht erinnere, gab es Funktionen für die serielle
> Schnittstelle schon in den frühen Versionen von VB, noch ohne .NET.

Ja, richtig. Über COM (MSCOMM32.OCX, glaube ich).

> Ich denke mal, dass es Funktionen, welche die Anzahl
> von Bytes im Empfangspuffer zurückgeben auch in C++ oder was auch immer
> gibt.

In C++ bzw. der Standardbibliothek und der STL nicht, da es 
systemabhängig ist, aber es existieren entsprechende Bibliotheken, z.B. 
Boost.Asio (boost::asio::serial_port).

von uwe (Gast)


Lesenswert?

Wenn er nen blockierenden ReadFile macht dann nützt ihm nen timer auch 
nichts. Die Timeouts der Comm Funktionen nutzen sollte die angestrebte 
Lösung sein.

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.