Hallo,
für die Uni sollen wir ein kleines Mikrocontroller-Programm schreiben,
welche eine Uhr darstellt.
Nach einiger Überlegung habe ich mich dazu entschlossen, es quasi wie
die Unix-Zeit zu gestalten, also einen Counter, der pro Sekunde um 1
erhöht wird, und aus welchem ich dann, wenn nötig, durch "mod 3600" und
"mod 60"-Operationen die aktuelle Zeit ermittle.
Um dies zu können muss die Zählervariable also Zahlen bis mindestens
86399 darstellen können.
Da dies mit uint16_t nicht möglich ist verwende ich also auf uint32_t,
womit sich ja sogar zahlen >4,2 Mrd speichern lassen.
Nun habe ich aber das Problem, dass ein Überlauf stattfindet, sobald die
Zeit größer als 18:12:15 wird, was nun genau 65535 entspricht. Danach
springt die Uhr auf 00:00:00 um.
Als Plattform kommt ein Butterfly-Modul mit dem Atmega169 zum Einsatz.
Die Defines:
1
#include<stdio.h>
2
#include<stdint.h>
3
#include<avr/interrupt.h>
4
#include"butterfly.h"
Hier die Deklaration:
1
uint32_tg_time=0;
Und der Bereich in den der Zähler erhöht wird:
1
if(timer_get()!=c_time)
2
{
3
if(g_time==86399)
4
{
5
g_time=0;
6
}
7
else
8
{
9
g_time++;
10
}
11
g_hour=g_time/3600;
12
g_minute=(g_time-(g_hour*3600))/60;
13
g_second=(g_time-(g_hour*3600)-(g_minute*60));
Ich bin nun langsam mit meinem Latein am Ende und vor allem habe ich
keine Lust, eine kompliziertere Lösung zu basteln (es sei denn, es ist
unbedingt nötig).
Dankeschön im voraus.
Gruß,
Daniel
Ohne über deine Rechnung weiter zu sinnieren kommt mir spontan folgende
Idee zum Fehler: Kann es sein, dass die Berechnung anstatt im
32Bit-Format im 16Bit-Format durchgeführt wird? Wie sind g_hour & co.
definiert?
pumpkin
Hi,
bringt leider nicht den gewünschten Erfolg.
23:59:00 wird immer noch als 05:46:45 angezeigt.
23*3600+59*60 - 5*3600 - 46*60 - 45 = 65535 = uint16_t
Ich werd hier noch blöde :(
Hi,
ich habs. Hätte mein Hirn vor meinem letzten Post nochmal anschmeißen
sollen. Das Problem lag in der Funktion, mit der ich die aktuelle Zeit
einstelle. Nachdem ich nun dort
>Nach einiger Überlegung habe ich mich dazu entschlossen, es quasi wie>die Unix-Zeit zu gestalten, also einen Counter, der pro Sekunde um 1>erhöht wird, und aus welchem ich dann, wenn nötig, durch "mod 3600" und>"mod 60"-Operationen die aktuelle Zeit ermittle.
1
g_hour=g_time/3600;
2
g_minute=(g_time-(g_hour*3600))/60;
3
g_second=(g_time-(g_hour*3600)-(g_minute*60));
Verstehen wir dasselbe unter der Modulo-Funktion?
Wie wäre es mit
1
g_minute=(g_time/60)%60;
2
g_second=(g_time%60);
oder mit
1
g_second=(g_time%60);
2
g_tmp=g_time/60;
3
g_minute=(g_tmp%60);
4
g_tmp/=60;
5
g_hour=g_tmp;
In meinen Augen sollte man versuchen, die Anzahl der Multiplikationen
und der Divisionen gering zu halten, da diese relativ viel Zeit in
Anspruch nehmen. Im Grunde genommen handelt es sich bei der
'Modulo-Funktion' auch um eine Division, allerdings kann diese manchmal
vom Compiler bereits sehr stark optimiert werden. Leider ist 60 kein
sehr schöner Wert dafür und leider ist für diese Art von Berechnung ein
Minimum an Divisionen notwendig, aber das ist eine generelle Stilfrage
bzw. Abwägung zwischen Lesbarkeit und Geschwindigkeit.
Hi,
ja, hast recht, ich hab mich da verschrieben, ich meinte die
stinknormale Division :)
Was die Anzahl Divisionen angeht, ich sehe nur zwei Möglichkeiten mit
vertretbarem Aufwand eine Uhr zu realisieren.
Entweder ich mache es, wie schon beschrieben, über einen Sekundenzähler,
aus dem ich mir dann mit den bereits vorgestellten Operationen die
"echte" Uhrzeit ermittle, oder aber ich bastel mir eine Uhr, bei der
ebenfalls der Sekundenzähler erhöht wird, und sobald er 60 erreicht wird
ein Minutenzähler erhöht wird usw..
Problem ist hier, dass man ziemlich viele verschiede Fälle unterscheiden
muss, damit die Uhr korrekt funktioniert (ist Stunde 23, Minuten 59,
Sekunden 59 + Kombinationen aus all dem).
Die erste Möglichkeit erscheint für mich als Mikrocontroller-Neuling
eigentlich die leichtere. Zumal es sich um ein Projekt für die Uni
handelt, bei dem weniger die Performance im Vordergrund steht sondern es
einfach darum geht, dass man sich mit der Materie auseinandersetzt und
mit den Datenblättern usw. des Mikrocontrollers klar kommt.
Die Uhr ist jetzt auch letztenendes das Tüpfelchen auf dem i. In
vorherigen Aufgaben haben wir die Bibliothek "butterfly.c" entwickelt,
diese enthält diverse Funktionen für den Joystick, das LCD-Display, den
Piezo-Lautsprecher und eben auch einen Timer, der pro Sekunde eine
Variable hochzählt.
Allerdings werde ich das Ganze (sprich die Uhr und alles was noch
gefordert ist) heute nochmal von vorne beginnen, da ich mich inzwischen
ein bischen verrannt habe und den Fehler gemacht habe, einfach drauf los
zu programmieren. Es funktioniert zwar im moment alles, aber es fehlen
noch einige Funktionen, die nach ihrer Implementierung zu gut wie alle
anderen Funktionen stören (zumindest was die Display-Ausgabe, und somit
das Herzstück des ganzen Projekts angeht).
Dankeschön euch alle für die Hilfe :)
Wenn eine Modulo-Operation vom Compiler optimiert werden kann, dann kann
auch die entsprechende Division optimiert werden (allerdings ist eine so
optimierte Modulo-Operation auf einem 8-Bit-Prozessor wie AVR etwas
billiger).
Zur Standardlib gehören jedoch auch die Funktionen div() und ldiv(), die
beide Operationen ein einem Aufwasch durchführen. Was sie in diesem Fall
sinnvoll macht, sofern die Laufzeit relevant ist.
>Problem ist hier, dass man ziemlich viele verschiede Fälle unterscheiden>muss, damit die Uhr korrekt funktioniert (ist Stunde 23, Minuten 59,>Sekunden 59 + Kombinationen aus all dem).
Machst Du Dir da nicht einen Knoten im Kopf?
Der Unix-Zeit Ansatz hat sicher manche Vorteile, einfacher zu
programmieren (und später für den mc WESENTLICH einfacher zu berechnen)
ist die ganz normale Zeitdarstellung mit getrennten asec, min und std
Variablen: