Hallo Erstmal möchte ich anmerken dass ich anfänger in uController programmierng bin. Mit Hilfe des Totorial is es mir schon gelunden eine led auf meinem board blinken zu lassen, allesdings nur mit dem Wait befehl. Jetz möchte ich dass ganze mit Timer realisieren...leider bis jetzt ohne erfolg. Ich habe mir schon von der ATMEL Page die Docu geholt. Ehrlich gesagt check ich nicht wirklich viel. Kann mir jemand erklähren wie dieser 8 Bit Timer/Counter funktioniert und wie ich eine LED zum blinken bringen kann? Da ich vor einigen jahren mal c gelernt habe würd ich es vorziehen in C zu programmieren Danke für Eure Antworten Peter
Im Grunde ist das ziemlich einfach. Ein Timer ist einfach nur ein Stück Hardware. Ein Zähler der vor sich hinzählt. Wie schnell dieser Zähler zählt wird mit dem Vorteiler eingestellt. Je nach eingestelltem Vorteiler wird der Systemtakt (also die Quarzfrequenz) durch genau diesen Faktor dividiert und mit dieser runtergesetzten Frequenz zählt dann der Timer. In dem Moment wo du einen Vorteiler setzt, zählt der Timer auch schon. Setzt du den Vorteiler auf 0 hört der Timer wieder auf zu zählen. Was kann man nun mit dem Timer machen? (Ohne Anspruch auf Vollständigkeit) Zuallererst kann man natürlich auf das Zählregister zugreifen. Super. Aber meist nicht sehr sinnvoll. Timer werden ja eingesetzt um eben nicht in einer Schleife Wartezeit zu verbrutzeln. Wenn ich aber in einer Schleife ständig das Zählregister überprüfe und warte bis das einen gewissen Wert erreicht hat, mach ich doch genau dasselbe. Das kanns also nicht sein. Aber Timer haben noch ein paar andere nette Features. Einer davon ist der Overflow Interrupt. Was'n das? Overflow: Jeder Timer hat nur eine bestimmte Bitgröße. Zb. Ist der Timer0 ein 8 Bit Timer. Das heist er zählt von 0 bis 255 (255 ist die größte Zahl, die mit 8 Bit gerade noch darstellbar ist). Und dann? Dann passiert ein Überlauf (engl. overflow) und der Timer fängt wieder bei 0 an. Das Interessante an der ganzen Sache ist nun, dass dieser Overflow einen Interrupt auslösen kann. Was'n ein Interrupt? Ein Interrupt ist eine 'Unterbrechung'. Das heist der µC lässt alles stehen und liegen womit er gerade beschäftigt ist und führt eine spezielle Funktion aus. Ist er mit der Abarbeitung dieser Funktion fertig, dann nimmt er seine Arbeit wieder dort auf, wo er unterbrochen wurde. Die Kombination aus beidem bewirkt jetzt, dass man bei einem Overflow des Timers eine bestimmte Funktion ausführen lassen kann. Das passiert immer, egal womit der µC gerade beschäftigt ist. Mit 2 Einschränkungen: * Die Interrupts müssen generell freigegeben sein * Eine Interrupt Funktion kann selbst nicht durch einen Interrupt unterbrochen werden. Die Funktion wird zuende gebracht und erst danach wird der neue Interrupt bearbeitet. (Das stimmt nicht ganz, aber fürs Erste belassen wir es mal dabei). Soweit die Einführung. Wie sieht das jetzt konkret in C, am Beispiel WinAvr avr-gcc aus? Zb. So #include <avr\io.h> #include <avr\interrupt.h> ISR( TIMER0_OVF_vect ) { PORTB ^= 0xFF; } int main() { DDRB = 0xFF; PORTB = 0x00; TCCR0 = ( 1 << CS01 ) | ( 1 << CS00 ); TIMSK = ( 1 << TOIE0 ); sei(); while( 1 ) { } } Die Programmausführung beginnt, wie immer bei main(). Dort richte ich zunächst mal einen Port her um dort eine Ausgabe machen zu können. Ich nehm einfach mal den kompletten Port als Ausgabe (DDRB = 0xFF;) und geh davon aus, dass zumindest an einigen davon eine LED angeschlossen ist. TCCR0 = ( 1 << CS01 ) | ( 1 << CS00 ); Hier wird der Vorteiler des Timers gesetzt. Aus dem Datenblatt ist ersichtlich, dass ein Setzen der Bits CS01 und CS00 den Systemtakt durch 64 teilt. Durch setzen von anderen Bits könnte man auch andere Teilfaktoren erreichen. Nachdem der Teiler gesetzt ist, beginnt der Timer auch schon fröhlich vor sich hin zu tuckern. TIMSK = ( 1 << TOIE0 ); Das hier setzt das Bit, dass für den Overflow Interrupt zuständig ist. Sobald also am Timer ein Overflow auftritt, wird ein Interrupt ausgelöst. Der macht aber noch nichts, da die Interrupts generell noch nicht freigegeben sind. sei(); behebt dieses (sei = Set Enable Iterrupt). Ab jetzt ist alles scharf und ein Overflow würde einen Interrupt auslösen den der µC auch mit einer speziellen Funktion, dem sog. Interrupt Handler, abarbeiten wird. In main() bleibt nichts mehr zu tun, also schicken wir den µC in eine Schleife, in der er bis zum St. Nimmerleinstag hängt: while( 1 ) { } Soweit so gut. Tritt jetzt am Timer ein Overflow ein, so wird eine speziell Funktion, der Interrupt Handler aufgerufen. Hier ist er vereinbart: ISR( TIMER0_OVF_vect ) { Das ISR ist obligatorisch, und sagt dem Compiler, dass das hier keine normale Funktion, sondern ein Interrupt Handler ist. Das TIMER0_OVF_vect sagt ihm auch noch, welcher Interrupt Handler gemeint ist. Ein AVR kann viele verschiedene Interrupts auslösen, wir wollen aber den Overflow des Timers 0 haben. Und in dem Handler? { PORTB ^= 0xFF; } Da schalte ich einfach den Ausgang vom PORTB um. Wenn an einem Pin bisher eine 0 war, dann wird eine 1 daraus und umgekehrt. Eine angeschlossene LED wird also entweder ein oder aus geschaltet, bei jedem Aufruf des Interrupt Handlers immer anders rum. Und das wars dann auch schon. Wie schnell blinkt nun die LED. Lass uns mal rechnen. Sagen wir mal dein µC arbeitet mit 1 Mhz. Wie schnell zählt dann der Timer? Der Vorteiler ist momentan auf 64, dh. der Timer zählt mit einer Frequenz von 1000000 / 64 = 15652 Hz Um einen Ocerflow auszulösen, muss der Timer einmal von 0 bis 255 zählen, also 256 Zählschritte ausführen. Ergo 15652 / 256 = 61,irgendwas Hz Mit dieser Frequenz wird die Led ein und ausgeschaltet. DIe Flackerfrequenz beträgt also 61 / 2, also knapp 30 Hz Deine Led flackert also bei 1 Mhz Taktfrequenz mit knapp 30 Hz bei einem Vorteiler von 64. Das wirst du nicht sehen können. Aber mann kann ja auch einen größeren Vorteiler nehmen :-)
Hallo Karl Heinz Danke erstmal für die Ausführliche Antwort. Das Hilft mir schon sehr weiter. Wenn man als Anfänger in die Thematik reinkommen will ist das ziemlich mühsehlich. Hab gestern 5 Stunden die Atmel Referenz studiert bin aber auf keinen grünen zweig gekommen. Mein letzendlches ziel soll eine Frequenzmessung eines rechtecksignals sein. Ich hab gesehn das der 16 Bit counter eine möglichkeit bietet den zähler mittels steigernder flanke zu starten und zu stoppen hast du da auch einen Tip für mich? mfg
Du meinst wahrscheinlich den Capture-Modus. Dabei wird der Zähler aber nicht gestartet oder gestoppt, sondern er läuft durch und bei den entsprechenden Flanken am Capture-Eingang wird der aktuelle Stand des Zählers in das Capture-Register kopiert. Da dies hardwaremäßig geschieht, also ohne Verzögerung durch eventuell gerade ablaufende Prozesse, ist das eine sehr präzise Methode. Zu dem Thema gab es hier schon eine ganze Reihe Threads. Gib mal "Capture" und/oder "Frequenzmessung" in die Betreffsuche ein, da wirst Du geholfen...
BTW: Bei der Suche am besten im µC/Elektronik-Forum suchen. Da gibts erheblich mehr Beispiele. Und natürlich auch mal in der Codesammlung schauen.
Input capture eignet sich aber letztlich nur (sinnvoll) zur Messung eher kleiner Frequenzen. Große Frequenzen misst man, indem man sie extern in einen Timer (der dann eher zum Counter wird) einspeist und mit einem zweiten Timer (Referenzzeit) dann den ersten startet und anhält. Die Anzahl der gezählten Impulse ist dann proporzional zur Frequenz.
Hallo, habe noch eine Frage zu diesem Thema. Habe den Timer wie oben beschrieben realisieren können, der Quarz den ich benutzt habe hatte allerdings 16Mhz, bei dem größten Vorteiler komme ich dann auf eine Frequenz von ca. 60 Hz. Das ist mir aber noch zu groß, mit welcher Methode teilt ihr eure Frequenz noch weiter runter? Da gibt es bestimmt mehrere Möglichkeiten, brauche nur einen kleinen Schlag auf den Hinterkopf. Danke
Guest wrote: > Hallo, > > habe noch eine Frage zu diesem Thema. Habe den Timer wie oben > beschrieben realisieren können, der Quarz den ich benutzt habe hatte > allerdings 16Mhz, bei dem größten Vorteiler komme ich dann auf eine > Frequenz von ca. 60 Hz. > Das ist mir aber noch zu groß, mit welcher Methode teilt ihr eure > Frequenz noch weiter runter? Da gibt es bestimmt mehrere Möglichkeiten, > brauche nur einen kleinen Schlag auf den Hinterkopf. <klap> Nichts und niemand hindert dich daran, selbst nochmal einen Zähler in die ISR einzubauen und deine LED-Umschalte nur dann zu machen, wenn die ISR zum, sagen wir mal, 5-ten mal aufgerufen wurde. Reicht der Klaps oder brauchst du's mit der groben Keule? :-)
da ist wohl was dran, dachte man müßte in den allgemeinen Timer-Einstellungen den ISR einfach noch seltener auslösen lassen oder so. Vielen Dank
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.