Timer 0 beim Atmega8

OP #356892
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
Gast
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.
Gast
Entweder tatsächlich blind, oder Du kannst nicht lesen. Warum schreib
ich eigentlich den ganzen Scheiß? Kann ich mir dann wohl auch sparen...
Gast
@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.
Gast
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.
Gast
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...
OP
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!
Gast
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
Gast
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
Gast
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
Gast
>>
> 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.
@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.

...
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 20 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.