Hallo, ich versuche gerade einen ganz einfachen Timer zu programmieren. Ausrüstung: Atmega 8515, 4Mhz Quarz, AVR-Studio, GCC. Es will einfach nicht funktionieren. Ich kann mit dem AVR Studio ja schön simulieren und habe festgestellt, dass die 100 an die Funktion wartems nicht weitergegeben wird. Siehe Bild1.jpg. Mir ist der Verdacht aufgekommen, dass eventuell der Simulator Bugs hat und habe das Programm auf den Controller gespielt. Funktioniert aber auch nicht. Habe ich irgend wo was vergessen? Jürgen PS: timer.c ist das Hauptprogramm
Hallo Schau dir mal warteus an. Kommst du da jemals wieder raus. timer bleibt immer 0 und somit immer kleiner timerus (falls > 0) Warum werden solche wartezeiten eigentlich immer neu erfunden?? Gruß Joachim
Joachim schrieb: > Hallo > > Schau dir mal warteus an. Kommst du da jemals wieder raus. > timer bleibt immer 0 und somit immer kleiner timerus (falls > 0) Das ist nicht der Grund. timer ist eine globale Variable, die in der ISR erhöht wird. > TCCR0 &= ~(1<<CS01)|(1<<CS00); // Kein Prescaler Ein Timer läuft, sobald du einen Prescaler zuweist. Hat der Timer einen Prescaler von 0, so läuft er auch nicht. Ein Timer der nicht läuft, zählt auch nicht. Ein Timer der nicht zählt generiert auch keine Overflows. Keine Overflows, keine ISR. Den Rest kannst du dir denken
Danke für die Antworten. ich habe das Programm folgender masen verändert:
1 | TCCR0 &= ~(1<<CS02)|(1<<CS01); // Kein Prescaler |
2 | TCCR0 |= (1<<CS00); |
Jetzt funktionierts zwar auf dem Controler aber die Simulation stimmt immer noch nicht. Auserdem stimmt die Wartezeit nicht. Eine Periode (Also LED an, LED aus) dauert 1.86s. Deshalb wollte ich ja eine eigene Routine machen um eine genaue Zeit zu bekommen. Wo habe ich falsch gedacht?
Jürgen schrieb: > Wo habe ich falsch gedacht? µC sind zwar schnell. Aber so schnell auch wieder nicht. Du gibst dem Timer genau 4 Taktzyklen Zeit ehe er den nächsten Overflow auslösen soll. 4 Takte, da ist der Inhalt deiner ISR schon länger. Kurz gesagt: Deine Vorgaben sind nicht erfüllbar.
Ohh, da übervordere ich ihn ein bischen. :-) muss ich woll ein wennig umrechnen. Aber wieso funktioniert es in der Simulation nicht? Danke.
Wenn ich den Timer mit 216 vorlade, dauert es 10µs bis der nächste Interrupt kommt. Ist das besser?
Au´s dem Bauch heraus: 40 Takte ist immer noch verdammt wenig. Und gewöhn dir den Quatsch mit Vorladen am besten gleich wieder ab, wenn du halbwegs vernünftige Timings haben willst (zumindest bei einem Vorteiler von 1). Vom Zeitpunkt wenn der Timer seinen Overflow auslöst, bis er sich zum ISR Aufruf bequemt, bis du in der ISR die Kontrolle kriegst ... da vergeht alles Zeit. Zeit in der der Timer in der Zwischenzeit weitergezählt hat. Zähltakte die du aber nirgends berücksichtigt. Wenn man eine Timer-ISR braucht, die abweichend von der Breite des Timers (8Bit oder 16 Bit) aufgerufen wird, dann nimmt man den CTC-Modus des Timers dafür.
Danke, CTC-Modus, interessant. Wir in der Schule haben immer nur den einen Timer verwendet. CTC-Modus werde ich mir morgen mal anschauen. Fühle mich bei euch gut aufgehoben. Gute Nacht und nochmals Danke.
Jürgen schrieb: > Danke, CTC-Modus, interessant. Wir in der Schule haben immer nur den > einen Timer verwendet. CTC-Modus werde ich mir morgen mal anschauen. http://www.mikrocontroller.net/articles/AVR-Tutorial:_Uhr
Hallo, hab mich jetzt ein wennig reingelesen. Jetzt funktioniert´s auch. Aber ich weis nicht warum. :-)
1 | #include <stdint.h> |
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | #include "warten.h" |
5 | #include "var.h" |
6 | |
7 | ISR(TIMER0_COMP_vect) |
8 | {
|
9 | timer ++; |
10 | }
|
11 | |
12 | //Hauptprogram
|
13 | |
14 | int main(void) |
15 | {
|
16 | //Ein - Ausgänge Definieren
|
17 | |
18 | DDRC = 0xff; //PORTC Ausgang (LEDs) |
19 | PORTA = 0xff; //PORTA Pullup aktivieren (Taster) |
20 | |
21 | DDRD = 0xff; //PORTD (Display Daten) auf Ausgang setzten |
22 | DDRB = 0x07; // Asugänge schalten für Display RS/RW/E |
23 | |
24 | |
25 | // Timer 0 konfigurieren
|
26 | |
27 | //Prescalerkonfiguration
|
28 | TCCR0 &= ~(1<<CS02)|(1<<CS01); // Kein Prescaler |
29 | TCCR0 |= (1<<CS00); // " |
30 | |
31 | //CTC Modus aktivieren
|
32 | TCCR0 &= ~(1<<WGM00); |
33 | TCCR0 |= (1<<WGM01); |
34 | |
35 | //Output Compare Interrupt erlauben
|
36 | TIMSK |= (1<<OCIE0); |
37 | |
38 | /*Output Compare Register vorladen mit 40
|
39 | Interrupt Aktion alle (4000000/40 = 1000.000Hz = 10µs
|
40 | ausführen
|
41 | */
|
42 | OCR0 = 0x19; |
43 | |
44 | //Interupt starten
|
45 | sei(); |
46 | |
47 | |
48 | |
49 | while(1) |
50 | {
|
51 | LED = 0x00; |
52 | wartems(250); |
53 | wartems(250); |
54 | wartems(250); |
55 | wartems(250); |
56 | LED = 0xff; |
57 | wartems(250); |
58 | wartems(250); |
59 | wartems(250); |
60 | wartems(250); |
61 | }
|
62 | |
63 | }
|
Durch rumprobieren habe ich herausgefunden das ich das Register OCR0 mit HEX 19 also DEZ 25 beschreiben muss um auf die z.B. 1s zu kommen. Dass würde aber nicht meiner Rechnung entsprechen die folgendermaßen aussieht: 4.000.000/40 = 100.000 Hz = 10µs. Mit HEX 19 sieht es aber so aus: 4.000.000/25 = 160.000 Hz = 6,25µs. Wie kommt das? Außerdem habe ich nicht ganz verstanden wo der Unterschied zwischen den beiden Modusen ist. Ich muss doch beide Vorladen. Auch das simulieren funktioniert nicht. Es kommt immer noch die Meldung:"Location not valid" Wo mache ich Fehler?
25 Takte von einem Interrupt zum nächsten ist immer noch sehr eng. Lass doch dem µC etwas Zeit! Deine 4Mhz, wo kommen die her? interner Oszillator, Quarz? > Außerdem habe ich nicht ganz verstanden wo der Unterschied zwischen > den beiden Modusen ist. Ich muss doch beide Vorladen. Im CTC lädst du in der ISR den Timer nicht vor. Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl > Es kommt immer noch die > Meldung:"Location not valid" Du hast den Optimizer eingeschaltet und der Optimizer hat die Variable rausgeworfen, weil er sie nicht braucht.
Karl heinz Buchegger schrieb: > Lass doch dem µC etwas Zeit! Am Anfang wollte ich eine Routine schreiben um eine Funktion zu haben Portionsweise 1 µs hochzuzählen. Jetzt muss ich die Portionen schon erhöhen um 10. Das muss dem doch reichen!! :-) Aber im ernst, wie kann ichs besser machen. Und komm mir ja nicht mit _delay ... . ;-) Genau das möchte ich umgehen. Ich habe gelesen, sobald ein Interrupt dazwischen kommt, stimmt die Zeit nicht mehr. Deshalb wollte ich was eigenes machen. Und da ich die Timer sowieso besser kennen lernen wollte habe ich es als Übung versucht. Karl heinz Buchegger schrieb: > Deine 4Mhz, wo kommen die her? > interner Oszillator, Quarz? externem Quarz. Karl heinz Buchegger schrieb: > Im CTC lädst du in der ISR den Timer nicht vor. > Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl Verstanden. Danke.
Jürgen schrieb: > Jetzt muss ich die Portionen schon erhöhen um 10. Das muss dem doch > reichen!! :-) Wenn du im Büro sitzt und alle 15 Sekunden kommt wer rein und will was von dir, kriegst du auch deine eigentliche Arbeit nicht mehr auf die Reihe. Beschränkst du aber den Zugang zu dir auf alle 5 Minuten, dann geht auch bei dir was weiter. >> Deine 4Mhz, wo kommen die her? >> interner Oszillator, Quarz? > > externem Quarz. ok. Das erklärt dann nicht den zeitlichen Versatz >> Im CTC lädst du in der ISR den Timer nicht vor. >> Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl > > Verstanden. Danke. Der springende Punkt ist: Der Timer zählt von sich aus exakt die angegebene Anzahl an Takten ab. Beim vorladen hast du immer einen Versatz drinnen, durch Dinge die du nicht beeinflussen kannst.
Jürgen schrieb: > Aber im ernst, wie kann ichs besser machen. Und komm mir ja nicht mit > _delay ... . ;-) Genau das möchte ich umgehen. Das kann man so pauschal nicht sagen. Das hängt natürlich auch immer von der Taktfrequenz ab. Bis zu einer gewissen Grenze sind _delay... schon in Ordnung. Vor allen Dingen, weil du das auch mit einem Timer nicht genauer hinkriegst, ganz im Gegenteil. > Ich habe gelesen, sobald > ein Interrupt dazwischen kommt, stimmt die Zeit nicht mehr. Vor den _delay.. einfach die Interrupts deaktivieren und danach wieder einschalten. Ich würde mal aus dem Bauch heraus sagen: Bis zu ~500µs sind _delay... durchaus verschmerzbar, wenn es nicht im Programm andere Gründe gibt, warum man auf keinen fall warten möchte. Denn: Auch ein Timer ist kein Allheilmittel. Vor allen bei kleinen Zeiten wirds mit einem Timer schin knifflig.
Karl heinz Buchegger schrieb: > Vor allen bei kleinen > Zeiten wirds mit einem Timer schin knifflig. Das habe ich jetzt auch gemerkt. Okay, habs jetzt soweit verstanden. Herzlichen Dank für deine Mühe.
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.