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
jup thanks, wo kann ich das nachlesen, um dem das nächste mal vorzubeugen? nochmal thanks
Oder gleich
1 | TCNT0 = 0; |
schreiben. Falls GCC im Einsatz, hat der das DB schon gelesen und macht's richtig!
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?
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.
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”
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.
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...
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
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.
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 :(
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.