Hallo Zusammen,
ich bin neu in der MC-Programmierung mit MSP430 und CCS und war schon
ca. 10Jahre nicht mehr auf dieser Seite - also alles vergessen was mit
MC zu tun hat... :-)
Wollte ein LED im Sekundentakt blinken lassen, diese Sekunde solle mir
ein Interrupt zählen.
Leider blinkt nur das LED, das im Interrupt getoggelt wird, nicht das
LED, das in der while(1) getoggelt wird.
Kann mir jemand sagen, warum?
Grüße,
Alfred
Abgesehen von dem nicht-atomischen Abfragen und Rücksetzen von
Do_1s_Action, was hier aber nicht das primäre Problem sein sollte,
sollte das eigentlich funktionieren.
Wenn alle verwickelten Fehler ausgeschlossenen sind, muss es ein
trivialer Fehler sein.
Wenn du vor der Schleife P1OUT BIT0 auf 0 setzt, bleibt dann die LED
aus?
Vielen Dank für Eure schnellen Antworten!
Leider hatte ich bis jetzt keinen Erfolg... :-(
@Irgend W.:
Was genau habe ich falsch gemacht? Habe ich volatile falsch angewandt?
@ MaWin :
"nicht atomisch"?
Ein Kommentar schrieb:> Wenn alle verwickelten Fehler ausgeschlossenen sind, muss es ein> trivialer Fehler sein.>> Wenn du vor der Schleife P1OUT BIT0 auf 0 setzt, bleibt dann die LED> aus?
Nein, die LED ist immer an! Sowohl wenn ich Bit0 vor while(1) oder auch
innerhalb while(1) schreibe... wie kann das sein?
Grüße,
Alfred
Alfred schrieb:> @ MaWin :> "nicht atomisch"?
Der Interrupt kann (theoretisch) zwischen der Hauptschleifen-Abfrage des
Flags und dem Hauptschleifen-Rücksetzen des Flags ausgeführt werden.
Damit würde ein Setzen des Flags im Interrupt verloren gehen.
Allerdings wird das bei dir hier in diesem speziellen Fall aufgrund des
langsamen Timings nicht passieren.
Alfred schrieb:> Nein, die LED ist immer an! Sowohl wenn ich Bit0 vor while(1) oder auch> innerhalb while(1) schreibe... wie kann das sein?
Ich würde einmal sagen du hast ein elektrisches Problem, oder dein
Controller muss noch besonders konfiguriert werden zur Verwendung dieses
Pins.
Tausche doch einmal Bit 0 und 6 in Hauptschleife und Interrupt.
Ach und:
Ist BIT0 und BIT6 überhaupt eine Bitmaske? Oder ist es eine Bitnummer?
Wenn es eine Bitnummer ist, dann musst du so schreiben:
xxx ^= 1 << BIT0
xxx ^= 1 << BIT6
Alfred schrieb:> Nein, die LED ist immer an! Sowohl wenn ich Bit0 vor while(1) oder auch> innerhalb while(1) schreibe... wie kann das sein?>> Grüße,
Hat die LED jemals gblinkt? Ist die wirklich richtig angeschlossen? Dein
Code sieht OK aus, auch volatile ist drin, passt.
Lass mal die LED ohne ISR blinken, einfach mit old school delay.
Hi MaWin,
nochmal danke für Deine schnelle Reaktion!
Ich konnte das Problem lösen, indem ich das LPM0_bits nicht mehr
schreibe (Zeile 22), jetzt geht alles wie gewünscht, hat was mit dem
LowPower-Mode zu tun - muss ich nachher mal genauer nachlesen... (habs
nur durch ausprobieren rausbekommen).
MaWin O. schrieb:> Alfred schrieb:>> @ MaWin :>> "nicht atomisch"?>> Der Interrupt kann (theoretisch) zwischen der Hauptschleifen-Abfrage des> Flags und dem Hauptschleifen-Rücksetzen des Flags ausgeführt werden.> Damit würde ein Setzen des Flags im Interrupt verloren gehen.> Allerdings wird das bei dir hier in diesem speziellen Fall aufgrund des> langsamen Timings nicht passieren.
Das ist ein interessanter Aspekt! Hättest Du spontan ein Beispiel für
mich, wie diesen Effekt umgehen kann? (Ich möchte ja ein längeres
Programm schreiben, als nur eine LED blinken zu lassen ;-))
Grüße,
Alfred
Hi Falk,
ja, das hatte ich auch probiert, ging auch nicht!
Dachte mir: das kann nicht sein!
Dann hatte ich den global interrupt deaktiviert, braucht man dann ja
nicht -> dann gings!
...so bin auch auf die Lösung mit LPMO gekommen...
Danke Dir trotzdem!
Alfred schrieb:> nochmal danke für Deine schnelle Reaktion!>> Ich konnte das Problem lösen, indem ich das LPM0_bits nicht mehr> schreibe (Zeile 22), jetzt geht alles wie gewünscht, hat was mit dem> LowPower-Mode zu tun - muss ich nachher mal genauer nachlesen... (habs> nur durch ausprobieren rausbekommen).
Das ist eine Besonderheit beim MSP430. Der kann in einem der LPMs
arbeiten, eine ISR ausführen und bei deren Verlassen den automatisch
wieder einschalten, sodaß die Hauptschleife NIE ausgeführt wird! Will
man das nicht, muss man in der ISR die LPM-Bits ausschalten. Frag mich
jetzt aber nicht wie das genau geht, hab ich vor 15 Jahren das letzte
Mal gemacht 8-0
>> Der Interrupt kann (theoretisch) zwischen der Hauptschleifen-Abfrage des>> Flags und dem Hauptschleifen-Rücksetzen des Flags ausgeführt werden.
Auch praktisch.
>> Damit würde ein Setzen des Flags im Interrupt verloren gehen.
Nö. Denn das Löschen erfolgt NUR bei vorher erkanntem Flag!
>> Allerdings wird das bei dir hier in diesem speziellen Fall aufgrund des>> langsamen Timings nicht passieren.> Das ist ein interessanter Aspekt!
Nö, es ist ein Irrtum.
> Hättest Du spontan ein Beispiel für> mich, wie diesen Effekt umgehen kann? (Ich möchte ja ein längeres> Programm schreiben, als nur eine LED blinken zu lassen ;-))
Man kann das Löschen das Flags am Ende der Abarbeitung von Funktionen
nutzen, ob das Timing schnell genug ist.
https://www.mikrocontroller.net/articles/Multitasking#Verbesserter_Ansatz_mit_Timer
Falk B. schrieb:> Nö. Denn das Löschen erfolgt NUR bei vorher erkanntem Flag!>>>> Allerdings wird das bei dir hier in diesem speziellen Fall aufgrund des>>> langsamen Timings nicht passieren.>>> Das ist ein interessanter Aspekt!>> Nö, es ist ein Irrtum.
Ach komm Falk.
Rede keinen Unsinn.
Es könnte ein Flagsetzen verloren gehen. Das wird in diesem Konkreten
Fall nur verhindert, weil das Setzen eine sehr langsame Periode hat und
in dieser Zeit die Hauptschleife den kritischen Bereich sicher verlassen
wird.
Alfred schrieb:> Hättest Du spontan ein Beispiel für> mich, wie diesen Effekt umgehen kann?
Deaktivieren der Interrupts vor Abfrage und Re-aktivierung der
Interrupts nach Abfrage + Rücksetzen des Flags.
MaWin O. schrieb:>> Nö, es ist ein Irrtum.>> Ach komm Falk.> Rede keinen Unsinn.
Eben. Das tue ich nicht ;-)
> Es könnte ein Flagsetzen verloren gehen.
Ach sooo, jetzt verstehe ich. Ja, könnte. Ist aber wie bei JEDEM
Interrupt! Wenn die Beantwortung zu lange dauert, werden diese
verschluckt.
> Das wird in diesem Konkreten> Fall nur verhindert, weil das Setzen eine sehr langsame Periode hat und> in dieser Zeit die Hauptschleife den kritischen Bereich sicher verlassen> wird.
Stimmt.
> Deaktivieren der Interrupts vor Abfrage und Re-aktivierung der> Interrupts nach Abfrage + Rücksetzen des Flags.
Das löst das Problem nicht wirklich. Denn auch hier kann eine zu lange
Bearbeitungszeit dazu führen, daß eben die Periodendauer des Timers
überschritten wird. Und dann verhindert man mit der ISR-Sperre die
Ausführung der ISR. OK, EINMAL funktioniert der Trick, aber wenn die
Zeit NOCH länger wird, schon nicht mehr.
Alles in allem MUSS man durch Simulation oder Messung sicher stellen,
daß die Funktionen zwischen Erkennen des ISR-Flags und dem Löschen
SICHER kleiner als die Timerperiode ist. Man kann das Flag auch gleich
nach dem Erkennen löschen. Aber auch dann muss die Bearbeitung von
wasauchimmer() so kurz sein, daß die nächste Abfrage des Flag das erneut
gesetzte Flag erkennt und nicht mehrere Timerdurchläufe überspringt!
Steht alles seit Ewigkeiten im Artikel Interrupt.
https://www.mikrocontroller.net/articles/Interrupt#Zusammenfassung
Falk B. schrieb:> Denn auch hier kann eine zu lange> Bearbeitungszeit dazu führen
Völlig richtig. Ich wollte hier lediglich in einem Nebensatz auf ein
Problem hinweisen und nicht das Problem vollumfänglich lösen. (Man
könnte zum Beispiel zählen statt Flag setzen).