Forum: Mikrocontroller und Digitale Elektronik Timer zählt trotz reset


von Fabian S. (fabian727)


Lesenswert?

moin alle zusammen,

ich arbeite im mom mitm attiny 261A.

Mein einfaches ziel besteht an einem pin die Zeit zwischen zwei 
positiven Flanken zählen zu lassen. Wenn eine Flanke ankommt, wird die 
Zeit abgespeichert und der Timer0 wieder resettet.

Mein Problem:
Ich resette den Zähler. Im Debug-Modus ist das auch zu sehen, TCNT0L und 
TCNT0H sind null. Nach Start des Timers zählt der Timer aber wieder vom 
alten Wert weiter.

Wodurch kommt das? Wie kann ich das beheben?

    TCCR0B |= (1<<TSM) | (1<<PSR0);      //stop timer & reset prescaler
    TCCR0B &= ~(1<<CS02);          //really stop! no prescaler
    txbuffer[timercounter] = TCNT0L;    //safe the integer
    txbuffer[timercounter-1] = TCNT0H;
    TCNT0L = 0;                //reset timer
    TCNT0H = 0;
    for(int i = 0; i < 100; i++)      //wait that timer safes really the 
new time (0x0000)
    {
      i++;
    }
    TCCR0B &= ~(1<<TSM);      //clear the stop bit
    TCCR0B |= (1<<CS02);      //prescaler = 256


Die for Schleife kam erst im nachhinein zur Sicherheit rein, um sicher 
zu sein, dass der wert auch wirklich in den registern steht.
Zur Initialisierung nutze ich diese Funktion:
void timer0_init(void)
{
  TCCR0A |= (1<<TCW0);                //16Bit mode enabled
  TCCR0B |= (1<<PSR0) | (1<<CS02) | (1<<TSM);      //prescaler = 256 & 
stop of counting
}

danke für hilfe schon mal jetzt :D

von Stefan E. (sternst)


Lesenswert?

Fabian S. schrieb:
> TCNT0L = 0;                //reset timer
> TCNT0H = 0;

Falsche Reihenfolge.

von Fabian S. (fabian727)


Lesenswert?

jup thanks,

wo kann ich das nachlesen, um dem das nächste mal vorzubeugen?

nochmal thanks

von Stefan E. (sternst)


Lesenswert?

Fabian S. schrieb:
> wo kann ich das nachlesen, um dem das nächste mal vorzubeugen?

Datenblatt.

von Bastler (Gast)


Lesenswert?

Oder gleich
1
TCNT0 = 0;
schreiben. Falls GCC im Einsatz, hat der das DB schon gelesen und 
macht's richtig!

von Fabian S. (fabian727)


Lesenswert?

weiß jemand wo das herkommt?
klar vom tiny. Aber warum ist das so rum und nicht anders rum?
Bzw. warum gibt es eine festgelegte Reihenfolge?

von Stefan E. (sternst)


Lesenswert?

Fabian S. schrieb:
> weiß jemand wo das herkommt?
> klar vom tiny. Aber warum ist das so rum und nicht anders rum?
> Bzw. warum gibt es eine festgelegte Reihenfolge?

Steht ebenfalls alles im Datenblatt.

von Nochamal (Gast)


Lesenswert?

Fabian S. schrieb:
> weiß jemand wo das herkommt?
> klar vom tiny. Aber warum ist das so rum und nicht anders rum?
> Bzw. warum gibt es eine festgelegte Reihenfolge?

Datenblatt-TCNT0H: “Accessing Registers in 16-bit Mode”

von Mike (Gast)


Lesenswert?

Fabian S. schrieb:
> Bzw. warum gibt es eine festgelegte Reihenfolge?

Weil es so ist. Sonst mußt du dir deinen eigenen Prozessor bauen, z.B. 
mit einem FPGA, dem das egal ist.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Fabian S. schrieb:
> weiß jemand wo das herkommt?
> klar vom tiny.
Nein, es kommt von der 8-Bit AVR-Architektur, die auf ein 16-Bit 
register zugreifen muss.
Mal angenommen, es würde dieses Schattenregister nicht geben, und du 
willst das 16-Bit Timerregister auslesen. Dieser Timer steht gerade bei 
0x02FD. Dann liest du in deinem Programm mit dem 8-Bit Bus zuerst z.B. 
die obere Hälfte des Timerregisters aus. Du merkst dir also 
Highbyte=0x02. Und jetzt passierts: während des Auslesens kommt ein 
Interrupt und unterbricht das Auslesen der zweiten Hälfte. Also läuft 
während des Interrupts der Timer z.B. um 7 Schritte weiter, bis 0x0305. 
Und dann kommst du aus dem Interrupt zurück und liest die zweite Hälfte 
aus: 0x05. Zusammen sieht dein ausgelesener Zählerwert also so aus: 
0x0205. Und das ist falsch.
Jetzt könntest du sagen: dann sperre ich einfach die Interrupts beim 
Auslesen, und die Sache ist geritzt!

Zu kurz gedacht: Denn weil der Zähler ja unabhängig von deinem 
Programm weiterläuft, kann es sein, dass er zwischen den beiden 
Zugriffen um 1 hochzählt und überläuft. Der Timer hat z.B. 0x04FF. Das 
Highbyte wird ausgelesen: 0x04. Und während des Auslesens zählt der 
Timer weiter auf 0x0500. Jetzt wird das Lowbyte ausgelesen: 0x00. 
Zusammen gibt das 0x0400 --> das ist der falsche Wert.

Und nein: es bringt hier auch nichts, die Reihenfolge des auslesens 
umzudrehen. Im ersten Fall oben hättest du dann den Zählerwert 0x03FD, 
Im zweiten Fall 0x05FF. Und auch das ist beides falsch.

Und das selbe Spiel geht natürlich umgekehrt beim Schreiben auch schief. 
Das kannst du dir einfach mal selbst überlegen...

Wenn du also über einen 8 Bit Bus auf ein 16 Bit Register (das sich 
während der beiden 8 Bit Zugriffe ändern kann) konsistent zugreifen 
willst, dann musst du beim Auslesen einer der beiden Hälften von der 
anderen Hälfte einen Snapshot machen, so dass die beiden Hälften 
gleichzeitig ausgelesen werden. Und beim Schreiben musst du die andere 
Hälfte schon mal vorbereiten und in einem Schattenregister 
bereitstellen.

> Aber warum ist das so rum und nicht anders rum?
Und jetzt musst du nur noch überlegen, wleches der beiden Bytes 
sinnvollerweise zwischengespeichert werden sollte. Das ist recht 
einfach: mal angenommen, ich bräuchte nicht die ganzen 16 Bit des 
Timers, sondern nur maximal 8 Bit. Dann wäre es umständlich, wenn ich 
auf das interessante Lowbyte nur über einen Umweg zugreifen könnte. Also 
sollte ich klugerweise ohne Schattenregister direkt auf das Lowbyte 
zugreifen können.

Und genauso ist es implementiert.

BTW: wenn man den Mechanismus verstanden hat, braucht man nicht mal das 
Datenblatt, um zu wissen, wie die Reihenfolge aussieht... ;-)

Mike schrieb:
> Weil es so ist.
Nein, weil es sein muss und nur so sinnvoll ist. Und auch in einem 
eigenen Prozessor im FPGA hätte ich das selbe Problem und würde mit ein 
wenig Nachdenken auf die selbe Lösung kommen...

von Fabian S. (fabian727)


Lesenswert?

das is mal ne hammer Erklärung! Danke
Die Stelle im Datenblatt hab ich inzwischen auch gefunden. Wie ich 
finde, erklärt die das nicht so schön.

Thanks @ all

von stefanus (Gast)


Lesenswert?

Datenblätter sind halt knapp formuliert. Allerdings habe ich das schon 
als 15 Jähriger verstanden.

Naja, damals war es für Elektronik-Bastler auch normal, die Funktion 
sämtlicher 74er IC's zu verstehen und man konnte sie zumindest 
Theoretisch mit Transistoren nachbauen. Da ging man mehr in die Tiefe, 
als heute.

von mag-keine-Opis (Gast)


Lesenswert?

Ja, früher war halt alles besser, du armer, verbitterter alter Mann.

von Nochamal (Gast)


Lesenswert?

mag-keine-Opis schrieb:
> Ja, früher war halt alles besser, du armer, verbitterter alter Mann.

Früher gab es Qualität. Heute zählt Quantität :(

von Thomas E. (thomase)


Lesenswert?

Fabian S. schrieb:
> Mein einfaches ziel besteht an einem pin die Zeit zwischen zwei
> positiven Flanken zählen zu lassen. Wenn eine Flanke ankommt, wird die
> Zeit abgespeichert und der Timer0 wieder resettet.
>
> Mein Problem:
> Ich resette den Zähler. Im Debug-Modus ist das auch zu sehen, TCNT0L und
> TCNT0H sind null. Nach Start des Timers zählt der Timer aber wieder vom
> alten Wert weiter.
>
> Wodurch kommt das?
Woher das kommt, weisst du jetzt ja.

> Wie kann ich das beheben?
Indem du es gar nicht dazu kommen lässt. Zum Messen der Zeit zwischen 
dem Auftreten zweier Pegel bringt der Timer alles von Haus aus mit, was 
man dazu braucht. Dieses ganze Gehampel mit Timer anhalten und Zähler 
zurück setzen kann man sich dabei komplett sparen.
Port PA4 kann alternativ als ICP0 benutzt werden. Lies dir im Datenblatt 
dazu das Kapitel "16-Bit Input Capture Mode" durch. Diese Funktion ist 
genau für deine Aufgabenstellung gemacht.
Der Timer Counter muss auch nicht zurück gesetzt werden. Die 
16-Bit-Arithmetik sorgt von selbst dafür, dass du den richtigen Wert 
erhältst, wenn du den ersten Wert vom zweiten Wert subtrahierst.

Mfg.

von Klaus I. (klauspi)


Lesenswert?

stefanus schrieb:
> Naja, damals war es für Elektronik-Bastler auch normal, die Funktion
> sämtlicher 74er IC's zu verstehen und man konnte sie zumindest
> Theoretisch mit Transistoren nachbauen. Da ging man mehr in die Tiefe,
> als heute.

Damals war so ein Logik-IC ja auch noch eine richtige Investition und 
man musste in sich vom Munde absparen ;o)
Da konnte man viel Lesen bis man sich den nächsten leisten konnte.

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.