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
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.
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
was mir außerdem gerade noch eingefallen ist: Ich könnte noch eine automatische Umstellung auf Sommer- bzw. Winterzeit einbauen.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.