Hallo,
ich habe einen ATMEGA8 im Einsatz mit einem LCD Display.
Die Anzeige funktioniert ohne Probleme. Jetzt möchte ich gerne eine
Zeitmessung über zwei Taster realisieren die an den PIN B0 und B1
hängen.
Soweit ich mich eingelesen habe, sollte das über den TIMER Interupt
realisiert werden, allerdings komme ich gerade nicht weiter.
Ich habe da ein paar Verständnisprobleme zum Ablauf. Der TIMER soll
durch die Betätigung von Taster 1 gestartet werden. Danach springt er in
die ISR und inkremmentiert die variablen. Eigentlich soll er mir während
dessen schon die variable Sekunde anzeigen. Nachdem der Zähler einmal
durch ist springt er wieder in die while schleife?
Hier erstmal mein Code:
Peter W. schrieb:> mit einem LCD Display.
Also sozusagen mit einem Liquid Crystal Display Display.
Also ein Display das ein Liquid Crystal Display anzeigt?
Neue Technologie?
Dumpf Backe schrieb:> Peter W. schrieb:>> mit einem LCD Display.>> Also sozusagen mit einem Liquid Crystal Display Display.>> Also ein Display das ein Liquid Crystal Display anzeigt?>> Neue Technologie?
Danke für deine Hilfe. Dein Name ist anscheinend Programm, auch wenn du
ihn nicht richtig schreiben konntest.
Vielleicht habe ich deine Aufgabenstellung nicht ganz verstanden,
aber mir scheint, du machst es sehr umständlich!
Lass doch einfach den Timer und seine Stoppuhr-Register
die Zeit zählen (ms ss mm / hh ) - das machst du doch schon
ganz richtig per ms-Interrupt.
Wenn du jetzt die Zeit von Taste 1 (Start) gedrückt, bis
Taste 2 (Stopp) gedrückt anzeigen willst, mach es so:
Programmstart: Stoppuhr-Register = NULL, Zähler Stopp (CS = 0)
Zähler Start: Stoppuhr-Register = NULL, dann
Zähler Start: CS = passender Prescaler
Zähler Stopp: (CS = 0)
Stoppuhr-Register bleiben auf dem letzten Wert
Dann kannst du jederzeit (am Besten getaktet von einem
anderen Timer) die Zeitregister auslesen und anzeigen.
Gute Nacht erst mal
So habe meinen Fehler gefunden. Das lcd_clear() hat das Display ständig
gelöscht und deswegen wurde nichts angezeigt.
Habe noch ein Verständnisproblem. Wenn ich 1msek inkrememntieren will,
wie muss ich dann meinen Systemclock und alles einstellen
Anbei mein jetziger Code.
Wenn du eine Millisekunde dekrementieren oder inkrementieren möchtest,
dann must du einen Timer so mit einem Wert setzen, das der nach einer
Millisekunde einen Überlauf hat. Der Überlauf löst dann einen Interrupt
aus und dann kannst du auch Inkrement oder Dekrement oder was auch
sonnst du damit machen möchtest...
Der Haupttakt spiel dabei keine Rolle. Du mußt nur den Timerwert des
Zählers den du setzt bevor Überlauf stattfindet, so setzen das es passt.
Bei langsamen Haupttakt näher an 65535 (oder 255 bei 8-Bit Timer, wenn
8-Bit überhaupt reichen!), bei schnellerem Haupttakt weiter weg von
65535.
Beispiel bei z.B. 10MHz Haupttakt hast du 100nS bei einem Takt. Wenn du
nun also 1mS haben möchtest, benötigst du also nach Adam Riese 10000
Takte.
Dann rechne 65536 - 10000 = 55536. Diese 55536 setzt du jedes mal in der
Überlauf- Interrupt Routine in die Timer Register H und L. Dann wird der
Überlaufinterrupt auch immer alle 1mS aufgerufen werden. Nämlich immer
nach 10000 Takten.
Peter W. schrieb:> //Eingänge der Taster B0 und B1> DDRB = 0x00;> PORTB = 0x00;
Die Ports sind falsch initialisiert. Hier müssen die internen PullUps
eingeschaltet werden, sonst floaten die Inputs und die Interupts werden
zufällig ein- bzw. ausgeschaltet, wenn keine Taste gedrückt wurde.
Leider hast du nicht geschrieben, ob die Taster die Input Pins auf HIGH
(5V) oder LOW (GND) ziehen. Wenn die internen Pull-Ups benutzt werden,
dann müssen die gegen GND ziehen
Reiner_Gast schrieb:> Peter W. schrieb:>> //Eingänge der Taster B0 und B1>> DDRB = 0x00;>> PORTB = 0x00;>> Die Ports sind falsch initialisiert. Hier müssen die internen PullUps> eingeschaltet werden, sonst floaten die Inputs und die Interupts werden> zufällig ein- bzw. ausgeschaltet, wenn keine Taste gedrückt wurde.>> Leider hast du nicht geschrieben, ob die Taster die Input Pins auf HIGH> (5V) oder LOW (GND) ziehen. Wenn die internen Pull-Ups benutzt werden,> dann müssen die gegen GND ziehen
Hallo Reiner,
die Taster sind wie im Tutorial gegen GND angeschlossen. Bislang hab ich
mit den Tastern keine Probleme. Sie lösen den Interupt aus.
Ben schrieb:> Beispiel bei z.B. 10MHz Haupttakt hast du 100nS bei einem Takt
Hallo Ben,
was heißt das für mein Bsp mit 1Mhz Systemtakt.
Und heißt es nicht T=1/f ? Also T= 1/1 MHz = 1*10^-6 s = 1 mikrosekunde
Wie muss ich dann den Prescaler wählen und den Vergleichswert für den
CTC.
Peter W. schrieb:> Und heißt es nicht T=1/f ? Also T= 1/1 MHz = 1*10^-6 s = 1 mikrosekunde> Wie muss ich dann den Prescaler wählen und den Vergleichswert für den> CTC.
Der Prescaler muss auf 8 gesetzt werden. OCR2 auf 149 (es wird ab 0
gezählt)
BTW: Was funktioniert denn genau nicht?
Reiner_Gast schrieb:> BTW: Was funktioniert denn genau nicht?
Also aktuell startet der Timer mit Taster 1 und Stoppt mit Taster 2.
Leider sind die Zeiten nicht annähernd an der Realität. Und ich bin mir
gerade gar nicht so sicher wie mein Systemclock ist, da ich ohne
externen Oszillator arbeite. Vermutlich hat der ATMEGA8 dann 8 MHz mit
Werkseinstellung?
Ich komme einfach mit der Rechnung nicht klar, wie ich auf 1ms kommen
kann.
Reiner_Gast schrieb:> Der Prescaler muss auf 8 gesetzt werden. OCR2 auf 149 (es wird ab 0> gezählt)
Das sieht jetzt schon besser aus. Kannst du mir die Rechnung erklären?
Peter W. schrieb:> Vermutlich hat der ATMEGA8 dann 8 MHz mit> Werkseinstellung?
Ein neuer ATMega8 wird mit dem internen RC Oszillator auf 1MHz gesetzt
ausgeliefert.
willst du jetzt z.B. im CTC Modus so gut es geht auf 1ms Ticker kommen,
dann kannst du z.B. den Vorteiler des Timers 2 auf 8 setzen (125 kHz
Takt am Timer) und ihn dann bis 125 zählen lassen (OCR2 auf 124 setzen).
Damit tickt der Timer mit 1kHz = 1ms Periode die ISR.
Du kannst auch Timer 1 benutzen, Vorteiler auf 1 setzen und ihn bis 1000
zählen lassen. Aber Timer 1 ist 'der Beste' im Mega8 und kann auch für
andere Dinge benutzt werden.
Der interne RC Oszillator ist nicht super genau. Abweichungen von den
nominellen 1 MHz sind normal und auch von der Umgebungstemperatur
abhängig.
Peter W. schrieb:> Das lcd_clear() hat das Display ständig> gelöscht und deswegen wurde nichts angezeigt.
Ja, das ist eine völlig überflüssige Funktion, die aber leider in jedem
Beispielcode einem Anfänger förmlich aufgezwungen wird.
In der Praxis überschreibt man einfach den alten mit dem neuen Text.
Damit bei kurzen Zahlen kein Rest stehenbleibt, benutzt man für die
Ausgabe vorzugsweise sprintf und gibt die maximale Länge der Zahl an.
Peter W. schrieb:> Reiner_Gast schrieb:>> BTW: Was funktioniert denn genau nicht?>> Also aktuell startet der Timer mit Taster 1 und Stoppt mit Taster 2.> Leider sind die Zeiten nicht annähernd an der Realität. Und ich bin mir> gerade gar nicht so sicher wie mein Systemclock ist, da ich ohne> externen Oszillator arbeite. Vermutlich hat der ATMEGA8 dann 8 MHz mit> Werkseinstellung?>> Ich komme einfach mit der Rechnung nicht klar, wie ich auf 1ms kommen> kann.
Wie oben schon gesagt... das kann daran liegen, dass die Inputs evtl.
floaten, d.h. keinen definierten Zustand haben, wenn keine Taste
gedrückt wird. Dann kann zufällig der Timer IRQ ein- oder ausgeschaltet
werden. D.h. wenn eigentlich der IRQ mit dem taster eingeschaltet wurde,
können durch die ganzen Ein- und Abschaltungen des IRQ einfach etliche
IRQ nicht gezählt worden sein... Ich würde das mal prüfen.
Ohne Schaltplan kann ich dir dabei aber nicht weiterhelfen.
Peter W. schrieb:> Vermutlich hat der ATMEGA8 dann 8 MHz mit> Werkseinstellung?
Ich weiß nicht, wie es bei den ATMEGA8 ist, aber bei allen ANTINY84/85
und ATMEGA328/644 war die Werkseinstellung immer der interne 8MHz Oszi
und der Teiler durch 8 durch die Fuse CLK/8 gesetzt... Das macht dann 1
MHz Takt
Da schaust du mit dem AVR Studio am besten mal nach, wie die Fuses
eingestellt sind.
Je nach dem, was dabei rauskommt, berechnet sich auch der Prescale und
der Wert für OCR2, das hat Matthias S. ja schon gut beschrieben.
Reiner_Gast schrieb:> Ich weiß nicht, wie es bei den ATMEGA8 ist, aber bei allen ANTINY84/85> und ATMEGA328/644 war die Werkseinstellung immer der interne 8MHz Oszi> und der Teiler durch 8 durch die Fuse CLK/8 gesetzt... Das macht dann 1> MHz Takt
Das ist beim alten Mega8 noch etwas anders. Der hat einen internen RC
Oszillator, den man auf 1, 2, 4 oder 8 Mhz fusen kann. Genau wie bei den
neueren AVR ist er aber werksseitig konservativ auf 1MHz eingestellt.
Peter W. schrieb:> ISR (TIMER2_COMP_vect)> {> millisekunden++;> if(millisekunden == 1000)> {> sekunde++;> millisekunden = 0;> if(sekunde == 60)> {> minute++;> sekunde = 0;> }> }
Ich habe mir jetzt mal ein Oszilloskop besorgt und würde ganz gerne an
PB3 als Ausgang immer den Takt der Millisekunden ausgeben. Ich weiß grad
gar nicht wie ich am besten die Ausgabe realisiere. Ich müsste eine ms
PB3 auf 0 und dann eine ms wieder auf 1 legen, damit ich am Oszi den
Takt erkennen kann.
Hat jemand einen Tipp zur Realisierung?
Und wie funktioniert das? Also wie trifft er die Entscheidung zu Low
oder High. Hatte mir jetzt überlegt mit dem Modulo Operator nach Gerade
oder Ungerade zu unterscheiden und dann den Port Low oder High zu
schalten.
Peter W. schrieb:> Und wie funktioniert das?
Der Exclusiv-Oder Operator invertiert genau das Bit oder die Bits, die
Du in der Maske ausgewählt hast.
Wenn du wissen willst, wie der µC das genau macht, dann musst du im
Maschinencode des Compilers nachschauen.
> Also wie trifft er die Entscheidung zu Low> oder High. Hatte mir jetzt überlegt mit dem Modulo Operator nach Gerade> oder Ungerade zu unterscheiden und dann den Port Low oder High zu> schalten.
Das geht natürlich auch, ist aber umständlicher.
Übrigens ergibt dieses toggeln jede Millisekunde eine Frequenz von 500Hz
- nicht das du dich beim messen wunderst...)