Forum: Mikrocontroller und Digitale Elektronik Timer 0 beim Atmega8


von Andreas 2. (andreas2000)


Lesenswert?

Hallo ich habe folgendes Problem(seit Stunden),

Ich habe ein Unterprogramm geschrieben welches den Timer0 benutzt und
beim Überlauf eine Interruptroutine abarbeiten soll.Den Timer habe ich
initialisiert, TCCR0 gesetzt,TIMSK gesetzt,sei() auch eingegeben.
Im AVR-Studio Simmulator zählt der Timer auch hoch,springt aber beim
Erreichen des Endwertes an den Anfang der Main und arbeitet diese
wieder ab. die Interrupt Service Routine wird ignoriert, bringe ich
aber den Quelltext der Routine an das Ende der Quelldatei springt die
ISR weningstens dort hinein, aber nach hochzählen des Timers wieder an
den Anfang der Main! Muß nach abrbeiten der ISR nicht wieder an die
Stelle gesprungen werden von wo sie aufgerufen wurde?
Und warum wird sie manchmal garnicht angesprungen?
ISR (Timer0) oder ISR (Timer0_OVF) falsch?
Danke für eure Hilfe

von johnny.m (Gast)


Lesenswert?

Wenn Du den Code nicht postest, kann Dir hier keiner wirklich helfen,
außer mit schwammigen Vermutungen. Wenn Du mit WINAVR-C programmierst,
dann kann ich Dir wenigstens sagen, dass ISR (Timer0) und ISR
(Timer0_OVF) falsch sind und dass das wahrscheinlich das Problem sein
dürfte, da der Interrupt zwar freigegeben ist, aber der µC keine
gültige ISR zur Bearbeitung hat. Deshalb wird in den Spurious Interrupt
Handler gesprungen, was i.d.R. einen Reset bedeutet. Die richtigen Namen
der Interrupt-Vektoren stehen in der iom8.h. Sie enden alle mit _vect.

von Andreas 2. (andreas2000)


Lesenswert?

alles klar ich schicke gleich den Quellcode

von johnny.m (Gast)


Lesenswert?

Probier erst das mit den richtigen Interrupt-Vektoren aus! Vielleicht
brauchste dann gar nix mehr zu schicken!

von johnny.m (Gast)


Lesenswert?

Ich kann Dir so viel verraten, dass z.B. der Vektor für den
Overflow-Interrupt von Timer 0 mit TIMER0_OVF_vect definiert ist...

von Andreas 2. (andreas2000)


Angehängte Dateien:

Lesenswert?

Hier der Quellcode, vielleicht bin ich ja blind?
Danke

von Hannes L. (hannes)


Lesenswert?

Und initialisiere den Stackpointer, falls du in ASM arbeitest.

...

von J. Ustiz (Gast)


Lesenswert?

Entweder tatsächlich blind, oder Du kannst nicht lesen. Warum schreib
ich eigentlich den ganzen Scheiß? Kann ich mir dann wohl auch sparen...

von johnny.m (Gast)


Lesenswert?

@J. Ustiz:
Hä???

@Andreas2000:
Schön, dass Du den Code doch noch schickst, aber einen Fehler hab ich
Dir ja schon mitgeteilt. Abgesehen von dem falschen Vektornamen
bekommst Du wahrscheinlich Probleme mit Variablen, die Du in der ISR
veränderst, wenn Du sie nicht volatile deklarierst.

von Andreas 2. (andreas2000)


Lesenswert?

Vectornamen habe ich angepasst, Aber trotzdem wird die ISR nicht
angesprungen. Das müsste doch klappen?
Was meinst du mit "volatile"?

von Andreas 2. (andreas2000)


Lesenswert?

Die ISR wird jetzt aufgerufen.(Ein Zeichen war noch falsch).
Hat denn jemand ne Idee wie man es schaft das der Timer z.B. 5 mal
durchlaufen wird,und dann in die Main zurück springt ?

von johnny.m (Gast)


Lesenswert?

Wenn eine globale Variable, die in einer Interrupt-Routine verändert
werden soll, nicht volatile deklariert wird, kann es passieren
(vereinfacht gesagt), dass das Hauptprogramm von einer Änderung nichts
mitbekommt. Der Typqualifizierer volatile teilt dem Compiler mit, dass
die betreffende Variable nicht im Rechenregistersatz abgelegt werden
soll, sondern im SRAM, da die vom Programm benutzten Rechenregister am
Anfang der ISR gesichert und am Ende wiederhergestellt werden.

von johnny.m (Gast)


Lesenswert?

Achja, und das mit dem 'Timer 5 mal durchlaufen und dann in die main
zurück' müsstest Du mal näher erläutern. Du willst doch hoffentlich
nicht in der ISR eine Warteschleife einbauen? So was ist nämlich
Pfui...

von Andreas 2. (andreas2000)


Lesenswert?

