Forum: Projekte & Code einfache Pausenzeit


von Michael N. (e-lektroniker)


Angehängte Dateien:

Lesenswert?

Ich habe bis jetzt meine AVR´s immer mit Bascomavr Programmiert.
Nun möchte ich auch C lernen.
Da ich programmir Anfänger bin. Möchte ich erstmal so einfache Sachen
machen wie z.B.: eine LED Blinken lassen. Nun stand ich vor dem Problem
das es in C den Befehl wait 5 --> also 5 Sekunden warten nicht gibt.
Erst habe ich versucht das ganze mit _delay_ms(5000)zu lösen.
Dies funktioniert natürlich nicht.
(maximal mögliche Delay-Zeit: 262,14ms/F_CPU in MHz z.B.: Bei 8Mhz =
32,77ms--Bei ´4Mhz ca. 65)

Also habe ich eine Funktion geschrieben (wait) ,
welche als Parameter die
Wartezeit übernimmt und dann in einer Schleife, solange _delay_ms
ausführt bis die gwünschte Pausenzeit erreicht ist.

Ich Poste dies , weil ich im Forum nicht vergleichbares gefunden habe.
Nur Kluge Ratschläge, man macht so etwas mit Timern.
Das mag wol richtig sein, aber gerade für Anfänger(wie ich),
sind Timer recht schwer zu verstehen.
Auserdem, braucht man bei einer Schaltung wo zum Beispiel ein Relais
blinken soll, keine anderen Sachen gleichzeitig ausführen.

Ich find für alle Anfänger ist dies ein guter Einstieg.

von The Daz (Gast)


Lesenswert?

Michael, das ist die korrekte Methode um laaaange delays in C zu
basteln. Der Grund, warum die glibc nur so 'kurze' delays
ermoeglichst, ist die Tatsache, dass in fast allen Faellen ein solches
delay die schlechteste aller moeglichen Loesungen darstellt weil nur
sinnlos processor power verbraten wird.

von Hannes L. (hannes)


Lesenswert?

Die Timer sind so schwer zu verstehen, weil sie (bei den neueren AVRs)
so viele Features haben und daher das Kapitel "Timer" im Datenblatt
etwas langatmig geschrieben ist.

Um die Grundfunktionen zu verstehen, lohnt es sich, mal das Datenblatt
vom AT90S2313 oder AT90S8515 vorzukramen und sich den Aufbau des Timers
anzusehen.

Auch eine Simulation in AVR-Studio kann zeigen, wie der Timer
funktioniert. Dazu benötigt man zwar etwas Assembler, das ist aber viel
einfacher als allgemein angenommen. Mit Datenblatt, Instruction-Set und
Onlinehilfe des AVR-Studios kommt man schnell zu einem sichtbaren
Ergebnis.

Das Verwenden langer Delay-Schleifen blockiert den MC für andere
Arbeiten. Sowas macht man nicht, solche Programme lassen sich nicht
erweitern, sie haben keine Rechenzeitreserven.

Mein Tip:
Versuche Assembler zu lernen und richte dich nach dem Datenblatt. Dort
sind alle I/O-Register und die Funktionen ihrer Bits genau erklärt. Für
kleinere Programme direkt an der Hardware ist ASM sogar einfacher als
eine Hochsprache.

...

von Simon K. (simon) Benutzerseite


Lesenswert?

@Hannes: In allen 5 Punkten: ACK!

von Michael N. (e-lektroniker)


Lesenswert?

Hab mich inzwischen ein bischen mit den Timern befast.
Hatte das Problem das ich mit den obrigen Progamm meine Uhr nicht
nebenbei Laufen lassen kann, wärend das Programm z.B.: die DCF Zeit
ausliest.Inzwischen habe ich begriffen das Programme mit Pausen
schlecht sind. Wärend der Pause kann man einfach nichts anders mehr
machen.

Aber wie gesagt, für die allerersten Schritte ist das obrige Programm
ein guter Einstieg.


Hier die elegantere Methote:
Das ganze hab ich auf einem AT 90S8515 getestet.
Müste aber im Prinzip auf jeden Typ laufen.
(Timer anpassen)
int main(void)
{
TCCR1B = (1<<CS10) | (1<<CS11);   //setzt den Prescaler 64
OCR1A = 62500;                    //setzt den Vergleichswert
TCNT1 = 0;                        //startewert des Counters
TIMSK = 1<<OCIE1A;                //Compare-Int aktivieren
sei();                            //globale Ints aktivieren
}

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
 //wird ausgeführt wenn der Counterwert mit dem Vergleichswert
übereinstimmt
  // Uhrenroutine
  s++;  // s jede Sekunde um 1 erhöhen
  TCNT1 = 0; //timer 1 auf null

for (;;)
{Programm}
}

OCR1A = 62500;  errechnet mit der Formel:

OutpurCompare = Fosc/prescaler * Tsoll
z.B.:
OCR1A = 4000000Mhz/64 * 1 = 62500

von Hannes L. (hannes)


Lesenswert?

Ein Timer kann mehrere Dinge zugleich erledigen...

Z.B. für die Uhr:
Timer-Interrupt alle 10ms (Hundertstel Sekunden)
In der ISR:
- Hundertstel Sekunde hochzählen, bei Erreichen von 100 wieder
  löschen und ein Flag für das Hauptprogramm setzen, dass eine neue
  Sekunde begonnen hat, worauf das Hauptprogramm bei nächster
  Gelegenheit die Sekunde und ggf. Minute, Stunde, Wochentag, Tag,
  Monat, Jahr, Jahrhundert... aktualisiert.
- Bei aktivem DCF-Empfang den DCF-Eingang pollen, also abfragen und
  die Impuls-Zeiten (in Hundertstel Sekunden) registrieren, um das
  DCF-Signal zu decodieren.
- Die Bedienungstasten der Uhr abfragen und entprellen, hier bietet
  sich sogar an, das DCF-Signal mit zu entprellen und die Auswertung
  im Hauptprogramm zu machen.
- Die LCD-Ausgabe (via Ringbuffer) zu synchronisieren, für eine
  einfache Uhr genügen 100 Zeichen pro Sekunde, so schnell kann eh
  niemand lesen.
- Beim Hundertstelsekundenstand von 50 ein Flag setzen, damit das
  Hauptprogramm den Doppelpunkt der Zeitanzeige wieder mit einem
  Leerzeichen überschreibt, damit das wie Blinken aussieht.
- Im Weckbetrieb den Piepser toren, da ein periodischer Piepser viel
  besser weckt als ein Dauerpiep.

Und das alles in einem einzigen Timer-Interrupt alle 10000 Takte, falls
der AVR mit 1MHz läuft...

Deinen C-Code habe ich mir nicht angesehen, ich schreibe in ASM.

...

von Simon K. (simon) Benutzerseite


Lesenswert?

TCNT1 = 0; //timer 1 auf null

nicht nötig!

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.