Hallo, ich suche für einen Atmega8 mit 16Mhz eine Wartschleife weil ich mit delay_ms() nicht mehr auskomme leider kriege ich das irgenwie nicht gebacken ich will Zeiten zwischen 3s und 300s überbrücken mir ist es gegal wenn der AVR in der Zeit nix macht sollte halt relativ genau sein ( im µs Bereich). Kann mir da jemand helfen? Schon mal vielen dank!! Gruß noop
noop schrieb: > ich suche für einen Atmega8 mit 16Mhz eine Wartschleife weil ich mit > delay_ms() nicht mehr auskomme leider kriege ich das irgenwie nicht > gebacken ich will Zeiten zwischen 3s und 300s überbrücken mir ist es > gegal wenn der AVR in der Zeit nix macht sollte halt relativ genau sein > ( im µs Bereich). Kann mir da jemand helfen? _delay_ms geht bis 65535 Sekunden, allerdings dann nur mit einer Genauigkeit von max 100µs. Wozu braucht man bei einem 300s Delay eine Genauigkeit im µs-Bereich? Wenn es wirklich so genau sein muss, solltest du am besten einen Timer benutzen.
100µs wäre noch okay aber _delay_ms geht nur bi 6,5535 Sekunden Gruß noop
noop schrieb:
> 100µs wäre noch okay aber _delay_ms geht nur bi 6,5535 Sekunden
Ach ja verdammt, der Punkt ist ja ein Komma.
Und wenn ich _delay_ms() in ner for schleife ablaufen lasse hab ich ja wieder die Schleifenzeit drin.
Hallo, ich blick da noch net so ganz durch also ich hab einen Timer z.b. 8 Bit und lass denn mit 16MHz/ 1024 laufen der kann maximal einen Wert von 256 dann kann der doch bis 0,16384s zählen oder ? und wie komm ich dann auf z.b. 300s ? Gruß noop
Hallo, dann hab ich aber doch wieder die Zeit von der Zählerschleife mit Variablen drin dann kann ich doch auch _delay_ms en paar tausend mal laufen lassen oder ?
Du zählst die Überläufe mit bis du die fragliche Zeit erreicht hast. Wenn ich nicht ganz daneben liege sind es 16,384ms die du mit dem 8bit timer schaffst. Mit einem 16bit Timer wären es schon 4,194s. Bei jedem Timeroverflow n+1 while n<x mit x=Wunschzeit/Zähldauer
@ noop (Gast) Das macht man so. Stell deinen timer so ein, dass er z.B. mit 100Hz einen Interrupt erzeugt, kann man mit dem CTC-Modus spielend erreichen. In dem Interrupt wird dann eine Variable hochgezählt. Erreicht die dann den gewünschten Wert, wird eine Aktion ausgeführt. Aber an deiner Frage erkennt man, dass du noch VIIIIIELLE Grundlagen durcharbeiten musst, ehe du dort was Gescheites machen kannst. MFG Falk
Zuerst überlegst du dir mal, in welcher Auflösung du deine Delays brauchst (nicht zu fein, das ist problematisch, die 100 µs von oben sind doch z.B. ein schöner Wert). Dann nimmst du einen Timer, der den CTC-Modus beherrscht, und stellst ihn so ein, dass er Interrupts in dieser Auflösung produziert. Im Interrupt zählst du einen Wert runter. Das Warten ist dann nur ein Warten darauf, dass der Wert Null wird. Bisschen Pseudocode:
1 | volatile Typ_passender_Groesse delay_count; |
2 | |
3 | ISR () { |
4 | |
5 | if (delay_count) |
6 | delay_count--; |
7 | }
|
8 | |
9 | wait (Typ_passender_Groesse delay) { |
10 | |
11 | counter auf Null setzen; |
12 | delay_count = delay; |
13 | while (delay_count) |
14 | ;
|
15 | }
|
16 | |
17 | |
18 | wait(3000); // warte 300s |
Hallo, wie bekomme ich denn den Timer dazu das der bei 100µs ein Interrupt produziert weil ich kann ja z.b. den Timer 16Mhz/8 nehmen also 2 Mhz das ergibt dann bei 256 Takten 128µs? Gruß noop
Du kannst z.B. den Teiler 64 nehmen, und dann bis 24 zählen lassen. Der Timer0 des Mega8 kann aber keinen CTC Modus. Musst dann also Timer2 nehmen (wenn es ein 8-Bit Zähler sein soll). Versuche jetzt aber nicht, das bis ins letzte Detail aus mir rauszuleiern. Das Stichwort "CTC" ist völlig ausreichend, dass du dir das selber zusammensuchen kannst. Im Datenblatt und dem Tutorial gibt es haufenweise Infos darüber.
mal abgesehen davon das das durchaus möglich ist (und wer weiß wie bekommt das auch im 5 min programmiert) vermute ich einen Denkfehler bei 300Sek Wait und 100µS Genauigkeit Erzähl uns doch mal was du vor hast... Gruß Sven
Hallo, es geht halt darum das eine LED leuchten zu lassen und das halt relativ genau und das unterschiedliche Zeiten.
Welches ist denn die kürzeste Zeit? In welchen Zeitraster soll eingeschaltet werden? Also in welchen Intervallen kann man zwischen der oberen und unteren Grenze die Zeit einstellen?
>also ich brauch von 0,4s - 300s in 0,1s Schritten
Dann kann man den Timer so einstellen, dass er alle 100ms einen
Interrupt erzeugt, und in der ISR dazu einfach Variablen hoch- oder
runterzählen.
In der Hauptschleife guckt man dann einfach nach, ob die "Weckzeit"
erreicht wurde.
Das sollte man sogar mit dem Wissen aus dem Tutorium als "blutiger"
Anfänger an einem Tag hinbekommen.
Hi zu deiner Sorge das die Schleifenaufrufe mitzählen. Das machen sie bei Timer-Interrupts nicht. Der Timer läuft unabhängig von der CPU (bis auf die Taktfrequenz). Wenn also die CPU gerade die Schleife abarbeitet, läuft der Timer weiter. Kritisch wird es nur wenn du zulange im Interrupt bist und der Timer noch einen Interrupt auslöst, dieser wird dann übersehen. In 100µs sollte das aber locker drin sein, baue aber kein Delay ein :-)
Hallo, hab mal was rumgebastelt nur warum kann ich das im AVR Studio nicht vernünftig Simulieren wenn ich über den Teil springen will und dahinter einen Breakpoint setze dann zeigt der als Stop Watch nur ca 470µs an woran liegt das er müsste doch 1s anzeigen
1 | OCR2 = 6250; // Wenn Timer bis 62500 gezählt hat dann Ereigniss auslösen und clearen |
2 | |
3 | TCNT2 = 0; // Setze Counter auf 0 |
4 | |
5 | TCCR2 |=(1<<CS22)|(1<<WGM21); // 16MHz/256 - CTC-Mode |
6 | |
7 | loop_until_bit_is_set(TIFR, OCF2); // warte, bis der Timer angekommen ist |
8 | |
9 | TIFR |= (1 << OCF2); // lösche Output Compate Flag |
Du hast da anscheinend überhaupt ein Durcheinander. Timer 2 ist ein 8 Bit Timer!
noop schrieb:
> oh sry hab mich vertippt müsste OCR2 = 62500; heißen
Wieso tippst du Programmcode ab?
Copy&Paste und schon hast du diese blöden Tippfehler nicht mehr und wir
suchen nicht Probleme die du in deinem realen Code gar nichts hast.
okay hab jetzt den 1024 teiler genommen kann dass es daran liegt das der Compiler mir ne Fehlermeldung rausgibt: warning: large integer implicitly truncated to unsigned type
1 | OCR2 = 15625; // Wenn Timer bis 15625 gezählt hat dann Ereigniss auslösen und clearen |
2 | |
3 | TCNT2 = 0; // Setze Counter auf 0 |
4 | |
5 | TCCR2 |= (1<<CS20)|(1<<CS22)|(1<<WGM21); // 16MHz/15625 - CTC-Mode |
6 | |
7 | loop_until_bit_is_set(TIFR, OCF2); // warte, bis der Timer angekommen ist |
8 | |
9 | TIFR |= (1<<OCF2); // lösche Output Compate Flag |
noop schrieb: > okay hab jetzt den 1024 teiler genommen kann dass es daran liegt das der > Compiler mir ne Fehlermeldung rausgibt: warning: large integer > implicitly truncated to unsigned type Der Hinweis des Compilers ist schon nicht schlecht. Timer 2 ist ein 8 Bit Timer. In 8 Bit passt nichts größeres rein als 255. Wie willst du daher 15625 in 8 Bit unterbringen? Dazu musstest du mindestens über 14 Bits verfügen, die du aber nicht hast
noop schrieb:
> ich dachte der timer 2 ist ein 16 bit Timer?
Im Zweifelsfall hilft immer: Datenblatt lesen
Und auch im Nichtzweifelfall ist Datenblatt lesen immer eine gute Idee.
okay :-) also nehm ich dann mal Timer 1 :-) pack ich den timer jetzt in eine For-Schleife und lass die dann entsprechend ausführen oder wie mache ich das am besten um auf die gewünschte Zeit zu kommen ?
noop schrieb: > okay :-) also nehm ich dann mal Timer 1 :-) pack ich den timer jetzt in > eine For-Schleife und lass die dann entsprechend ausführen Das Prinzip, das du benutzt hast, kannst du ja weiterbenutzen (Das Flag aber auch löschen ehe du den Timer startest. Kein Mensch garantiert dir, dass das zurückgesetzt ist). Du bist nur darüber gestolpert, dass Timer 2 nicht so weit zählen kann, wie du es brauchen würdest. > oder wie > mache ich das am besten um auf die gewünschte Zeit zu kommen ? Das kommt immer darauf an, wie genau die die Zeit brauchst. Im einfachsten Fall lässt man sich von einem Timer einen periodischen Interrupt auslösen und zählt in der ISR eine Uhr hoch. Frei nach dem Motto: Wenn ich 10 mal 1 Sekunde gewartet habe, hab ich in Summe auch 10 Sekunden gewartet.
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.