Hallo zusammen,
ich bin noch ziemlich neu in der uC-Programmierung.
Ich wollte ein Programm schreiben, dass 2 verschiedene Blink-Programme
ausführt. Im ersten Programm sollen PortD und PortB blinken und im
zweiten Programm sollen sie ganz simpel leuchten.
Das Blinken geschieht in Timer0 und funktionierte in vorherigen Tests
auch schon.
Der Programmwechsel sollte im OverflowHandler von Timer1 stattfinden,
aber das klappt leider nicht so ganz.
Vielleicht könnte mir jemand Denkanstöße liefern und andere Fehler in
meinem Quelltext finden?
Vielen Dank,
Eroli
Hallo,
erstmal Danke für deine Antwort. Auf solche Stolperfallen muss man
erstmal achten...
Habe das nun so umformuliert:
1
ldi temp, 0b00000101 ; Timer0-Overflow und Timer1-Overflow "erlauben"
2
out TIMSK, temp
Das gesamte Programm habe ich nochmal angehangen.
Leider ist das Verhalten immer noch nicht ganz richtig. Nach ca. 60
Sekunden fängt es an zu blinken und dann hört es nie wieder auf.
Leider kann ich das auch nicht debuggen, da meine Breakpoints (je einer
in der ersten Zeile des Overflow-Interrupts) nicht erreicht werden oder
zumindest nicht feuern (das Programm läuft einfach weiter?)
Kann mir einer sagen, woran das liegen könnte?
Hi
Das passt nicht so richtig:
> ...> brge resetProg ; "Programmüberlauf" --> prog = 0>> pop temp ; LESEN von SREG vom STACK (KOPIE)> out SREG, temp ; Wiederherstellen von SREG> pop temp ; Wiederherstellen von "TEMP">>resetProg:> ldi prog, 0x00 ; Zuruecksetzen> reti
resetProg wird immer ausgeführt. Bei dem Sprung zu resetProg wird SREG
und der Stack nicht wieder rekonstruiert.
MfG Spess
Du startest nur Timer1, bei dessen ersten Überlauf wird dann Prog0
ausgeführt (Timer 0 starten fürs Blinken). Und bei jedem weiteren
Überlauf wird wieder Prog0 ausgeführt, weil am Ende jedes Überlaufs
prog mit 0 geladen wird. Bei letzterem kann man schon fast "zum Glück"
sagen, denn würde bei dem "inc prog" tatsächlich prog mal 2 werden,
verabschiedet sich dein Programm ins Nirwana (weil dann das
SREG-Zurückschreiben und Stack-Aufräumen gar nicht ausgeführt werden
würde).
Wollte es noch editieren, aber da war es schon zu spät:
So sollte es nun aber doch funktionieren, oder?
1
Timer1_Overflow:
2
push temp ; Sichern von "TEMP" im Stack
3
in temp, SREG ; Einlesen des SREG
4
push temp ; Schreiben von SREG im Stack (KOPIE)
5
6
cpi prog, 0b00000000
7
brne Prog1
8
;Prog0 ausfuehren:
9
ldi temp, 0x00
10
out PORTB, temp ;LEDs jetzt aus
11
out PORTD, temp
12
ldi temp, 0b101 ;Timer0 starten mit Vorteiler 1:1024 (Teilt die Blinkfrequenz durch 1024)
13
out TCCR0, temp
14
rjmp ende
15
Prog1:
16
cpi prog, 0b00000001
17
brne ende
18
;Prog1 ausfuehren:
19
ldi temp, 0b000 ;Timer0 beenden (Kein Blinken)
20
out TCCR0, temp
21
ldi temp, 0xFF
22
out PORTB, temp ;LEDs jetzt nur leuchten
23
out PORTD, temp
24
rjmp ende
25
26
ende:
27
ldi temp, 0x00 ;Hier wird der Timer0 mit einem Startwert (z.B. 0) vorbelegt.
28
out TCNT1L, temp
29
out TCNT1H, temp
30
31
pop temp ; LESEN von SREG vom STACK (KOPIE)
32
out SREG, temp ; Wiederherstellen von SREG
33
pop temp ; Wiederherstellen von "TEMP"
34
35
inc prog ; Kein "Programmüberlauf"
36
cpi prog, 2 ; maximales Programm
37
brge resetProg ; "Programmüberlauf" --> prog = 0
38
reti ; Hier mögliches Ende
39
resetProg:
40
ldi prog, 0x00 ; Zuruecksetzen
41
reti
EDIT: Es Funktioniert wirklich :-)
Nochmal vielen Dank an alle helfenden Hände :-)
EDIT2:
Wie könnte ich denn ein weiterschalten zum nächsten Programm per Taster
erzwingen? Kann ich bei einem Druck auf einen Taster einen TimerOverflow
erzwingen?
Nochmals Hallo zusammen,
kann mir vielleicht noch jemand verraten, wie man das Weiterschalten zum
nächsten Programm per Taster zusätzlich auf die Reihe kriegt?
Außerdem wollte ich mein Programm um ein neues Blinprogramm erweitern,
welches ich ebenfalls in Timer0 ausführen wollte. Bei diesem Programm
sollen die LEDs der Reihe nach angehen...
Da ich immer noch nicht weiß, wie ich Interrupts debuggen kann (dort
werden keine Breakpoints erreicht??), habe ich den Code testweise mal in
die mainloop gepackt und dann debugged. Das Ergebnis war, dass das
Programm am Ende immer auf RESET sprang und damit bei 0 anfing und das
war natürlich falsch. Ich weiß jedoch nicht, woran das liegt?
Vielen Dank für eure Hilfe im vorraus,
Eroli
Hi
>Da ich immer noch nicht weiß, wie ich Interrupts debuggen kann (dort>werden keine Breakpoints erreicht??),
Die werden schon erreicht. Das dauert nur sehr lange. Setze zum debuggen
einfach die Prescaler der Timer auf 1.
> ....> rjmp ende <- unnötig>ende:> ldi temp, 0x00 <- unnötig> out TCNT1L, temp <- beim Overflow fängt der Timer> out TCNT1H, temp <- wieder von Null an
Ändere den Teil:
> pop temp ; LESEN von SREG vom STACK (KOPIE)> out SREG, temp ; Wiederherstellen von SREG> pop temp ; Wiederherstellen von "TEMP"> inc prog ; Kein "Programmüberlauf"> cpi prog, 2 ; maximales Programm> brge resetProg ; "Programmüberlauf" --> prog = 0> reti ; Hier mögliches Ende>resetProg:> ldi prog, 0x00 ; Zuruecksetzen> reti
mal in
1
inc prog ; Kein "r18rammüberlauf"
2
cpi prog, 3 ; maximales r18ramm
3
brcs resetr18 ; "r18rammüberlauf" --> r18 = 0
4
clr prog ; Zuruecksetzen
5
resetr18:
6
pop temp ; LESEN von SREG vom STACK (KOPIE)
7
out SREG, temp ; Wiederherstellen von SREG
8
pop temp ; Wiederherstellen von "TEMP"
9
reti
um.
>ldi temp, 0b101>out TCCR1B, temp
macht man besser so:
ldi temp,1<<CS12|1<<CS10
out TCCR1B, temp
Ich habe dein Programm nur mal überflogen. Das ist wahrscheinlich nicht
alles.
MfG Spess
Habe deine Vorschläge mal berücksichtigt, aber einige Fragen:
1) Warum wird der Stack im Timver1Overflow nur rekonstruiert, wenn ein
"Programmüberlauf" stattfindet?
2) Zum Debuggen: In der Schaltung wird nach ca. 60 Sekunden das erste
Mal das Programm gewechselt. Wenn ich den Debugger anschmeisse und in
AVR Studio4 auf Debug-->Run gehe, wird dann nicht bis zum Erreichen
eines Haltepunkts laufen gelassen oder wird das debuggen quasi beendet
und nur noch ausgeführt?
Habe mit obiger Methode (Debug-->Run) schon ca. 10 Minuten darauf
gewartet, dass ein Haltepunkt erreicht wird - ohne Erfolg.
Mit deinen Änderungen sehe ich folgendes Verhalten in meiner Schaltung:
Erst leuchtet alles, so wie es soll und nach ca. 60 sekunden fangen sie
zu blinken an, aber das machen sie dauerhaft. Das nächste Programm wird
nicht mehr erreicht, aber es wird auch nicht mehr zum ersten Programm
(dauerhaftes leuchten) zurückgeschaltet...
Irgendwie ist da der Wurm drin...
Hi
>1) Warum wird der Stack im Timver1Overflow nur rekonstruiert, wenn ein>"Programmüberlauf" stattfindet?
Das bezog sich auf das Programm von:
Beitrag "Re: ATmega8 Timer Problem">2) Zum Debuggen: In der Schaltung wird nach ca. 60 Sekunden das erste>Mal das Programm gewechselt. Wenn ich den Debugger anschmeisse und in>AVR Studio4 auf Debug-->Run gehe, wird dann nicht bis zum Erreichen>eines Haltepunkts laufen gelassen oder wird das debuggen quasi beendet>und nur noch ausgeführt?
So richtig verstehe ich die Frage nicht.
Ich gehe mal davon aus, das du mit 'Debugger' den Simulator meinst.
Mit Debug-->Run wird das Programm simuliert, bis ein Haltepunkt erreicht
wird oder du den Ablauf mit 'Break' unterbrichst. Während 'Run' läuft
werden keine Registeranzeigen aktualisiert. Die Simulation ist
wesentlich langsamer als der reale AVR.
Wenn ich in deinem Programm die Prescaler der Timer von 1024 auf 1
setze, kommen die Interrupts im Simulator im Sekundenrhythmus.
>Mit deinen Änderungen sehe ich folgendes Verhalten in meiner Schaltung:>Erst leuchtet alles, so wie es soll und nach ca. 60 sekunden fangen sie>zu blinken an, aber das machen sie dauerhaft. Das nächste Programm wird>nicht mehr erreicht, aber es wird auch nicht mehr zum ersten Programm>(dauerhaftes leuchten) zurückgeschaltet...
Ich hatte geschrieben
>Ich habe dein Programm nur mal überflogen. Das ist wahrscheinlich nicht>alles.
Mit der Änderung werden erst mal alle drei 'Programme' im
Timer1-Overflow abgearbeitet. Ob die jetzt richtig sind, kann ich dir im
Moment auch nicht sagen.
MfG Spess
Hi
Noch etwas: Könnte es sein, das du im Timer0_Overflow mit dem falschen
wert für 'prg' arbeitest?
Du stellst im Timer1_Overflow ein bestimmtes Programm ein und änderst
danach
die Programmnummer, auf die du im Timer0_Overflow wieder zugreifst.
MfG Spess
Hallo zusammen,
habe gestern nochmals meine Konzentration zusammengenommen und einige
Stunden experimentiert. Dabei ist mir aufgefallen, dass da an vielen
Stellen noch einiges ziemlich schief lief. Ich habe nach und nach alle
Fehler ausgemerzt (und andere auch nochmal eingebaut :-D), aber nach 7
Stunden Arbeit funktioniert mein Programm erstmal :-)
Vielen Dank an die geduldigen Helfer und die Denkanstöße :-)
Hi
Kleiner Vorschlag:
wenn du für dein Blinkprogramm die Ports gleich im Timer1_Overflow
inialisierst, kannst du den Teil:
>blinken:> sbic PORTB, 0 ;Nächsten Befehl überspringen, falls Bit0 abm PortB ist >> rjmp led_ein ;Ansonsten LED einschalten (s. unten).> sbis PORTB,0 ;Überspringen, falls Bit0 abm PortB ist EIN (= LED ist> rjmp led_aus ;Ansonsten LED ausschalten (s. unten).> led_ein: ;Zum Einschalten:> ldi temp, 0x00> out PORTB, temp> out PORTD, temp> rjmp end ;und beenden.> led_aus: ;Zum Ausschalten:> ldi temp, 0xFF> out PORTB, temp> out PORTD, temp> rjmp end
auf
1
ldi temp1,$FF
2
in temp, PORTB
3
eor temp,temp1
4
out PORTB, temp
5
out PORTD, temp
6
rjmp end
eindampfen.
>Ich habe nach und nach alle Fehler ausgemerzt ...
Und was ist das?
>cpi prog, 3>breq aufsteigend
Deine Programmnummer gehen doch nur von 0..2.
MfG Spess
Danke,
werde das noch verkürzen.
>>cpi prog, 3>>breq aufsteigend>>Deine Programmnummer gehen doch nur von 0..2.
Die Programmnummern sind im Timer0 um eins höher, da sie am Ende von
Timer1 ja schon erhöht werden. Ist etwas tricky, aber wenn man es weiß,
dann klappt es ganz gut ;-)