Forum: Mikrocontroller und Digitale Elektronik Led mit 8Bit-Timer alle 1,3s für 100ms aufleuchten lassen


von Wheels C. (wheels)


Lesenswert?

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

von franz (Gast)


Lesenswert?

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?

von Spanner (Gast)


Lesenswert?

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.

von Wheels C. (wheels)


Lesenswert?

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.

von Daniel (erfolgstyp)


Lesenswert?

ja der programmablauf wird schon "verzögert" aber nur um wenige takte 
kommt ganz drauf an wie viel du in den interrupt rein schreibst

von franz (Gast)


Lesenswert?

"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!

von Tom M. (tomm) Benutzerseite


Lesenswert?

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.ä.)?

von Wheels C. (wheels)


Lesenswert?

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

von franz (Gast)


Lesenswert?

Na dann gute Nacht und viel Erfolg morgen!

von Daniel (erfolgstyp)


Lesenswert?

eigentlich ist das nur eine möglichkeit du musst in dem interrupt eine 
variable inkrementieren.

von Wheels C. (wheels)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Wheels C. (wheels)


Lesenswert?

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?

von Ohje (Gast)


Lesenswert?

Junge, du gehörst wohl auch zu denen, die das alte Sprichwort 
beherzigen: "Warum einfach, wenn es auch kompliziert geht?"

von Karl H. (kbuchegg)


Lesenswert?

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

von Wheels C. (wheels)


Lesenswert?

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
Noch kein Account? Hier anmelden.