Softwarertimer Windows Visual Studio

Gast #4001639
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
Persönliche Seite #4001764
"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.
Gast #4002708
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
Gast #4002984
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?
Gast #4003138
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..
Persönliche Seite #4003343
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.
Gast #4003387
@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
Gast #4003625
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...
Gast #4003645
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.
Gast #4003727
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.
Gast #4003752
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.
Gast #4003785
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).
Gast #4005096
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.