PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega8 Timer0



Krampfda
14.10.2007, 20:31
Nabend,
ich habe folgendes problem. ich möchte gerne den Timer0 meines atmega8 in gang bringen. und bei einem overflow einen interrupt auslösen.
also habe ich, wie im datenblatt und in etlichen beispielen beschrieben den timer in gang gesetzt:
timer aktivieren F_CPU/1024 (TCCR0)
interrupt durch timer0 erlauben (TIMSK)
interrupts allgemein einschalten
ISR routine für timer0 overflow schreiben ISR(TIMER0_OVF_vect)

soweit von meiner seite ersichtlich, ist an dem code nichts auszusetzen 8-[

da ich gehört habe, dass es da durchaus drauf ankommt, wie man seinen code compiliert, habe ich das beigefügt.

Hier das Compileren und Flashen:


> avr-gcc file.c -c -o file.o -Os -g -mmcu=atmega8
> avr-gcc file.o -o file.elf -mmcu=atmega8
> avr-objcopy -j .text -j .data -O ihex file.elf file.hex
> avrdude -c avrispv2 -p m8 -P usb -U flash:w:file.hex:i


Hier der Code:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define F_CPU 1000000

ISR(TIMER0_OVF_vect)
{
DDRB = 0xfd; // Alles ausgang ausser PB1 -> Eingang
PORTB = 0x03; // Ausgang für PB0 high , Pull-Up für PB1 an
}


int main(void)
{
TCCR0 = (1<<CS02)|(1<<CS00); // TCCR0 = 0x03;
TIMSK = (1<<TOIE0);
sei();
while(1)
{

}
/* Wird nie erreicht */
return 0;
}


Ich weis, dass die Anweisung in der Interrupt-Funktionen für nen timer keinen sinn hat. es geht hier auch lediglich um den test des timers ;-)

In einer fertigen beispieldatei funktioniert der timer.
suchfunktion des forums ergab für mich keine weiterhelfenden themen.

ich hoffe, dass mir jemand helfen kann.
danke schonmal im vorraus.
gruß
Krampfda

Reeper
14.10.2007, 20:58
Ich kann kein Fehler im Code entdecken.
Auch beim compilieren mit WinAVR kommt keine Fehlermeldung.
Gruß Stefan

Dirk
14.10.2007, 21:09
Hallo Krampfda,

bis auf 2 Dinge scheint alles ok:
1. Was hat eine DDRx-Festlegung in einer ISR zu suchen?
2. TCCR0 ist nicht 0x03 (Kommentar), sondern 0x05, aber der Code selbst ist ok.

Schreib doch mal einen Code, der wirklich etwas macht (LED einschalten o.ä.).

Gruß Dirk

Krampfda
15.10.2007, 15:57
habe die DDRB festlegungen aus der ISR genommen und in main() eingefügt. und die andere anweisung ssollte ja eine LED o.ä. in gang bringen (was mit genau dem code in main() auch funktioniert), aber offensichtlich klappt das auch nicht nachdem DDRB schon vorher festgelegt wird.

Dirk
15.10.2007, 16:33
... aber offensichtlich klappt das auch nicht ...

Was klappt nicht? Poste evtl. das ganze Programm und sag, was es machen soll.

Gruß Dirk

Krampfda
15.10.2007, 16:42
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define F_CPU 1000000

ISR(TIMER0_OVF_vect)
{
PORTB = 0x01;
}


int main(void)
{
DDRB = 0x01;
TCCR0 = (1<<CS02)|(1<<CS00);
TIMSK = (1<<TOIE0);
sei();
while(1)
{

}
/* Wird nie erreicht */
return 0;
}
DDRB steht nun in main().
und wenn ich nun PORTB ebenfalls in main() so belege, wie momentan in ISR, dann leuchtet die an PB0 angeschlossene LED einwandfrei.

nur so, wie es im moment ist, passiert gar nichts.

McJenso
15.10.2007, 17:14
Hallo,

frag doch mal das Overflow Flag TOV0 in TIFR inerhalb der Endlosschleife ab. Dann weißt du, ob es am Timer oder am Interrupt liegt.

Gruß

Jens