Pfui möchte ich natürlich nicht!!
Mein Bemühen ist es ein und Ausschalten eines Ports zu realisieren,
also eine bestimmte Frequenz mit dem Timer zu erzeugen. Diese sollte
aber insgesammt nur 5 Perioden haben(zu Testen).
Später sollen es dann einmal 20 Periden mit einer Frequenz von
41,...kHz werden, um eine US-Transceiver_Schaltung anzusteuern().
Zum erzeugen der Frequenz eignen sich Timer ja gut nur das durchlaufen
des Timers mus irgendwie abzählbar sein!

von Andreas 2. (andreas2000)


Lesenswert?

Hat denn jemand ne Idee wie man Timerdurchläufe zählbar macht, oder wie
man trotz ISR ein Schleife geschickt einbindet?
Wäre für eine Code Idee dankbar.

von Wolfgang (Gast)


Lesenswert?

Hallo,

Du schreibst in der ISR eine 1 in das Bit TOV0 des Registers TIFR.
Damit setzt Du das Overflow Interrupt-Flag zurück. Dann pollst Du das
Bit TOV0 und wen es wieder gesetzt ist, dann ist wieder ein Overflow
aufgetreten. Bit wieder zurücksetzen und dann wieder pollen (pollen =
abfragen).

Aber ansich ist eine Warteschleife in einer ISR eine Todsünde.

Gruß

Wolfgang
--
www.ibweinmann.de
Brushless Development Kit - Der Weg zum Brushlessregler mit AVR

von Andi (Gast)


Lesenswert?

Nimm eine globale Variable setze sie auf 10, und zähle bei jedem
Interrupt 1 ab.
Wenn sie 0 erreicht schaltest du das Port-Bit nicht mehr um - fertig.
Jedesmal wenn du wieder erneut ein Signal senden willst setzt du im
Main die Variable wieder auf 10 (oder später auf 40).

Timer_Interrupt:
  if(PeriodCount > 0)
  {
     Port toggeln;
     PeriodCount--;
  }
EndeInterrupt

Noch ein Tipp: Port toggeln (=Zustand wechseln) kann man bei neueren
AVRs ganz einfach in dem man das entsprechende Bit im PINxx Register
setzt.

Gruss Andi

von Fred (Gast)


Lesenswert?

Hallo,

wie wär's damit:
Die Timer Interrupt Routine (ISR) zählt bei jedem Überlauf eine
Variable um eine Einheit hoch. Jetzt folgt noch die Abfrage, ob diese
Variable schon einen bestimmten Wert erreicht hat (weiteres Bit setzen)
oder nicht (kein Bit setzen g) und es wird ins Hauptprogramm
gesprungen.
Entweder wird jetzt bei jedem Durchlauf des Hauptprogramms dieses Bit
(in irgendeinem beliebigen Register; "privates Statusregister")
abgefragt, oder Du legst es auf einen Pin, der als externer Interrupt
festgelegt ist. Wird aus der ISR zurückgesprungen, wird das Interrupt
enable Bit gesetzt und anschließend sofort die Service Routine für X
Timerdurchläufe ausgeführt.
Gruß

Fred

von Hannes L. (hannes)


Lesenswert?

> Noch ein Tipp: Port toggeln (=Zustand wechseln) kann man bei neueren
> AVRs ganz einfach in dem man das entsprechende Bit im PINxx Register
> setzt.

Laut Betreff handelt es sich um den Mega8 und der kann das noch nicht.

...

von Axel R. (Gast)


Lesenswert?

>>
> Noch ein Tipp: Port toggeln (=Zustand wechseln) kann man bei neueren
> AVRs ganz einfach in dem man das entsprechende Bit im PINxx Register
> setzt.

Laut Betreff handelt es sich um den Mega8 und der kann das noch nicht.

...
>>
Welches Bit der "neueren" ist das?
Muss ich mir glatt mal ansehen.
PORTTOGGLEBIT oder so?

Wenn man nicht ständig auf dem laufenden bleibt...
AxelR.

von Hannes L. (hannes)


Lesenswert?

@Axel:

Bei Mega48/88/168 z.B. bewirkt das Setzen von Bits (Schreiben mit sbi
oder out) in den PIN-Registern (PINB, PINC, PIND) das Toggeln des
zugehörigen Ausgangs. Ist ein nettes Feature, aber dafür wurden etliche
oft gebrauchte I/O-Register (auch Timer) in den Extended-I/O-Space
verlagert, wo sie nicht meht mit IN/OUT (also mit nur einem Takt)
angesprochen werden können.

...

von Axel R. (Gast)


Lesenswert?

Kapitel 12.2.2 im Datenblatt, habs gefunden.
Danke.
Muss ich für mich aber noch den Nutzen abwägen. kommt man da nicht mit
den Portzuständen komplett durcheineander?
Na egal, danke nochmal

Zu den IN/OUT vs. LD/ST habe ich hier irgentwann mal ein ASM Makro von
der ATMEL Seite gepostet, wo das automatisch berücksichtigt wird.

AxelR.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.