Ich (Assembler Anfänger, komme eigentlich aus der Industrieautomatisierung) habe als mein erstes Projekt die Düsseldorfer Rheinturmuhr auf dem Atmel AT90S2313 programmiert. Das Ergebniss gibt es hier: http://www.thomasklapper.de/rheinturmuhr.html Wer Interresse hat mir ein wenig unter die Arme zu greifen, ich bin um jede Hilfe dankbar. Besonders die Genauigkeit macht mir noch Sorgen. Geplant ist, wenn ich das irgendwann mal hinbekomme, die Uhr über DCF zu stellen. Aber das ist noch ein weiter Weg. Bis dahin,
erstmal Kompliment, wenn das wirklich dein 1.eigenes Programm ist. Der 1.Blick bei Anfängerprogrammen führt mich immer zum SP und zu den Interupts. Ersteres gut gemacht (=nicht vergessen), die Timer-ISR nicht so ganz. Grober Schnitzer - du hast vergessen das SREG zu sichern. 2 prinzipielle Möglichkeiten: ein Register nur dafür reservieren .def sreg_bak R1 in sreg_bak, sreg . . out sreg, sreg_bak reti oder auf dem stack push r16 in r16, sreg push r16 Die 1.Variante ist schneller, blockiert aber ein Register. Dann sollte man eigentlich nicht ohne triftigen Grund von der ISR aus weitere Unterprogramme aufrufen. Grund: Interupts sollte man kurz halten (andere Ints sind während dieser Zeit blockiert), ausserdem steigt die stackbelastung, man weiss ja nicht, wann der Timer zuschlägt, das Programm kann gerade schon tief im stack stecken (mehrere calls/rekursion), dann noch die Rückkehradresse und die Sicherungen in der ISR. Ein stack-Überlauf bringt ganz komische Effekte, an denen man sich einen Wolf sucht - läuft stunden/tage/wochenlang, aber dann passiert es immer wieder mal. Ist in deinem Programm beides kein Problem, aber man muss es sich ja nicht erst angewöhnen. Der bessere Weg: ein Bit setzen, welches anzeigt, dass der Timerinterupt da war und dieses im Hauptprogramm abfragen und ggf. eine Aktion auslösen und dieses wieder löschen. Thema Genauigkeit: mit 4MHz und Vorteiler 1024 hast du schon einen systematischen Fehler drin (den man zwar ausgleichen könnte durch zyklische Änderungen des reload-Wertes, aber das muss ja nicht sein). Dein Timer wird mit 256µs getaktet, *122 reload-Wert *32 =0,999424s, klingt genau, macht aber pro Tag fast eine Minute aus. Besser wäre beispielsweise ein Vorteiler 64, reload -250, Softwarezähler 250. Macht dann 16µs Takt *250 *250= 1s. Quarzabweichungen wirst du trotzdem noch haben, aber dazu kannst du später noch mal fragen.
noch was vergessen: einfacher wird der Teilerkram mit dem Timer1 (16bit), dann am besten den OCR-Int nutzen.
Hallo Crazy Horse, erst einmal vielen Dank für die Tipps. Ja, das ist wirklich mein erstes Assemblerpogramm. Ich habe mit dem AVR Ende letzten Jahres angefangen und die Rheinturmuhr war sozusagen mein erstes Etappenziel. Bis dahin habe ich nur kleine Codeschnippsel ausprobiert und mit ein paar Bauteilen herum gespielt, I2C, LCD, Schrittmotoren. Nur um wieder einen kleinen Einstieg in die Elektronik zu bekommen. Ich habe fast 10 Jahre lang Industriesteuerungen programmiert (SPS) nun hat sich mein berufliches Aufgabengebiet geändert und ich komme auch Entzug, ich muss halt was zum austüfteln haben. Daher mein Interesse für die AVR. Soviel zu mir. Nun aber zum Programm: Das mit dem Timer 1 habe ich gestern auch herausgefunden, einfach bis 40000 zählen lassen, sind dann 10ms. Ich werde das bei gelegenheit einpflegen. Die Interrupt bearbeitung werde ich versuchen umzumodeln, wenn ich Zeit finde. Auch die SREG Sicherung wird noch eingebunden. Ich denke wir sollten in Kontakt bleiben. Thomas
Bezüglich exakter Zeitbasis und DCF77 gibts hier schon einige Beispiele: http://www.mikrocontroller.net/forum/read-4-57760.html#new http://www.mikrocontroller.net/forum/read-4-57760.html#new Peter
So, nun mit angepasster Interruptbearbeitung und Timer1 Taktung. Mal schauen, wie genau sie nun läuft. Danke "crazy horse"
noch ein paar kleine Verbesserungen/Ideen. 1. Da du nur den Sekundentakt brauchst, könntest du den direkt mit demTimer1 erzeugen (Vorteiler 64 =Takt 16µs, OCR 62500), der Software-Zähler könnte entfallen. Da das INT-Programm dann eigentlich gar nichts mehr macht, könntest du sogar noch weiter gehen und dieses entfallen lassen. Dein Sekunden-bit ist dann TIFR.OCF1A. Ist es gesetzt, ist eine Sekunde um, per Software löschen durch Schreiben einer 1. 2. die eigentlich Uhr: das geht zwar so, wird auch oft so gemacht. Ich persönlich bevorzuge aber einen reinen Sekundenzähler. Dekodiert wird erst bei der Ausgabe, intern rechnest du nur mit Sekunden. 3. deine vielen Vergleiche und und davon abhängiges Laden mit Konstanten: oft geht sowas einfacher, schneller, kürzer und übersichtlicher mit Tabellen im Flash und dem LPM-Befehl. Alles nichts Ernstes , aber falls du Lust hast, kannst du das ja mal probieren. Das ideale Programm ist kurz, schnell und übersichtlich. Z.T widerspricht sich das zwar, aber verschleudern muss man Ressourcen ja nicht. Du wirst in deinem weiteren Programmierleben an Grenzen stossen (Laufzeit, Programmspeichergrösse, RAM-Grösse). Insofern macht sich eine von Anfang an konsequente Arbeitsweise irgendwann bezahlt. Viel Erfolg weiterhin.
@crazy horse "Ich persönlich bevorzuge aber einen reinen Sekundenzähler. Dekodiert wird erst bei der Ausgabe" Ich denke mal, daß sowas für einen Anfänger etwas zu komplex ist. Auch sollte man dann besser in C programmieren. Hier ist ja schonmal eine entsprechende Routine: http://www.mikrocontroller.net/forum/read-4-140631.html#new Peter
zu komplex? Weiss nicht, er hats doch bis jetzt ziemlich gut gemacht. 32bit-Divisionsroutinen gibts auch fertig. Er braucht ja auch keine Kalenderfunktion, sondern nur 24h.
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.