Abend Kollegen ;) Ich möchte in meinem Programm etwa 1 Sekunde warten. Dazu nehme ich meine for-Schleife "for(i=0; i<Endwert; i++)". Den richtigen Endwert will ich dann durch ausprobieren herausfinden. Mein Chef meinte aber das ist keine gute Idee. Was meint ihr könnte den hier schief gehen? Gruß Bernie
Berni S. schrieb: > Abend Kollegen ;) > > Ich möchte in meinem Programm etwa 1 Sekunde warten. Dazu nehme ich > meine for-Schleife "for(i=0; i<Endwert; i++)". > > Den richtigen Endwert will ich dann durch ausprobieren herausfinden. > Mein Chef meinte aber das ist keine gute Idee. > > Was meint ihr könnte den hier schief gehen? > > Gruß > Bernie Dein Chef hat recht... Der µC, PC oder was auch immer bleibt ausschließlich in dieser Schleife, die ganze Sekunde lang, und der restliche Prozessor ist nun ausschließlich damit beschäftigt und kann keine weiteren Aufgaben mehr erledigen. Desweiteren, unterbricht ein Interrupt diese Schleife - dann stimmt dein "händisch" Zählen nicht mehr und dein Timing ist dahin. Richtig macht man sowas mit einem Timer oder einem Pseudo-Threading.
Berni S. schrieb: > Was meint ihr könnte den hier schief gehen? Ohne Kontext vieles und gar nichts. Bei einem Raketenabwehrsystem bedeutet eine Sekunde nichts tun, also wirklich GAR NICHTS, weil es gerade eine variable hochzählen muss, vielleicht den Tod. Bei einer elektronischen Grußkarte wäre es wohl verschmerzbar.
Berni S. schrieb: > Ich möchte in meinem Programm etwa 1 Sekunde warten. Das Programm ist für welche Zielplattform?
> Der Compiler wird dir das sowieso rausschmeißen. Eben erst: Beitrag "AVR Studio 6 und 7 stoppen nicht im Simulator beim debuggen"
Berni S. schrieb: > Ich möchte in meinem Programm etwa 1 Sekunde warten. Wenn das komplette Programm eine ganze Sekunde wirklich nur warten soll, kannst du die CPU schlafenlegen und damit Strom sparen. Die meisten Mikrocontroller bieten diese Möglichkeit und ebenso einen Timer, der als "Wecker" konfiguriert die CPU nach einer vorgegenen Zeitdauer wieder aufweckt. Führt die CPU während der Wartezeit interruptgesteuert noch andere Dinge im Hindergrund aus, ist die Warteschleife ebenfalls eine schlechte Lösung, weil die Zeit für ihre Abarbeitung vom Rechenaufwand für die Hindergrundaktivitäten abhängt.
Wenn du ein Programm erstellen willst, dass nur ein wenig zeitbezogen arbeiten soll, dann lässt du in einer Timer-Interrupt-Service-Routine z.B. alle 10 ms eine Variable COUNT_10MS hochzählen. In dieser Routine - prüfst du, ob Tasten für eine Mindestzeit gedrückt, oder losgelassen wurden (Entprellung...) und vermerkst das in zugeordneten Variablen. - prüfst du, ob irgendwelche regelmäßigen Aktionen (Update der Anzeige, ...) an der Reihe sind, was in zugeordneten Variablen dem Hauptprogramm gemeldet wird. - zählst du Warte-Variablen, solange sie größer NULL sind, um 1 herunter. Das Hauptprogramm besteht aus einer Schleife, in der diese zugeordneten Variablen abgefragt werden und reagiert dann entsprechend. Wenn eine Aktion in 1 s erforderlich ist, setzt du eine Warte-Variable auf 100 (100 x 10 ms = 1s). In der Schleife des Hauptprogramms schaust du regelmäßig nach, ob diese Warte-Variable schon NULL geworden ist. In der Zwischenzeit kann der µC weiterhin alles andere schön abarbeiten...
Jacko schrieb: > Wenn du ein Programm erstellen willst, dass nur ein wenig > zeitbezogen arbeiten soll, dann lässt du in einer > Timer-Interrupt-Service-Routine z.B. alle 10 ms eine > Variable COUNT_10MS hochzählen. > > In dieser Routine > - prüfst du, ob Tasten für eine Mindestzeit gedrückt, oder > losgelassen wurden (Entprellung...) und vermerkst das in > zugeordneten Variablen. > - prüfst du, ob irgendwelche regelmäßigen Aktionen (Update > der Anzeige, ...) an der Reihe sind, was in zugeordneten > Variablen dem Hauptprogramm gemeldet wird. > - zählst du Warte-Variablen, solange sie größer NULL sind, > um 1 herunter. >. > Das Hauptprogramm besteht aus einer Schleife, in der diese > zugeordneten Variablen abgefragt werden und reagiert dann > entsprechend. . > Wenn eine Aktion in 1 s erforderlich ist, setzt du eine > Warte-Variable auf 100 (100 x 10 ms = 1s). . > In der Schleife des Hauptprogramms schaust du regelmäßig > nach, ob diese Warte-Variable schon NULL geworden ist. > In der Zwischenzeit kann der µC weiterhin alles andere > schön abarbeiten... Und um Folgefragen gleich zu beantworten, die Variable WDR so definiert:
1 | unsigned volatile count_MS; |
damit der Compiler auf die Idee kommt, den Wert jedesmal neu lesen zu müssen.
Wenn Du kompletter Anfänger wärest und Du die Schleife für irgendwas zum ausprobieren brauchst, so wäre das mal kurzfristig vielleicht ok. Da Du aber mit Deinem "Chef" darüber sprichst ... bist Du als Programmierer oder gar Entwickler angestellt? Dann wäre es höchste Zeit, mehr über Deine Kenntnisse zu schreiben um an den Basics zu arbeiten. Auf dem Niveau wirst Du einem Ansatz mit timer und Interrupt vermutlich nicht direkt folgen können. Ich hoffe daher, Du machste ein Praktikum. Aber auch dann ist es hilfreich zu wissen, was Du schon kannst und was Du erforschst, um Dich nicht zu über- oder zu unterfordern.
Das war schon 1980 Murks, als viele Spiele u.a. Tetris und auch der MS Flugsimulator auf der nächst schnelleren Kiste (z.B. AT) nicht mehr nutzbar waren. Schnell die nächste Rasperry Pi Generation oder ein Prozessor mit höherem Takt eingesetzt und deine "tu nichts" Schleife stimmt nicht mehr. So gut wie jedes System bietet hierzu einen Timer, den du setzen und abfragen kannst, wann deine Sekunde abgelaufen ist. Stöber mal zu deinem Prozessor im Internet, sollte sich etwas finden. Mit freundlichen Grüßen Christian
Berni S. schrieb: > Ich möchte in meinem Programm etwa 1 Sekunde warten. Dazu nehme ich > meine for-Schleife "for(i=0; i<Endwert; i++)". eine typische Anfänger-"Lösung" > Den richtigen Endwert will ich dann durch ausprobieren herausfinden. > Mein Chef meinte aber das ist keine gute Idee. Da hat er recht. Und er hätte auch dann Recht, wenn er nicht dein Chef wäre. > Was meint ihr könnte den hier schief gehen? Das ist nicht unbedingt der Punkt. Auch ohne daß etwas wirklich "schief geht" ist es trotzdem aus vielerlei Gründen eine blöde Idee: 1. die Schleife muß kalibriert werden. Das ist ein zusätzlicher Arbeitsschritt. 2. die Kalibrierung stimmt dann aber nur für a) diesen µC bei b) dieser Taktfrequenz und c) diesen Compiler mit d) diesen Optimierungseinstellungen. a) Portierbarkeit auf einen anderen µC ist nicht gegeben. Stell dir vor, der µC wird in ein paar Jahren abgekündigt und das Produkt muß auf einen anderen µC umgestellt werden. Fängst du wieder bei 1. an. b) je nachdem wie genau deine Verzögerung sein muß, ist vielleicht sogar schon die Abweichung der Taktfrequenz zu groß. c) einen neuen Compiler kannst du schnell mal kriegen, z.B. weil die neue Version einen lästigen Bug fixt. Wenn du ein Betriebssystem mit automatischen Updates nutzt, merkst du das womöglich gar nicht gleich. Oder stell dir mal vor, in 10 Jahren soll an dem Produkt noch was geändert werden, aber der alte Compiler ist nicht mehr aufzutreiben. d) genau genommen würde ich von jedem halbwegs aktuellen Compiler erwarten, daß er die Schleife komplett wegoptimiert - es sei denn du hast die Optimierung ausgeschaltet. Allerdings beobachte ich in der Praxis eher das Gegenteil: das Programm wird im Laufe der Entwicklung immer langsamer und die Entwickler drehen als erstes mal die Optimierung im Compiler hoch. Und bumms - schon stimmt deine tolle Schleife nicht mehr. 3. während dieses busy waiting (das ist der Fachbegriff) verbraucht dein µC das Maximum an Strom um - nichts zu tun. Wobei: stimmt nicht. Er tut nicht "nichts", sondern er rennt vollkommen sinnlos im Kreis. Insbesondere kann er während dieser Zeit auch nichts sinnvolles tun. Das ist wie wenn du während des Wartens auf den Geschirrspüler die ganze Zeit etwas sinnloses tun würdest. Sagen wir: den Geschirrschrank immer wieder aus- und wieder einräumen. Eine ganze Stunde lang, bis der Geschirrspüler fertig ist. Käme dir das sinnvoll vor? Würdest du die ZEit nicht lieber für eine sinnvolle Arbeit verwenden? Oder, wenn du partout nichts zu tun hast, ein Nickerchen auf der Couch machen? Der korrekte Weg, eine Verzögerung zu implementieren, nutzt einen der (meist vielen) Timer im µC. Das ist ein Hardware-Zähler, der einen (konfigurierbaren) Takt zählt und bei einem (konfigurierbaren) Zählerstand oder beim Überlauf einen Interrupt auslöst. Das funktioniert vollkommen in Hardware, unabhängig davon was der µC gerade tut (insbesondere auch, wenn er in einen Stromsparmodus versetzt wurde) und mit hoher Genauigkeit. Wenn man dem Timer nicht gleich seinen eigenen, unabhängigen Takt gibt, z.B. von einem Uhrenquarz, dann kennt man den Takt zumindest und muß im Fall des Falles nur eine Konstante im Programm ändern. PS: zu 2. gibt es eine nette Anekdote. Die Programmierer bei Borland wollten besonders schlau sein und haben in Turbo Pascal eine automatische Kalibrierung ihrer Verzögerungsschleife eingebaut. Dazu haben sie den System-Timer ausgelesen (der zählt alle 55ms um 1 hoch), dann die Schleife mit 1 Million [1] Durchläufen rennen lassen und den System-Timer wieder ausgelesen. Aus der vergangenen Zeit (Differenz Timerwerte mal 55ms) konnten sie dann ausrechnen, wieviel Schleifendurchläufe sie für eine bestimmte Zeit brauchten. Blöderweise wurde die PC irgendwann so schnell, daß sie die Schleife in weniger als 55ms schafften. Die beiden Timerwerte waren gleich und bei der Berechnung kriegte man einen "Division durch Null" Fehler (gerade nochmal nachgegoogled: "runtime error 200" war das). Das nur zur Warnung, falls du diese Idee auch hattest. [1] 1 Million ist ein Beispiel. Ich weiß nicht wieviele Zyklen sie wirklich gemacht haben. Ist auch nicht von Belang. Es war halt eine Zahl, bei der sie eine Verzögerung im Bereich von maximal einer Sekunde erwartet haben.
:
Bearbeitet durch User
Borland..."runtime error 200" war das. Wie habe ich den gehasst! Ich musste einige uralte Programme von längst verschollenen Autoren auf aktuelle Frameworks umschreiben und neu compilieren - denn ein Bugfix von Borland war Monate zu spät verfügbar. Das war für mich auch die letzte Arbeit mit Borland Produkten.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.