Hallo, ich hab folgendes Problem: ich möchte mit einem ATmega1284P eine LED alle 1,3sec für 100ms leuchten lassen. Dazu muss der 8Bit Timer2 verwendet werden. Die zwei 16bit Timer und der andere 8bit Timer werden schon anderweitig gebraucht. Meine Taktfrequenz sind 20 MHz. Einen zusätzlichen Takt für den Timer anzulegen ist nicht möglich, da ich keinen Pin mehr frei habe. Nun meine Frage: Ist es überhaupt möglich eine Frequenz von 0,769Hz unter den oben genannten Bedingungen zu erzeugen? Bei einem Vorteiler von 1024, komme ich höchstens auf eine Periodendauer von 13,056ms. Also weit weg von meinen gewünschten 1,3sec. Könnte man mit Interrupts etwas erreichen? Ich habe keine Ahnung. Vielleicht hat jemand ja eine Idee. Gruß Wheels
Mach doch mit Deinem 8-Bit-Timer einen 1ms-Interrupt. Alle 1ms zaehlst Du dann ein Register hoch, wenn es 1300 hat, machst Du ne LED an, wenn es 1400 hat, machst die LED aus und setzt das Register auf 0. Nur so als Beispiel... beliebig aenderbar. Was würde dagegen sprechen?
Also du musst ja die LED nicht bei jedem Timerdurchgang schalten. Zähl einfach bei jedem Timerdurchgang eine Variable hoch, wenn du lange genug gezählt hast (bis 1.3s um sind) schaltest du deine LED ein. Brauchst auch keinen extra Timer für das.
Ich bin noch neu auf dem Gebiet. Würde ein solcher Interrupt mein Hauptprogramm unnötig aufhalten? Das hätte ich dazu schreiben müssen. Mein Programm sollte nämlich so weit es geht nicht durch ein delay oder ähnliches aufgehalten werden. Ein Timer läuft ja so nebenher ohne den eigentlichen Programmablauf zu verzögern.
ja der programmablauf wird schon "verzögert" aber nur um wenige takte kommt ganz drauf an wie viel du in den interrupt rein schreibst
"Die zwei 16bit Timer und der andere 8bit Timer werden schon anderweitig gebraucht. " Mhm, dann hast Du Dich doch schon damit beschaeftigt, oder? - Also, klar, wie mein Vorredner sagte, brauchst Du vielleicht auch gar nicht einen Extra-Timer dafuer, wenn z.B. die anderen schon einen brauchbaren "Takt" erzeugen. Ja, Timer laufen nebenher und brauchen nur Zeit zum initialisieren (aber das geht ja fix und muss nur am Anfang einmal gemacht werden. Wenn er läuft, unterbricht er dann halt den Programmablauf mit einem Interrupt und führt eine Interruptroutine aus, die dann dementsprechend kurz gehalten werden sollte. - Oder er schaltet irgendwas an - oder aus, wenn er einen bestimmten Zaehlerstand erreicht hat, dann "stoert" er das Hauptprogramm noch weniger. Lies doch mal im Tutorial oder im Datenblatt was ueber Timer, das hilft!
Wheels C. schrieb: > Würde ein solcher Interrupt mein Hauptprogramm unnötig aufhalten? Weiss nicht, was muss dein Hauptprogramm denn Superwichtiges erledigen? :o) Du hast ein MC mit 20Mhz, das Ding rattert also >16 Millionen Instruktionen jede Sekunde ab. Wenn du jetzt alle 100ms noch eine ISR abarbeitest mit 1k oder 10k Instruktionen, "so what"?! Pollst du in der main(), oder was gibt's da zeitkritisches zu erledigen? Könnte das auch IRQ gesteuert gemacht werden (Flanke triggern o.ä.)?
Ok,danke erstmal. Ich denk ich werde beide Varianten (Interrupt und Variable inkrementieren) mal ausprobieren. Aber erst morgen. heute bekomme ich's nicht mehr hin. Nicht mit meiner Birne. Wünsche euch noch nen schönen Abend Grüße
Na dann gute Nacht und viel Erfolg morgen!
eigentlich ist das nur eine möglichkeit du musst in dem interrupt eine variable inkrementieren.
Guten Morgen allerseits, hab mal folgenden Programmcode ausprobiert. Im Moment noch ohne Interrupt.
1 | while(1){ |
2 | |
3 | if (TCNT2 == 0xFF) |
4 | {
|
5 | i++; |
6 | }
|
7 | |
8 | if (i==50) //Periodendauer 1,3s = 50 Overflows *26,112ms |
9 | {
|
10 | PORTB|=LED_G; |
11 | i=0; |
12 | }
|
13 | |
14 | else if (i==4) //ca. 100ms |
15 | {
|
16 | PORTB &= ~LED_G; |
17 | }
|
18 | |
19 | }
|
Zum Testen läuft er bei mir als Hauptprogramm. Benutzt habe ich PWM, Phase Correct (Modus 1) mit einem Vorteiler von 1024. Die Sache ist nur die, dass die kommentierten Zeiten mit meiner Blinkfreuqenz gar nicht zusammen passen. Die LED blinkt mit gefühlten 2Hz anstatt alle 1,3sec und hat zudem regelmäßige Ausetzer. Hab beim besten Willen keine Ahnung woran das wieder liegt. Hat es vielleicht mit dem i=0 etwas zu tun?
Wheels C. schrieb: > Guten Morgen allerseits, > > hab mal folgenden Programmcode ausprobiert. Im Moment noch ohne > Interrupt. > >
1 | > while(1){ |
2 | >
|
3 | > if (TCNT2 == 0xFF) |
4 | > { |
5 | > i++; |
6 | > } |
7 | >
|
8 | > if (i==50) //Periodendauer 1,3s = 50 Overflows *26,112ms |
9 | > { |
10 | > PORTB|=LED_G; |
11 | > i=0; |
12 | > } |
13 | >
|
14 | > else if (i==4) //ca. 100ms |
15 | > { |
16 | > PORTB &= ~LED_G; |
17 | > } |
18 | >
|
19 | > } |
20 | >
|
> Zum Testen läuft er bei mir als Hauptprogramm. Benutzt habe ich PWM, > Phase Correct (Modus 1) Wozu? Dir ist schon klar, dass im Phase Correct Modus der Timer so zählt: 0, 1, 2, 3, 4, ..... 253, 254, 255, 254, 253, 252, ...., 4, 3, 2, 1, 0 Das ist je gerade der Witz am Phase Correct Modus Spar dir diesen Unsinn, den Timerwert in der Hauptschleife abzufragen. Häng dich an einen Interrupt und gut ists. Wenn du Pech hast, zählt der Timer in der Zwischenzeit um 2 weiter während dein Programm etwas anderes tut und du wirst deinen Timer nie bei einem bestimmten Zählerstand antreffen, weil du einfach nicht oft genug hinsiehst.
Weiss ich, aber wenn ich immer bei TCNT==0xFF inkrementiere ist das doch genau ein Timerdurchlauf. Also 20MHz/(1024*510)=26,112ms. (steht so auch im Handbuch) Und 26,112ms*50Inkremente sollten ca. 1,3s sein. Ein Interrupt mach ich noch. Ich wollte erst einmal die ganze Sache so testen. Würde sich mit einem Interrupt dieser Effekt denn nicht zeigen? Dort macht das Programm doch auch nichts anderes als in meiner while-Schleife?
Junge, du gehörst wohl auch zu denen, die das alte Sprichwort beherzigen: "Warum einfach, wenn es auch kompliziert geht?"
Wheels C. schrieb: > Weiss ich, aber wenn ich immer bei TCNT==0xFF inkrementiere Die Frage ist, ob du dein Programm das sieht, dass TCNT2 gleich 0xFF ist. An einem Beispiel: Wenn du immer bei einer vollen Minute etwas machen willst aber nur alle 7 Sekunden auf die Uhr siehst, dann wirst du die Zeigerstellung: 0 verpassen. Du siehst auf die Uhr bei 0, 7, 14, 21, 28, 35, 42, 49, 56, 63 Ooops. Bei 60 wäre eine Aktion fällig gewesen. Und du hast sie verpasst. Daher Interrupt: Den kannst du nicht verpassen
Oh schon gut hab's grade begriffen. Dein 'nicht oft genug hinschauen' hat bei mir das entscheidenen Klick gegeben. Danke. Also ich werd's dann mit Interrupt machen Grüße
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.