Hmm.
So wie ich das sehe, genügt es nicht einfach nur mittels sei()/cli() die
Interrupts zuzulassen. Denn: Der Timer läuft ja weiter. Und wenn dann
der sei() gegeben wird, hast du keine Kontrolle darüber welcher der
Comnpare-Match Interrupts als erster kommt, weil du ja keine Kontrolle
über den Zählerstand des Timers hast.
D.h. du musst dir Logik einbauen, die sicherstellt, dass nach dem sei()
erst mit einem Compare-Match A (wenn ich das richtig gesehen) die ganze
Sache wieder ins Rollen kommt. Nachdem du mittels cli() die ganze Sache
abgestellt hast, werden Compare Matches auf B bzw. C ignoriert und kein
Ausgang geschaltet, solange bis der darauffolgende Match auf A alles
wieder freigibt.
Auch bin ich mir nicht sicher, ob du einfach so mittels cli() die ganze
Steuerung abdrehen darfst. Denn im schlimmsten Fall kommt der cli()
genau mitten im Puls. Wodurch dir dann der Ausgang im letzten Zustand
hängen bleibt.
-> Ich würde das ganze NICHT mittels sei()/cli() lösen, sondern mit
einer globalen Variablen, die aussagt, ob die Zündung eingeschaltet ist
oder nicht. Im Compare Match A wird diese Variable abgefragt und nur
wenn freigegeben, wird auch eine weitere Variable auf true gesetzt, die
im Compare Match B bzw. C abgefragt wird und nur dann, wenn die auf true
steht, dann werden auch die Aktionen gemacht. Im Compare Match C wird
die Variable dann wieder auf false gesetzt, sodass die nächste
Pulssequenz durch einen erneuten COmpare Match A erst wieder freigegeben
werden muss. Kommt diese Freigabe nie (weil du sie per Taster abgedreht
hast), dann erfolgen auch die Aktionen im Match B bzw. C nicht.
1 | volatile uint8_t doSparkle;
|
2 | volatile uint8_t continueSparkle;
|
3 |
|
4 | ISR (TIMER1_COMPA_vect)
|
5 | {
|
6 | if (doSparkle)
|
7 | {
|
8 | continueSparkle = TRUE;
|
9 |
|
10 |
|
11 | if(Drehrichtung == 0)
|
12 | {
|
13 | PORTA |= (1<<PINA4);
|
14 | }
|
15 | else
|
16 | {
|
17 | .....
|
18 | }
|
19 |
|
20 | OCR1B = ALPHA + 2000;
|
21 | ....
|
22 | }
|
23 |
|
24 | ISR (TIMER1_COMPB_vect)
|
25 | {
|
26 | if (continueSparkle)
|
27 | {
|
28 | if(Drehrichtung == 0)
|
29 | {
|
30 | ....
|
31 | }
|
32 | }
|
33 |
|
34 | ISR (TIMER1_COMPC_vect)
|
35 | {
|
36 | if (continueSparkle)
|
37 | {
|
38 | continueSparkle = FALSE;
|
39 |
|
40 | if(Drehrichtung == 0)
|
41 | ....
|
42 | }
|
43 | }
|
44 |
|
45 |
|
46 | int main()
|
47 | {
|
48 | ....
|
49 |
|
50 |
|
51 | if( irgendwas Taster gedrückt )
|
52 | doSparkle = TRUE;
|
53 |
|
54 | if( irgendein anderer Taster
|
55 | doSparkle = FALSE;
|
56 |
|
57 |
|
58 | }
|
der Timer läuft durch und auch die Interrupts sind zu allen Zeiten
aktiv.
Auf die Art ist sichergestellt, dass
* die komplette an den Pins sichtbare Sequenz immer mit einem Compare
Match A beginnt
* auch nach abschalten der Zündung die komplette Pin-Sequenz bis zu
einem Compare Match C durchlaufen wird.
D.h. im Grunde: Die Logik der Zündung läuft die ganze Zeit. Lediglich
das Schalten der Ausgangspins wird durch Variablen unterdrückt, der
ganze OCR Mechanismus läuft weiter. Wodurch extern gesehen, die Zündung
abgeschaltet ist. Aber: sie läuft sauber an und sie stoppt auch sauber.