Forum: Projekte & Code RTC + Scheduler


von ape (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Forum,
für meinen in Bau befindlichen Verstärker hab ich mir diese Kombination
aus Real Time Clock und Scheduler gebastelt.

Die Real Time Clock kommt ohne zusätzlichen Uhrenquarz aus. Die Uhrzeit
wird mit Hilfe eines Timers mit Compare-Interrupt aus der normalen
Oszillator-Frequenz gewonnen. Das beiliegende Demo-Programm ist für
einen 3,6864MHz Quarz ausgelegt. Andere Frequenzen sollten sich relativ
einfach über andere Prescaler / Compare-Match Kombinationen realisieren
lassen. Im Moment wird ein 8-Bit Timer verwendet. Mit einem 16-Bit
Timer sollte es möglich sein aus nahezu jeder üblichen Quarz-Frequen
eien "genaue Sekunde" zu generieren. Außerdem lässt sich die RTC im
Headerfile für unterschiedlich viele Interrupts pro Sekunde
konfigurieren. Im Moment werden pro Sekunde 100 Interrupts ausgelöst.
Eine so hohe Auflösung mag für die reine Uhr Funktionalität nicht nötig
sein, ist aber für den Scheduler von Interresse, aber dazu später mehr.
Die RTC stellt Jahr, Monat, Tag, Stunde, Minute, Sekunde und
Sekundenbruchteil zur Verfügung.
Außerdem gibt es ein paar Zusatzfunktionen um aus dem Datum den
Wochentag zu ermitteln (die Berechnung erfolgt mit Hilfe des Doomsday
Algorithmusses), ein beliebiges Datum mit der momentanen RTC-Zeit zu
vergleichen, usw.

Der Scheduler nutzt kein Array fester Größe um die zu erledigenden
Aufgaben zu speichern sondern allokiert dynamisch Speicher für jeden
Eintrag der hinzugefügt wird.
Um einen Eintrag hinzuzufügen übergibt man dem Scheduler die
Callback-Funktion, den Ausführungszeitpunkt und einen zusätzlichen
benutzerdefinierbaren Parameter. Als Rückgabe bekommt man eine ID, die
den Task eindeutig identifiziert. Mit dieser ID kann man
Ausführungszeit, Übergabe-Paramter usw. später noch ändern.
Die Callback-Funktion bekommt neben dem benutzederfinierbaren Parameter
noch den Ausführungszeitpunkt übergeben. Dieser kann dann geändert
werden. Über den Rückgabewert kann die Funktion steuern, ob sie nach
der Ausführung aus der Liste gelöscht wird oder zum geänderten
Zeitpunkt erneut ausgeführt werden soll.
Der Ausführungszeitpunkt einer Aufgabe kann den gesamten Wertebereich
der Real Time Clock umfassen. Also in 100ms oder in 5 Jahren.
Diese Flexibilität hat leider ihren Preis: Ein Listeneintrag umfasst 17
Bytes zusätzlich benötigt malloc() noch 2 weitere Bytes, so dass pro
Eintrag 19 Byte SRAM belegt werden.

Die Uhr kann auch ohne den Scheduler verwendet werden, dafür muss nur
ein #define in der rtc.h auskommentiert werden (hab ich aber noch nicht
getestet).

Das Demo-Programm veranschaulicht die wichtigsten Funktionen. Außerdem
habe ich mich bemüht das ganze einigermaßen sorgfältig zu kommentieren
:)

Würde mich über Feedback / gefunden Bugs freuen :)

mfg
ape

von Stefan May (Gast)


Lesenswert?

Feedback: Wunderschön. :-)

Ein paar Sachen, die mir aufgefallen sind:

1) Der Name Scheduler hat mich etwas anderes erwarten lassen, als es
eigentlich ist. Ich hatte was mit Threads erwartet und mich erst
gefragt, wie das zusammen passt. Jetzt weiß ich es. :-)

2) In rtc.h heißt es:

// auskommentieren wenn auch der Scheduler benutzt wird
#define USE_SCHEDULER

Das müßte doch genau umgekehrt sein?

3) Ich würde den Compare-Interrupt etwas anders gestalten. Die
Systemzeit würde ich als ein 32bit-Wert darstellen und die richtige
Zeit mit Minuten, Stunden usw. daraus berechnen. Routinen dazu sind in
der Code-Sammlung zu finden.

http://www.mikrocontroller.net/forum/read-4-140631.html

4) Den Wert RTC_TCOMP_VAL könnte man als Berechnung einfügen mit:

#define RTC_TCOMP_VAL (F_OSC  256  RTC_IRQS_SEC)

RTC_IRQS_SEC und F_OSC muß man dann vorher natürlich definieren.

ciao, Stefan.

von ape (Gast)


Lesenswert?

Hallo,

zu 1) Naja ich verstehe einen Scheduler jedenfalls als ein Ding das
einfach Aufgaben in einer Liste abarbeitet. Für richtige Threads
bräuchte man ein RTOS (Real Time Operating System).

zu 2) Stimmt :). Es müsste heißen auskommentieren wenn er NICHT benutzt
wird.

zu 3) Mhmm stimmt da könnt ich mal drüber nachdenken, würde außerdem
den Vergleich von Zeiten wesentlich einfacher gestalten und weniger
Speicher verbrauchen. Nachteil wäre aber die beschränkte Zeitdauer wenn
man bei 1/100s oder gar Milli-Sekunden als Auflösung bleibt. (Mit 1ms
als kleinster Einheit wären das gerade mal 50 Tage)

zu 4) Problem dabei wenn man den Compare-Wert berechnen lässt ist, das
man nicht mehr sieht, wenn ein "krummer" Wert rauskommt. Aber ich
könnts zumindest als Kommentar daneben schreiben, um die Berechnung zu
verdeutlichen.

mfg
ape

von ape (Gast)


Lesenswert?

was mir außerdem gerade noch eingefallen ist:
Ich könnte noch eine automatische Umstellung auf Sommer- bzw.
Winterzeit einbauen.

von Stefan May (Gast)


Lesenswert?

Das Problem mit krummen Werten kann man mit einer Warnung durch den
Präprozessor zumindest anzeigen.

#if((F_CPU % 256) > 0)
#warning "RTC ungenau, F_CPU ist nicht durch 256 teilbar"
#if(((F_CPU/256) % RTC_IRQS_SEC) > 0)
#warning "RTC ungenau, F_CPU und RTC_IRQS_SEC passen nicht"
#endif
#endif

ciao, Stefan.

von ape (Gast)


Angehängte Dateien:

Lesenswert?

Stimmt gute Idee. Hab das Header-File jetzt mal entsprechend angepasst.
Allerdings kommt bei mir mit #warning keine Meldung. #error geht...

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.