Hallo Community, LED's per µC zum leuchten zu bringen ist ja kein Ding. Jetzt wollte ich sie interruptgestuert steuern, da ich delay nicht verwenden möchte, bzw. nicht kann (mein Programm ist hauptsächlich interruptgestuert). Der Code soll ja nicht für ms immer angehalten werden. Normalerweise hab ich mir gedacht das bei bestimmten Ereignisen, wo die LED's leuchten sollen, ein Timerinterrupt auslöst. Die LED leuchtet für 500ms und dann gehts sie wieder aus und die Timer-ISR ist zu ende. So jetzt hab ich das Problem das ich mehrere LED's ansteuern möchte. Für ein entsprechendes Erreignis leuchtet die entsprechende Diode auf. Zur zeit sind es 3 Zustände, später werden es mehr. Wie kann ich jetzt die Timer-ISR etsprechend der 3 verschiedenen Zustände starten? Ein Controller hat doch meistens nicht so viele Timer, oder? Oder gibts es eine andere Möglichkeit der LED ansteuerung ohne delay? Achja: Die Ereignise laufen nicht nach einem Schema ab, sodass ich einen Zähler von 1-3 laufenlassen könnte und dann entsprechend der Zahl die LED's aufleuchten lasse. Danek im vorraus
3 Zähler in einer Timer-ISR sollten Deinen Bedingungen genügen. In dem Hauptprogramm setzt Du den Zähler (z.B. auf 100 für 500 msec), in der ISR zählst Du ihn runter. Wenn er auf 0 ist, schaltest Du die LED ab. Wenn Du die 3 Zähler als Array realisierst, kannst Du das schnell auf 5,7,usw. LEDs erweitern.
@ Rafi Dafi (alexanderw) >LED's per µC zum leuchten zu bringen ist ja kein Ding. Jetzt wollte ich >sie interruptgestuert steuern, da ich delay nicht verwenden möchte, Gute Einstellung. >LED's leuchten sollen, ein Timerinterrupt auslöst. Die LED leuchtet für >500ms und dann gehts sie wieder aus und die Timer-ISR ist zu ende. Fast. >Wie kann ich jetzt die Timer-ISR etsprechend der 3 verschiedenen >Zustände starten? Ein Controller hat doch meistens nicht so viele Timer, >oder? Wozu auch. Alles was du brauchst ist EIN Timer und eine statemachine. >Achja: Die Ereignise laufen nicht nach einem Schema ab, sodass ich einen >Zähler von 1-3 laufenlassen könnte und dann entsprechend der Zahl die >LED's aufleuchten lasse. Jedes noch so merkwürdige Schema ist mit einer statemachine sehr einfach umsetzbar. Ist am Ende eine einfache Tabelle, wo man reinschreibt was man haben möchte.
Rafi Dafi schrieb: > Normalerweise hab ich mir gedacht das bei bestimmten Ereignisen, wo die > LED's leuchten sollen, ein Timerinterrupt auslöst. Hier hast du deinen Denkfehler. Du setzt den Timer nicht so auf, dass du mit einem 'Timerlauf' genau die zu erzielende Zeit durch einen einzigen Interrupt erzeugst. Stell dir das eher wie deine Uhr vor. Du stellst den Timer so ein, dass er dir den Sekundenzeiger deiner Uhr realisiert. Und mit dem kannst du ja auch 28 Sekunden abzählen, indem du mitzählst, wie oft der Zeiger um 1 Position vorrückt (oder eben von 28 auf 0 runterzählst). Und das kannst du mit vielen Zeitdauern gleichzeitig machen, obwohl du nur 1 Sekundenzeiger auf deiner Uhr hast. Den Rest, wie man das dann technisch konkret machen kann, hat Frank ja schon angesprochen.
AHA-Effekt... Ich setzte beim Ereignis den Timer und schalte die LED ein. Wenn die Timer-ISR abgelaufen ist(500ms) dann werden einfach alle LED's ausgeschaltet... Richtig,meine Denkweise?
Wie wäre folgendes: Die ISR wird Timer gesteuert regelmäßig aufgerufen (z.B alle 10ms). Für jede LED gibt es einen Zähler. Ist dieser ungleich null, dekrementiert die ISR ihn und schaltet die zugehörige LED ein, ansonsten schaltet er die LED aus. Das Hauptprogramm muss dann nur noch den Zähler auf einen Wert ungleich null setzen.
@ Rafi Dafi (alexanderw) >Ich setzte beim Ereignis den Timer und schalte die LED ein. Wenn die >Timer-ISR abgelaufen ist(500ms) dann werden einfach alle LED's >ausgeschaltet... >Richtig,meine Denkweise? Fast. Du setzt einen Timer, der deine kleinste, benötigte Zeiteinheit darstellt, sei es nun 500ms oder sonstwas. Damit hast du ein festes Zeitraster, indem du deine Schaltvorgänge durchführen kannst. Siehe Artikel statemachine und Multitasking.
Rafi Dafi schrieb: > Richtig,meine Denkweise? Nein. Du lässt einen Timer einfach durchlaufen und lässt diesen zum Beispiel die ganze Zeit jede hundertstel Sekunde einen Interrupt ausführen, normalerweise einen Overflow-Interrupt. Jetzt hast Du also eine ISR, die 100 mal in der Sekunde aufgerufen wird, also
1 | static volatile uint8_t counter; |
2 | |
3 | ISR(....) |
4 | {
|
5 | if (counter > 0) |
6 | {
|
7 | counter--; |
8 | if (counter == 0) |
9 | {
|
10 | LED_AUS; |
11 | }
|
12 | }
|
13 | }
|
14 | |
15 | int main () |
16 | {
|
17 | ...
|
18 | |
19 | LED_AN; |
20 | counter = 50; // nach 500ms ist counter auf 0 |
21 | ...
|
22 | }
|
Das Erweitern auf ein Array für N LEDs überlasse ich Dir.
Rafi Dafi schrieb: > AHA-Effekt... > > Ich setzte beim Ereignis den Timer Kommt drauf an, wie du das jetzt meinst. Der Timer, also das physische Teil in deinem µC, ... den lässt du einfach dauernd laufen! Es gibt keinen Grund warum man den dauernd starten und stoppen müsste. Es sind die Countdown-Zähler, die dir die Software-Einzeltimer für unterschiedliche LED oder LED-Gruppen generieren!
1 | volatile int16_t TimerA; |
2 | volatile int16_t TimerB; |
3 | |
4 | |
5 | ISR( .... ) // wird jede 1 Millisekunde aufgerufen |
6 | { |
7 | if( TimerA > 0 ) |
8 | { |
9 | TimerA --; |
10 | if( TimerA == 0 ) |
11 | schalte LED |
12 | } |
13 | |
14 | if( TimerB > 0 ) |
15 | { |
16 | TimerB --; |
17 | if( TimerB == 0 ) |
18 | schalte andere LED |
19 | } |
20 | } |
21 | |
22 | int main() |
23 | { |
24 | Timer aufsetzen und starten |
25 | |
26 | sei(); |
27 | |
28 | while( 1 ) { |
29 | |
30 | if( irgendwas ) |
31 | { |
32 | LED einschalten |
33 | cli(); |
34 | TimerA = 500; // zb 500 Millisekunden, weil die ISR jede 1ms aufgerufen wird |
35 | // und bei jedem Aufruf wird der Wert um 1 runtergezählt |
36 | sei(); |
37 | } |
38 | |
39 | if( irgendwas ganz anderes ) |
40 | { |
41 | andere LED einschalten |
42 | cli(); |
43 | TimerB = 300; // zb 300 |
44 | sei(); |
45 | } |
46 | } |
47 | } |
Und was mit 2 Software-Countdowns geht, geht auch mit 200. Nur wird man dann sinnvollerweise ein Array nehmen und nicht 200 Einzeln-Variablen.
Rafi Dafi schrieb: > Normalerweise hab ich mir gedacht das bei bestimmten Ereignisen, wo die > LED's leuchten sollen, ein Timerinterrupt auslöst. Die LED leuchtet für > 500ms und dann gehts sie wieder aus und die Timer-ISR ist zu ende. Du willst in der ISR 500ms warten? Blöde Idee! Rafi Dafi schrieb: > Wie kann ich jetzt die Timer-ISR etsprechend der 3 verschiedenen > Zustände starten? Ein Controller hat doch meistens nicht so viele Timer Du brauchst mitnichten so viele (Hardware-)Timer wie du LED hast. Du brauchst nur genau einen Timer und etwas Grips. Eine mögliche Lösung für zwei LED und einen Timer sähe z.B. so aus:
1 | volatile uint8_t led1_timer; |
2 | volatile uint8_t led2_timer; |
3 | |
4 | void led_an(uint8_t led_nr, uint8_t zeit) { |
5 | if (led_nr == 1) { |
6 | led1_an(); |
7 | led1_timer= zeit; |
8 | }
|
9 | if (led_nr == 2) { |
10 | led2_an(); |
11 | led2_timer= zeit; |
12 | }
|
13 | }
|
14 | |
15 | void led_isr(void) { |
16 | if (led1_timer) { |
17 | led1_timer--; |
18 | if (led1_timer == 0) { |
19 | led1_aus(); |
20 | }
|
21 | }
|
22 | if (led2_timer) { |
23 | led2_timer--; |
24 | if (led2_timer == 0) { |
25 | led2_aus(); |
26 | }
|
27 | }
|
28 | }
|
die Makros ledX_an und ledX_aus mußt du natürlich bereit stellen. Und du mußt led_isr() regelmäßig aufrufen, z.B. jede Millisekunde aus einer Timer-ISR. Die zeit oben ist dann in Vielfachen der Timerperiode gemessen, die du aber dank CTC Mode und Compare-Einheit beliebig festlegen kannst. Für viele LED nimmt man natürlich besser ein Array für die ledX_timer Variablen. Und für längere Zeiten und/oder feinere Auflösung braucht man evtl. einen breiteren Typ als uint8_t. XL
Rafi Dafi schrieb: > Die Ereignise laufen nicht nach einem Schema ab Alles läßt sich in einem Schema ausdrücken. Du mußt nur erstmal festlegen, was Du eigentlich willst. Da es um LEDs geht, dürften 10ms als kleinste Schrittweite ausreichend sein. d.h. Du setzt einen Timer 10ms auf. Und jedesmal, wenn der Timer abläuft, liest Du aus einer Tabelle das Muster der LEDs und die Dauer (in 10ms Schritten) bis zur nächsten Änderung. Die Zeitdauer 0 kann man dafür reservieren, daß die Tabelle zuende ist und Du fängst wieder von vorn an. Peter
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.