Hallo, ich hab ein kleines Problem und ich komme nicht darauf wovon es kommt. Den Code zu posten würde denk ich keinen Sinn machen da das Programm zu umfangreich ist. Es geht um folgendes: Ein Timer1 löst alle 1ms eine ISR aus: In dieser ISR ist ein counter, der bis 1000zählt. Ist der Counter 1000 wird mein 2x16 Display upgedated. So, nun baue ich mein Hexfile (auf einem ATMEGA32) und spiele es drauf. Das Programm läuft zu 100% fehlerfrei. Wenn ich nun ein anderes mal baue und das programm lade/starte läuft es zu 90%. Die funktionalität ist komplett gegeben. Allerdings Zeigt dass Display ca. alle 10s etwas falsches an (nur bis zu nächsten update in 1s). Bsp.1: (sende string an lcd function) aus: "Decontamination end " wird "mination nation end " . Bsp.2: (sende integer an lcd function) aus: "Operating hours" (zeile 1 ohne fehler / string function) "0" oder "255" statt (zeile 2 /int function) "33" Also irgendwie scheint wohl was durcheinander zu laufen, Aber ich weiß nicht wo. Denn die update lcd function wird nur jede sekunde aufgerufen, also was soll da schief laufen? Das LCD benutzt einen anderen Timer. Ich weiß dass es recht wenig informationen sind, allerdings möchte ich auch keinen fertigen Quellcode, sondern nur eine Richtung wie ich den Fehler (was wohl ein Timingfehler ist) eingrenzen kann. Gruß
Was ist das für ein Display? Frägst du das Busy-Flag ab bevor du sendest? Du musst auch das Timing des Displays generell beachten, mache an ein paar Stellen testweise(!) einfach mal kurze Wartezeiten rein und schaue ob es sich dann bessert.
Die sollten aber schon reichen. Also wenn Du das Display asynchron zur Datenerfassung betreibst, dann muß du Semaphoren nutzen. Sprich, wenn Dein Erfassungsalgorithmus alle 1ms sprich 1000 in der Sekunde einen String erstellt, den das arme Display ausgeben soll, kotzt es irgendwann mal ab oder mit andern Worten ist einfach noch nicht mit dem lezten Job fertig. Das würde Andreas schrieb: > "Decontamination end " wird > > "mination nation end " . erklären. Als sofortmassnahme solltest Du mal die 1ms auf 100ms hochschrauben und schauen, ob dann dieser Fehler auftritt. Wenn nein, dann muß Du mit Ausgabepuffern arbeiten. Ich habe mir für das LC-Display eine Serviceroutine geschrieben, die im Leerlauf while(1){Arbeitejobs ab...} läuft. LC_Print() ist die Schnittstelle und liefert false, wenn der Puffer voll und noch nicht abgearbeitet ist. Als zweite Massnahme solltest Du mal überprüfen, ob nur Teile der Strings aktualisiert werden müssen. Das spart Ausführungszeit. Temperatur: xxx -> Temperatur nur zur Ini oder Modiwechsel einmal ausgeben und xxx den Wert also, so oft aktualisieren, wie Du es für notwendig hälst. Aber ein 1ms- Task ist schon heftig. Ist die wirklich notwendig? Oder willst Du nur wissen, was geht?
Das display Treiber ist ein HD44780 2x16. Es hat (natürlich) nichts mit dem bauen/draufladen zu tun. Hatte grad den Fehler im Programm drin, durch ab und zu schalten von der Versorgung des Boards funktioniert es jetzt einwandfrei. Kommt also eher drauf an, wann welcher button gedrückt wird, und dieser "schlägt" wohl in die Display routine. Ob das busyflag ausgelesen wird kann ich nicht sagen, da lib nicht von mir, aber ich schaue mal rein. Wäre es eine alternative (sicher nicht perfekt) während das Display sendet (in string und int function) die globalen interrupts zu sperren und dann wieder freizugeben (also am anfang und ende jeder funktion)?
Man kann nicht von 2 verschiedenen Funktionen auf ein Stream-Device zugreifen, wenn eine die andere unterbrechen kann. Durch das Unterbrechen wird der gerade laufende Stream zerstückelt. - LCD nur im Main: geht - LCD nur im Interrupt: geht - LCD im Main und Interrupt: verboten! Peter
Wenn Du im LCD-Timerinterrupt die Zeile ausgibst könnte es klappen, dass der andere Interrupt nicht unterbricht. Wenn der Ausfall dieser Erfassung Dir nicht weh tut, mach es...
Das könnte die richtige Richtung sein Peter! Wie gesagt das LCD wird per ISR alle sekunde upgedated. Allerdings möchte ich es auch beim Druck von bestimmten Buttons aus aktualisieren. Beispielsweise wenn ich den Button (switch display) drücke möchte ich dass sich das Display SOFORT updated - fernab vom Interrupt. Mal schauen wie ich das umstricken kann. Jedenfalls konnte ich so durch die Bedienung im Programm den Fehler bannen, bzw. mal reproduzieren.
das für mich naheliegendste verfahren wäre dann, eine task/funktion zu haben, die exklusiv das display ansteuert, und ihre daten eben aus den beiden anderen tasks/funktionen, zb per ringbuffer, bezieht... mfg
Als elegante Lösung kann man einen Timerinterrupt aufsetzen, der z.B. alle 1ms ein Byte aus nem Puffer ausgibt. Und alle Ausgabefunktionen schreiben nur in diesen Puffer. Wenn sie an verschiedene Adressen des Puffers schreiben, kommen sie sich nicht in die Quere. Als angenehmen Nebeneffekt hat man auch keine Verzögerungen durch das langsame LCD mehr. Z.B.: Beitrag "Formatierte Zahlenausgabe in C" Peter
Andreas schrieb: > Beispielsweise wenn ich den Button (switch display) drücke möchte ich > dass sich das Display SOFORT updated - fernab vom Interrupt. > > Mal schauen wie ich das umstricken kann. Verlege doch einfach die Displayausgaberoutine aus dem Interruptservice in die Hauptprogrammschleife. Deine Interrupt-Service-Routine setzt dann einfach nur eine globale Flag-Variable, um eine Ausgabe anzufordern, wenn wieder eine Sekunde abgelaufen ist. Die Displayroutine macht nur bei gesetztem Flag die Ausgabe und löscht das Flag wieder. Bei einem Druck auf einen der Buttons, setzt Du auch das Flag oder machst direkt eine entsprechende Displayausgabe, das wäre ja nun auch möglich, da keine konkurrierende Displayausgabe mehr im Interrupt erfolgt. Gruß, Thorsten
Andreas schrieb: > Das Programm läuft zu 100% fehlerfrei. Das möchte ich mal von meinen Programmen auch behaupten können. Aber damit hättest du eine große Sorge weniger, und das Problem kann ja nur noch in der Hardware sein. Glaubst du das? > allerdings möchte ich auch keinen fertigen Quellcode Du könntest allerdings DEINEN posten. Aber der kanns ja nicht sein...
Thorsten S. schrieb: > Andreas schrieb: > >> Beispielsweise wenn ich den Button (switch display) drücke möchte ich >> dass sich das Display SOFORT updated - fernab vom Interrupt. >> >> Mal schauen wie ich das umstricken kann. > > Verlege doch einfach die Displayausgaberoutine aus dem Interruptservice > in die Hauptprogrammschleife. > Deine Interrupt-Service-Routine setzt dann einfach nur eine globale > Flag-Variable, um eine Ausgabe anzufordern, wenn wieder eine Sekunde > abgelaufen ist. > > Die Displayroutine macht nur bei gesetztem Flag die Ausgabe und löscht > das Flag wieder. > > Bei einem Druck auf einen der Buttons, setzt Du auch das Flag oder > machst direkt eine entsprechende Displayausgabe, das wäre ja nun auch > möglich, da keine konkurrierende Displayausgabe mehr im Interrupt > erfolgt. > > Gruß, > Thorsten Gute Idee! Genau die selbe hatte ich beim Hochfahren des PCs heute morgen auch. Trotzdem vielen vielen Dank! Mit dem Flag das alle s in der ISR gesetzt wird fühle ich mich auch um einiges wohler als in der ISR direkt das Display zu aktualisieren. Merci, und einen schönen Tag noch!
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.