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
"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.
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
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?
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..
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_PTRWINAPISetTimer(
2
HWNDhWnd,
3
UINT_PTRnIDEvent,
4
UINTuElapse,
5
TIMERPROClpTimerFunc
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
VOIDCALLBACKTimerProc(
2
HWNDhwnd,
3
UINTuMsg,
4
UINT_PTRidEvent,
5
DWORDdwTime
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.
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...
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.
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.
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...
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.
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.
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).
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.