mikrocontroller.net

Forum: Projekte & Code AVR Timer mit 32 Bit


Autor: peter dannegger (Gast)
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Manchmal reicht die Auflösung der Timer nicht aus.

Kein Problem, wozu gibt es denn die Overflowinterrupts. Damit kann man
bequem in Software weiterzählen. Es ist auch nicht weiter kompliziert,
nur beim Auslesen muß man einiges beachten, damit man ein gültiges
Ergebnis erziehlt.

Die einfachste Möglichkeit zum korrekten Auslesen ist es, den Timer
solange zu stoppen. Blöd nur, wenn dann gerade ein Zählimpuls
reinkommt, den verliert man dann.

Also ist es besser, den Timer weiterlaufen zu lassen.
Für 32 Bit müssen insgesamt 4 Bytes ausgelesen werden, was beim AVR
nicht atomar möglich ist. Deshalb disabled man während des Auslesens
erstmal die Interrupts.

Die nächste Hürde ist dann, wenn gerade dabei ein Overflow auftritt,
ist zwar selten, aber es passiert. Mancher, der mal einen
Frequenzzähler so aufgebaut hat, wird gemerkt haben, daß bei bestimmten
Werten die Anzeige verrückt spielt und große Sprünge macht. Genau das
ist dann so ein nicht berücksichtigter Overflow.

Man hat also 3 Bytes aus dem Softwarezähler und das Timerbyte. Ist nun
ein Overflow aufgetreten konnte ja der Interrupt den Softwarezähler
nicht weiterschalten, da ja die Interrupts zum auslesen gesperrt
wurden. Bevor nun die Interrupts wieder freigegeben werden, merkt man
sich also das Overflowbit.

Ist das Overflowbit gelöscht, dann sind alle 4 Bytes gültig und gut.

Ist es aber gesetzt, muß man noch feststellen, ob es vor den Lesen des
Timerbytes gesetzt wurde und das ist dann der Fall, wenn das Timerbyte
0x00, 0x01 usw. ist. Hätte man es vor dem Overflow gelesen, müßte es ja
0xFF, 0xFE usw. sein.

Man testet also noch das höchstwertige Bit 7 und ist es gelöscht, dann
hat man nach dem Overflow gelesen und muß noch 256 zum Returnwert
addieren.


Peter

:
Autor: Paul Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter
Das ist eine geniale Methode. Leider kann ich den Algorithmus nicht
nachempfinden, da ich kein C beherrsche. Könntest Du das auch in Bascom
schreiben oder in Worten beschreiben? So eine Funktion könnte ich im
Moment gut gebrauchen.

MfG Paul

Autor: Thomas J. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Könnte man das Auslesen nicht auch so machen ?

1. Overflow-Zähler einlesen
2. Zählerstand einlesen
3. Overflow-Zähler erneut einlesen
4. wenn Overflow-Zähler verändert zurück zu 1.

Bei dieser Variante bräuchte mann weder Timer noch INT's zu sperren.


Gruss Thomas

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Thomas J.:

Das geht. Hab ich auch schon so gemacht. Gibt halt einen leichten
Jitter, weil man manchmal zum Einlesen etwas mehr Zeit braucht.

Autor: peter dannegger (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Neben dem Jitter gibt das auch mehr Code.

Ist doch nicht schlimm, die 2 Bits zu testen und 256 zu addieren.



@Paul,

ich habs doch beschrieben, was ist denn daran unklar ?

Anbei mal das Assemblerlisting.


Peter

Autor: Paul Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter
Danke für das Assemblerlisting. Das ist mir eine bessere Hilfe als
der C _ Quelltext. Mal sehen, ob ich das in Bascom hinkriege.

Wenn ich es bis jetzt richtig verstanden habe, zählst Du die Überläufe
des Interupts vom Timer2 in einem separaten Zähler hoch, der beliebig
vorgeladen werden kann, um auch "krumme" Teilerverhältnisse erzeugen
zu können, auf die man die Timer selber nicht einstellen kann.

Ist das soweit richtig?

Autor: bitbo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi !

Vielen Dank, bei mir funktioniert es nun einwandfrei !!!

Aber ich habe einen kleinen Bug in Timer32.c gefunden.
Wenn man die 256 "einfach" addiert, muss man sie an
anderer Stelle auch wieder abziehen, sonst hat man bei
der nächsten Abrage ca. 256 zu viel.

Hier meine Änderung:

u32 get_ticks( void )        // read T2 as 32 bit timer
{
  u32 val;
  u8 tifr;

  cli();
  val = t2_soft + TCNT2;
  tifr = TIFR;          // read interrupt flags
  if( (tifr & 1<<TOV2) && !(val & 0x80) ) // overflow prior reading 
TCNT2 ?
  {
    val += 256;          // then add overflow
  t2_soft -= 256;    // the next "ISR(TIMER2_OVF_vect)" would add to 
much
  }
  sei();

  return val;
}

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nö, da darf nichts abgezogen werden.

t2_soft darf von get_ticks nur gelesen werden, sonst gibts Ärger.



Peter

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Community,

Ich muss den Peter's TIMER32.C-Beispiel an den Atmega8515 anpassen, da 
der keinen Timer2(8Bit), sondern nur Timer0(8bit) und Timer1(16Bit) 
besitzt.
Allerdings, kommen nur 16Bit (max ca 65536) mit Timer0 per UART raus.

Peter's TIMER32.C-Beispiel  ----> Anpassung

TCCR2 = 1<<CS21; ---> TCCR0 = 1<<CS00;
TIMSK |= 1<<TOIE2; ---> TIMSK |= 1<<TOIE0;
val = t2_soft + TCNT2; ---> val = t2_soft + TCNT0;
if( (tifr & 1<<TOV2) && !(val & 0x80) ) --->  if( (tifr & 1<<TOV0) && 
!(val & 0x80) )

Insbesondere mach ich mir Sorgen um die letzte if-Schleife, weil ich sie 
noch nicht verstehe.

Könnte mir jemand bei der Anpassung weiter helfen?


MfG

Eugen

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eugen schrieb:
> Allerdings, kommen nur 16Bit (max ca 65536) mit Timer0 per UART raus.

Ein unsigned long ist 32Bit.
Aber Du mußt natürlich auch 32Bit anzeigen.


Peter

Autor: Eugen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank, Peter, für Deine schnelle Antwort.
Das stimmt, mit ultoa() klappt es.

Von allein würde ich nicht so schnell drauf gekommen.

Schöne Grüße

Eugen


P.S.
Ich lade jetzt dieses Beispiel für Neulinge wie mich hoch.

AvrStudio4.18SP3 + WinAVR-20100110
STK-500, Atmega8515L, Timer0, UART

Um Compiler-Warnungen zu vermeiden, kann man u8 in uputs() und 
uputchar() mit char ersetzen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.