Hubert.G
15.10.2007, 21:17
Ich kann mir nicht erklären wo dein Problem liegt, sicher nicht im Programm. Die Zeile in der ISR geändert auf : PORTB ^= 0x01; und die LED flimmert munter vor sich hin.

michas_rob
15.10.2007, 21:22
Hallo Krampfda,

hast du eigentlich den Interrupt initialisiert?

Hier ein auszug aus meinem Code:

ISR Initialisierung:

void init_ISR(void) {
sei(); // Globalen Interrupt aktivieren
TIMSK |= ( 0x01 << TOIE0 ) ; // Timer0 Overfloe Interrupt aktivieren
TCCR0 |= ( 0x01 << CS02 | 0x00 << CS01 | 0x01 << CS00 ) ; // Prescaler 1024 / Clock <- CPU
TCNT0 = 0x64; // Timer0 Counter mit 0x64 laden für 20ms bei 8Mhz
}

und hier meine ISR Schleife:

ISR(TIMER0_OVF_vect) {
Counter_X_20ms++;
TCNT0 = 0x64; // Timer0 Counter mit 0x64 laden
TIFR |= ( 0x01 << TOV0 ) ; // das Interruptflag sicher zurücksetzen
}

Ich hoffe, ich konnt dir weiterhelfen

Michael

Krampfda
15.10.2007, 21:47
ich habe mal deinen rat befolgt und das noch etwas ausgebaut:



while(1)
{
if(TIFR==(1<<TOV0))
{
PORTC = (1<<PC5);
}

if(TCNT0==0xff)
{
PORTB = 0x02;
}
}


die LED an PortB leuchtet. PORTC bleibt aus. da der timer hochzählt, scheint es nicht an diesem zu liegen, aber wo ist der fehler in meiner interrupt geschichte ?

komischerweise ergab


TIFR = (1<<TOV0);
if(TIFR==(1<<TOV0))
{
PORTC = (1<<PC5);
}

nicht das gewünschte ergebnis, auch hier blieb PB5 aus.

die codeabschnitte sind jeweils in die endlosschleife meines codes eingebaut worden, den ich oben erwähnt habe.

michas_rob
16.10.2007, 08:01
Hallo,

mit:

TIFR = (1<<TOV0);

kannst du eigentlich nur das Interrupt Flag löschen, eigentlich wird dies automatisch gemacht, aber man kann dies auch manuel durchführen.

also testest nachher nur, od du wirklich das Flag gelöscht hast....

lg michael

Hubert.G
16.10.2007, 08:56
@Krampfda
Wo liegt wirklich dein Problem, dein ursprüngliches Programm funktioniert doch. Ich habe das auf meinem Testboard ausprobiert. Wenn bei dir die LED nicht leuchtet dann hast du eher ein Hardwareproblem.

karmek
16.10.2007, 11:28
Bei mir blinkt die LED auch fleissig. Dazu eine kleine Verständnisfrage: Wieso geht die LED eigentlich wieder aus? Sie wird doch beim Interupt nur eingeschaltet, ich sehe keinen Grund wieso sie wieder ausgehen sollte und somit blinkt *verwirrt ist*. Müsste die led nicht eigentlich konstant leuchten?


EDIT:
streicht meinen Beitrag, ich hab ja in dem Code auch PORTB ^= (1 << PB0); stehen, daher geht das Ding halt an und aus. Wenn ich nur PORTB = (1 << PB0); setze, dann leuchtet die LED konstant.

Krampfda
16.10.2007, 17:42
@Krampfda
Wo liegt wirklich dein Problem, dein ursprüngliches Programm funktioniert doch. Ich habe das auf meinem Testboard ausprobiert. Wenn bei dir die LED nicht leuchtet dann hast du eher ein Hardwareproblem.

genau da liegt mein problem: alle sagen, das programm sei korrekt (was ich auch glaube), aber der interrupt scheint nicht zu funktionieren.

die LED funktioniert einwandfrei an dem port (wenn ich die anders ansteuer),
der timer funktioniert ebenfalls.
ausserdem habe ich auch schon einen anderen controller ausprobiert.

ich habe keine ahnung, wo das problem genau sitzt ^^

McJenso
16.10.2007, 19:39
ich habe keine ahnung, wo das problem genau sitzt ^^

