Frank schrieb:
> Ich habe den Fehler gefunden, aber ich Verstehe ihn nicht :(.
> Und zwar hatte ich unten in der While schleife das stehen
>
> PORTB ^= (1<<PB4);
>
> Wenn ich das reinsetze dann spinnt das toggeln in der Timer 1 Interrupt
> Routine
> Ist das ^ eventuell kein bitweises XOR?
Doch, doch.
Aber da passiert ganz was anderes:
Das Hauptprogramm läuft und läuft und läuft.
PORTB ^= (1^<<PB4);
wie implementiert der Compiler das?
Da es keine Assembler Instruktion für Pin Toggeln gibt (das können erst
neuerere Prozessoren), muss der Compiler das so implementieren.
Register = Inhalte vom PORTB
Bit mit einem XOR toggeln
Register zurück schreiben auf PORTB
ab und an passiert es dann mal, dass der Interrupt genau dann kommt,
wenn gerade die Instruktion
Register = Inhalt vom PORTB
durch ist.
Der Interrupt macht was? Der toggelt das Bit 0 am PORTB.
Danach ist er fertig und es geht zurück ins Hauptprogramm. Was macht das
Hauptprogramm?
Es toggelt seinerseits PB4 im Register und schreibt alles zurück an
PORTB.
Aber! Dadurch ist auch PB0 wieder in seinem Ursprungszustand. Das
Toggeln von PB0 würde rückgängig gemacht!
So etwas nennt man eine "Race Condition", wenn abhängig von den genauen
Details und je nachdem wer schneller ist andere Ergebnisse entstehen.
Das Problem war also, dass die Operation
PORTB ^= (1^<<PB4);
durch einen Interrupt unterbrochen wird.
Das Problem kannst du nur so lösen, dass du diese Unterbrechung nicht
zulässt.
1 | ...
|
2 |
|
3 | while( 1 ) {
|
4 | cli();
|
5 | PORTB ^= (1^<<PB4);
|
6 | sei();
|
7 | }
|