Timer funktioniert ab Vorteiler 256 nicht mehr

OP #628584
Lesenswert?

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


1
.include "m8def.inc"
2

3
.def temp1 = r16
4
.def leds = r17
5
.def z1 = r18
6

7
.org 0x0000
8
  rjmp main          ;Reset Handler
9

10
.org OVF0addr
11
  rjmp timer0_overflow    ;Timer Overflow Handler
12

13
main:
14
  ldi temp1, LOW(RAMEND)    ;Stackpointer initialisieren
15
  out SPL, temp1
16
  ldi temp1, HIGH(RAMEND)
17
  out SPH, temp1
18

19
  ldi temp1, 0b01000000    ;Register konfigurieren
20
  out DDRD, temp1
21

22
  ldi leds, 0xFF
23
  ldi z1, 0
24

25
  ldi temp1, 2        ;Vorteiler
26
  out TCCR0, temp1
27

28
  ldi temp1, 1<<TOIE0      ;Timer Interupts erlauben
29
  out TIMSK, temp1
30

31
  sei
32

33
loop:
34
  rjmp loop
35

36

37
timer0_overflow:
38
  ;inc z1
39
  ;cpi z1, 10
40
  ;brne timer0_overflow_end
41
  rcall invert_leds
42
timer0_overflow_end:
43
  reti
44

45
invert_leds:
46
  andi leds, 0b01000000    ;nur LED ansteuern
47
  out PORTD, leds
48
  com leds
49
  ret
#629010
Lesenswert?

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
Gast #629026
Lesenswert?

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.
OP #629041
Lesenswert?

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!
Gast #629086
Lesenswert?

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! :-)
OP #629116
Lesenswert?

Ä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...
#629126
Lesenswert?

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.
Gast #629135
Lesenswert?

>  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
    push t
3
    in t, SREG
4
    push t
5

6
    rcall invert_leds
7

8
timer0_overflow_end:
9
    pop t 
10
    out SREG, t
11
    pop t
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
OP #629213
Lesenswert?

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.
OP #629222
Lesenswert?

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.
Gast #629467
Lesenswert?

>Heißt das, dass ich doch ein Register nehmen soll, aber eben das Bit 4
>auf die LED ausgeben soll??

Ja, zum Beispiel so:
1
SwitchLED:
2
   inc c                   ; wird permanent hochgezählt (...254, 255, 0, 1, 2...)
3

4
   bst c, 4                ; Bit Nr. 4 von c ins T-Flag kopieren 
5

6
   clr ledstate
7
   bld ledstate, LEDPIN    ; T-Flag ins LEDPIN-ste Bit von ledstate schreiben
8
   out PORTD, ledstate     ; LED schalten
9

10
   ret

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:
1
SwitchLED:
2
   inc c                  ; wird permanent hochgezählt (...254, 255, 0, 1, 2...)
3

4
   mov ledstate, c
5
   andi ledstate, ...     ; nervige Piepser ausmaskieren 
6
   out PORTD, ledstate    ; alle an Port D angeschlosenen LEDs blinken lassen
7

8
   ret

>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.
Gast #629966
Lesenswert?

>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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren