Moin moin erstmal!
Ich mache gerade meine ersten Mikrocontroller-Gehversuche mit einem
ATMega8 und komme an diesem Timer einfach nicht weiter... Das Programm
soll eine LED an Port D (Pollin Evaluationsboard) ein- und ausschalten.
Sobald ich aber den Vorteiler auf 256 oder größer stelle, bleibt die LED
dunkel. Ich habe es mit dem extern Quarz (16 MHz) und allen internen
Taktfrequenzen probiert. Man sieht zwar dass die LED flackert, aber eine
geringere Taktfrequenz bringt nicht ein langsameres Flackern. Wo mache
ich da einen Denkfehler??
Vielen Dank für Eure Hilfe,
Chris
ich kann keinen direkten Fehler finden. die ANDI Anweisung im Interrupt
ist hier überflüssig. Aber funktionieren müßte das trotzdem.
Es ist nicht ganz klar, ob die LED dunkel bleibt oder flackert. Aufgrund
meiner ähnlichen Tests müßte die LED leuchten und nur wenn man genau
hinsieht, sehe ich ein Flackern. Etwas besser ist es, die andere LED
auch einzuschalten, damit man den Unterschied sieht. Habe ich aber auch
nicht gleich gesehen, waren fast gleich hell.
Ich würde einfach weiter programmieren. Manchmal sind die Fehler durch
eine Umstellung durch eine tlw. Neuprogrammierung weg, ohne daß man
weiß, woran das liegt.
mfg
Ich würde als Erstes mal die obligatorische Sicherung des SREG beim
Eintritt in die Interruptroutine und Wiederherstellung vor dem Verlassen
ergänzen. Wenn man das weglässt, braucht man sich über "seltsame
Effekte" nicht wundern.
Alles klar, das mit dem SREG werde ich gleich mal ausprobieren.
Die andi Maske benutze ich um nur die eine LED zu schalten. Auf dem
Board ist an Port D nämlich auch ein Piezo Pieper mit angeschlossen und
der nervt doch ein bißchen bei den Tests... ;-)
Ich werde nachher von Erfolgen oder evtl. Mißerfolgen berichten!
Noch was eingefallen...
>Sobald ich aber den Vorteiler auf 256 oder größer stelle, bleibt die LED>dunkel.
Ich hoffe, Du stellst den Vorteiler nicht auf 256, indem Du
ldi temp1, 256 ;Vorteiler
out TCCR0, temp1
schreibst. Dann bleibt der Timer nämlich wirklich stehen! (Klar, warum?
Wenn nicht, Bescheid sagen)
>Ich werde nachher von Erfolgen oder evtl. Mißerfolgen berichten!
Viel Glück! :-)
Ähhm, nein...
Soweit bin ich dann doch schon drin im Thema ;-)
1
ldi temp1, 5 ;Vorteiler 1024
2
out TCCR0, temp1
Geht aber leider auch mit sichern des SREG nicht...
1
timer0_overflow:
2
in temp1, sreg
3
rcall invert_leds
4
timer0_overflow_end:
5
out sreg, temp1
6
reti
Oder muss ich da noch mehr machen?? (temp1 wird nicht in invert_leds
genutzt)
Noch ne kleine Frage am Rande: Warum kann man SREG nicht mit push und
pop sichern? Ist das 16 Bit??
Viele Grüße
PS: Noch was: Ich will mit dem Programm kein PWM oder sowas machen,
sondern einfach die LED langsam blinken lassen. Ich hatte auch noch ein
zusätzlichen Zähler eingebaut, um die Frequenz noch weiter
herunterzubringen, hat aber auch nicht richtig geklappt. Falls ihr also
noch irgendwelche kreativen Anregungen in der Richtung habt, wäre ich
sehr dankbar...
Chris G. wrote:
> Noch ne kleine Frage am Rande: Warum kann man SREG nicht mit push und> pop sichern? Ist das 16 Bit??
Nein, es ist ein I/O-Register, und die kann man nicht direkt pushen und
poppen. Das geht nur mit Rechenregistern. Wenn Du im Programm Zeit hast,
kannst Du z.B.
1
in r16, SREG
2
push r16
3
;....ISR
4
pop r16
5
out SREG, r16
schreiben. Sind pro ISR zwei Taktzyklen mehr, als wenn man es im
Rechenregister lässt. Wenn das Register (kann auch jedes andere sein,
muss nicht r16 sein) eh nicht in der ISR genutzt wird, dann kann man den
Inhalt auch drinlassen.
> ldi temp1, 5 ;Vorteiler 1024> out TCCR0, temp1
Jepp. Eine besonders lesefreundliche Variante sieht übrigens so aus:
> ldi temp1, 1<<CS02 | 0<<CS01 | 1<<CS00 ;Vorteiler 1024> out TCCR0, temp1>Geht aber leider auch mit sichern des SREG nicht...
Hmmmm.....
>timer0_overflow:> in temp1, sreg> rcall invert_leds>timer0_overflow_end:> out sreg, temp1> reti>>Oder muss ich da noch mehr machen?? (temp1 wird nicht in invert_leds>genutzt)
Nein, das ist genau so OK, unter einer Bedingung: temp1 darf nirgendwo
sonst im Programm benutzt werden (ausgenommen der Initialisierungsteil -
logisch).
>Noch ne kleine Frage am Rande: Warum kann man SREG nicht mit push und>pop sichern? Ist das 16 Bit??
Du kannst das SREG problemlos mit push und pop sichern, und so wird es
auch am häufigsten bewerkstelligt.
1
timer0_overflow:
2
pusht
3
int,SREG
4
pusht
5
6
rcallinvert_leds
7
8
timer0_overflow_end:
9
popt
10
outSREG,t
11
popt
12
13
reti
Hier kann das Register t beliebig im restlichen Programm verwendet
werden. Der Preis dafür ist eine etwas weniger schnelle
Interruptroutine.
Das SREG ist 8 Bit breit.
8 MHz Systemtakt und Vorteiler 1024 macht eine Timer-Tickfrequenz von
7812.5 Hz. Overflow nach jedem 256. Tick resultiert zu einer
LED-Blinkfrequenz von ca. 30.5 Hz. Das ist nicht gerade eine langsames
Blinken; man dürfte es eher als unruhiges Flackern wahrnehmen. Tipp:
Zähl einfach stupide irgendein Register in der ISR hoch, und gib nicht
dessen Bit 0, sondern z. B. Bit 4 auf die LED. Dann hast Du auf
simpelste Weise einen weiteren "Software"-Frequenzteiler von 16 drin,
und die LED sollte "augenfreundlich" blinken.
Gruß zurück
Das mit den 30Hz bei 8 MHz Systemtakt hatte ich mir auch schon
ausgerechnet, deswegen hab ich den internen Takt mit 1 MHz benutzt,
sollte also so knapp 4 Hz ergeben. Wie gesagt, SOLLTE ES, tut es aber
nicht...
Oder gibts da irgendein Problem mit dem internen Takt?? Es kommt erstmal
auf Genauigkeit nicht an. Ich hätte sonst noch einen externen 16 MHz
Quarz auf dem Board im Angebot.
Hierzu:
> Tipp:> Zähl einfach stupide irgendein Register in der ISR hoch, und gib nicht> dessen Bit 0, sondern z. B. Bit 4 auf die LED. Dann hast Du auf> simpelste Weise einen weiteren "Software"-Frequenzteiler von 16 drin,> und die LED sollte "augenfreundlich" blinken.
...hab ich noch ne kleine Frage:
Heißt das, dass ich doch ein Register nehmen soll, aber eben das Bit 4
auf die LED ausgeben soll?? Kapier ich noch nicht ganz fürchte ich...
Ich hab jetzt einfach immer einen Zähler gemacht und dann mit cpi auf
einen Wert geprüft und mit brne dann die Verzweigung realisiert.
Yeah, es funktioniert!!
Ich hab nochmal ne Runde mit den Fuse-Bits "rumgespielt" und dazu das
Datenblatt des Mega8 gewälzt und bin zu folgender Einstellung gelangt:
CKOPT = 0
CKSEL3 = 1
CKSEL2 = 0
CKSEL1 = 1
CKSEL0 = 1
SUT1 = 1
SUT0 = 1
Somit sollte ich den externen Quarz mit 16 MHz nutzen können. Mit einer
einfachen Zählschleife kann ich nun die LED schön langsam ein- und
ausschalten. :-)
Aber warum das mit dem internen Takt nicht hingehauen hat verstehe ich
immer noch nicht ganz. Vielleicht kann ja hier noch jemand für
Aufklärung sorgen.
Das ergibt eine Frequenzteilung (ISR-Durchlauffrequenz zu
LED-Blinkfrequenz) von 2^4 = 16. Wenn Du aus der 4 eine 5 machst, hast
Du eine Teilung von 2^5 = 32 usw. Du kannst so die Blinkgeschwindigkeit
der LED in Faktor-2-Schritten einstellen.
Alternativ kannst Du auch direkt c auf den Port D ausgeben:
>Ich hab jetzt einfach immer einen Zähler gemacht und dann mit cpi auf>einen Wert geprüft und mit brne dann die Verzweigung realisiert.
So geht es natürlich auch, und hat den Vorteil, jede beliebige Teilung,
d. h. auch z. B. 5, 19, 27 zu ermöglichen.
>Yeah, es funktioniert!!
Glückwunsch! g>Ich hab nochmal ne Runde mit den Fuse-Bits "rumgespielt"
Uahhhhh... ;-) Beim "Rumspielen" mit den Fuse-Bits sollte man stets
vorsichtig sein, weil man mit bestimmten Einstellungen beispielsweise
den Reset-Pin zu einem IO-Pin umfunktionieren kann. Dann kann man den
Controller aber auch nicht mehr per ISP neu programmieren! Wenn Du dann
kein Board zur Hand hast, das High-Voltage-Parallel-Programming
unterstützt (wie etwa das STK500), stehst Du erst mal dumm da. Deshalb
ist es ratsam, die Fuse-Bits wie ein rohes Ei zu behandeln, und sie erst
zu beschreiben wenn man sicher sein kann, genau zu wissen was man tut.
Ich bin ganz vorsichtig mit den Fuses, versprochen... Hab auch nur an
den Takteinstellungen rumgestellt, und auch nur wenn ich mir 100%ig
sicher war.
Warum das aber alles mit dem internen Takt nicht geklappt hat weiß ich
immer noch nicht.
>Warum das aber alles mit dem internen Takt nicht geklappt hat weiß ich>immer noch nicht.
Komische Sache... Also meine Wahl für "1 MHz internal R/C oscillator"
wäre diese:
CKOPT = 0
CKSEL3 = 0
CKSEL2 = 0
CKSEL1 = 0
CKSEL0 = 1
SUT1 = 0
SUT0 = 0
Pins XTAL1 und XTAL2 offen lassen.
Läufts bei Dir damit?