Forum: Projekte & Code AVR Timer mit 32 Bit


von peter dannegger (Gast)


Angehängte Dateien:

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

:
von Paul Baumann (Gast)


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

von Thomas J. (Gast)


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

von Rolf Magnus (Gast)


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.

von peter dannegger (Gast)


Angehängte Dateien:

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

von Paul Baumann (Gast)


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?

von bitbo (Gast)


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;
}

von Peter D. (peda)


Lesenswert?

Nö, da darf nichts abgezogen werden.

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



Peter

von Eugen (Gast)


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

von Peter D. (peda)


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

von Eugen (Gast)


Angehängte Dateien:

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.

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.