Ich auch nicht. Habe den Code jetzt auch mal probiert, was soll ich schreiben, es geht.

Mit if(TCNT0==0xff) hast du bewiesen, dass der Zähler hoch läuft. Da TOV0 nicht gesetzt wird, scheint es ein Problem beim Überlauf zu geben. Das Flag wird aber erst mit dem Wechsel von 0xff zu 0x00 gesetzt. Wenn du Lust hast, kannst du der Sache mit folgendem Code auf den Grund gehen. Es wird dir bei der Lösung aber wohl nicht weiter helfen.



int main(void)
{
DDRB = 0x01;
TCCR0 = (1<<CS02)|(1<<CS00);
TIMSK = (1<<TOIE0);
//sei(); ist nur ein Test Nix mit Interrupt
TCNT0 = 0x01; //Wir wollen Prüfen, ob 0x00 wieder erreicht wird
while(1)
{
if(TCNT0==0x00)
{
PORTB = 0x01;
}
}
/* Wird nie erreicht */
return 0;
}

Leuchtet die LED findet ein Überlauf statt. Das Flag TOV0 müsste gesetzt sein.
Wie hilft dir das? Keine Ahnung. Sorry.
Hardewar? Okay, schließt du aus.

Gruß

Jens

edit:Mir ist noch eine Möglichkeit eingefallen. Schau mal ob du auch die richtigen Headerdateien, die vom Atmega8, einbindest. Nicht das der Interruptvektor weißdergeier wohin zeigt.

Hubert.G
16.10.2007, 20:23
Also der Interrupt funktioniert sicher, sonst würde die LED bei mir nicht blinken, die wird nur in der ISR angesteuert.
"karmek" hat ebenfalls geschrieben das die LED blinkt.

McJenso
16.10.2007, 20:44
Also der Interrupt funktioniert sicher, sonst würde die LED bei mir nicht blinken, die wird nur in der ISR angesteuert.
"karmek" hat ebenfalls geschrieben das die LED blinkt.

Bei mir funktioniertes auch. Nur beim op wohl nicht. :evil:
Oder habe ich da etwas überlesen? Er hat schon einen anderen ATMega8 probiert. Die LED soll an dem Port auch leuchten, wenn er sie ohne Interrupt anspricht. Hardware? Mir fällt kein passendes Scenario ein.
Nehmen wir mal an, er hat die Headerdatei vom AtMegaXX eingebunden. Dann ist TIMER_OVF_vect nicht mehr 5 sondern 8 (Werte ausgedacht, nicht nachgeschaut).

Gruß

Jens

Krampfda
16.10.2007, 20:47
Schau mal ob du auch die richtigen Headerdateien, die vom Atmega8, einbindest. Nicht das der Interruptvektor weißdergeier wohin zeigt.

in meinem ersten beitrag siehst du, wie ich den code compiliert und geflasht habe.
habe immer den controllertyp mit angegeben, wo es wichtig ist, meine ich, aber ggf kannst du da was finden.

gruß
krampfda

McJenso
16.10.2007, 20:59
:oops: :oops:

Jetzt wo du es schreibst ....

Hubert.G
16.10.2007, 21:09
Probier mal ob du meinen Code laden kannst

Krampfda
16.10.2007, 21:22
die led an PB0 blinkt einwandfrei.
es kann also nur noch an meinem avr-gcc liegen?!
wie hast du den denn nun compiliert und mit welcher avr-gcc version ?

Hubert.G
17.10.2007, 10:00
Ich arbeite mit dem AVR-Studio 4.13 und GCC 20070122.

Krampfda
18.10.2007, 22:03
so, nach ewig langem rumgemache funktioniert es jetzt einwandfrei :)

habe mal alle pakete, die für avr's wichtig sind aktualisiert auf die neusten versionen.

und nun macht der compiler auch genau das, was ich will \:D/ \:D/
danke an alle, die mir dabei geholfen haben, das problem ausfindig zu machen.

nebenbei habe ich auch als anfänger ein bisschen gelernt, welche möglichkeiten man bei avr's zum debuggen hat. also ein prima sache hier!

gruß
:arrow: ein glücklicher krampfda