Warteschleifen in C für Atmega 8

Gast #1281056
Lesenswert?

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
#1281068
Lesenswert?

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.
Gast #1281135
Lesenswert?

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
Gast #1281166
Lesenswert?

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
#1281167
Lesenswert?

@  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
#1281173
Lesenswert?

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
#1281334
Lesenswert?

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.
Gast #1281451
Lesenswert?

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
Gast #1281690
Lesenswert?

>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.
Gast #1281725
Lesenswert?

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 :-)
Gast #1286786
Lesenswert?

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
Gast #1286802
Lesenswert?

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
#1286809
Lesenswert?

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
Gast #1286841
Lesenswert?

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 ?
#1286851
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren