Hallo zusammen,
ich versuche gerade eine einfache Uhr in C zu programmieren.
Das ganze läuft über den Timer eines Mikrocontrollers. Mit dem
TimerInterruptOverflow zähle ich eine Variable hoch.
Diese wiederum zählt dann meine Schleifen hoch
if(sek==59){
sek=0;
min++;
usw.
funktioniert auch soweit und auch die Ausgabe auf das LCD.
Als Variablen benutzte ich uint8_t.
Das Problem ist das nach einer gewissen Zeit meine Zeilen auf dem
Display mit irgendeinem Kram überschrieben werden. Es scheint mir so als
ob die Variablen irgendwann überfüllt sind.
Das verstehe ich nicht, da ich ja immer wieder bei 59 auf 0 setze usw.
Hat jemand einen Tipp?
Ich programmiere mit AVR-Studio 4
Anfänger schrieb:> Hat jemand einen Tipp?
Ich würde zur Sicherheit auf >= 59 abfragen.
Zeig mal ein bisschen mehr vom Code und verwende dabei die C-Code
Formatierung
Poste mal den gesamten Code (als anhang). In dem Codeausschnitt kann ich
nichts sehen, was falsch wäre. Ich würde evtl. if(sek>=59) benützen, um
sicher zu gehen, aber sollte eig. kein Problem sein.
>Das Problem ist das nach einer gewissen Zeit meine Zeilen auf dem>Display mit irgendeinem Kram überschrieben werden. Es scheint mir so als>ob die Variablen irgendwann überfüllt sind.
Nö, ich denke das die Ausgabe auf das Display Müll ist.
>Das verstehe ich nicht, da ich ja immer wieder bei 59 auf 0 setze usw.
Wie gibst du die Zahlen aus?
Mal ein einfaches Beispiel:
Deine Minute war 59. Danach wird 0 ausgegeben.
59 -> 09. Sieht das ungefähr so aus?
Nein, kein Tipp.
Aber wenn du uns den Sourcecode zeigst und ggf noch sagst welche
Umgebung du nutzt und vielleicht sogar noch erwähnst welche Art Display,
Library usw. dann könnte ein Tipp dabei rausspringen
holger schrieb:> Deine Minute war 59. Danach wird 0 ausgegeben.> 59 -> 09. Sieht das ungefähr so aus?
kann sein wenn er nur 0 statt 00 ausgibt, beliebter Fehler :-)
Wer sagt denn das die IF Abfrage zeitnah erfolgt?
Anfänger schrieb:> if(sek==59){> sek=0;> min++;
was ist wenn sek schon bei 60 ist?
Max H. schrieb:> Ich würde zur Sicherheit auf >= 59
eben usw.
Anfänger schrieb:> beim umspringen von 59 auf 1
Eine Uhr sollte eigentlich von 59 auf 0 und nicht auf 1 springen.
> lcd_print_itoa(sekunde);
Die Funktion gibt keinen führenden Nullen aus, stimmt's?
BTW: Die unteren if würde ich weiter einrücken, dann sieht man auf
Anhieb, dass es verschachtelte if sind.
Anfänger schrieb:> die Funktion habe ich aus der vorhandenen lib und sieht so aus:
Sieht nicht so aus als wäre eine führende null.
> Die Uhr springt ja jeweils durch rücksetzen sekunde=0; auf Null oder> muss ich das anderst realisieren?
Die if-Abfrage sollte auf >59 abfragen und das print sollte erst nach
der Abfrage sein.
> Sieht nicht so aus als wäre eine führende null.
Jetzt muß ich doch mal fragen wo du das erkennst.
Der TO benutzt lcd_print_itoa,
zeigt uns aber die Beschreibung von itoa. Was lcd_print_itoa ist, das
wissen wir nicht.
Oder habe ich was übersehen ?
Ok ich verstehe schon was ihr meint.
Ich versuche mal eine Lösung zu finden bzw. eine andere Funktion für die
itoa Variante.
Wie kann ich die Printfunktion beeinflussen damit immer 2-stellig
geschrieben wird?
Das Problem, dass mir irgendwann alles überschrieben wird habe ich aber
immer noch nicht verstanden. Irgendeine Idee woher das kommen könnte?
Anfänger schrieb:> also wie gesagt das flag wird in der Iterrupt Routine gezählt.
Das ewige und meist auch sinnvolle Dogma mit der möglichst kurzen ISR
besagt nicht, dass man darin gar nichts machen darf. Zähl deine Uhr in
der ISR hoch. Soviel Zeit muss sein. Und die ist auch vorhanden. Dann
tritt auch das Problem, dass ein Inkrement verschluckt wird, gar nicht
erst auf. Du zählst einfach bis 60 bzw. 24 und setzt dann auf 0.
Nur Ausgabe auf das Display machst du natürlich nicht in der ISR. Sowas
ist meist tödlich.
mfg.
Thomas Eckmann schrieb:> Zähl deine Uhr in> der ISR hoch. Soviel Zeit muss sein.
Na, na, na, es reicht doch die Sekunden in der ISR zu inkrementieren.
Der Rest ist doch für den µC lllllaaaaannnggsssaaammmmm, sehr
llllllllllaaaaaaaannnnnnngggggsssssaaaaaaaammmmmmm.
ich inkrementiere nur ein Flag in der Interrupt Funktion und rufe hier
drin die Funktion Uhrzeit auf, in der dann alles weitere abläuft!
Sollte doch so richtig sein oder nicht?
Troll schrieb:> Na, na, na, es reicht doch die Sekunden in der ISR zu inkrementieren.
Ja. Aber in einer Long-Variable. Das reicht für 136 Jahre. Die Uhrzeit
rechnet man erst zur Ausgabe aus.
mfg.
Anfänger schrieb:> in der Interrupt Funktion und rufe hier> drin die Funktion Uhrzeit auf, in der dann alles weitere abläuft
Das ist nicht so gut. In der ISR solltest du nur das Flag und die
Sekunden inkrementieren. Alles weitere machst du in der Hauptschleife.
Wenn das C ist, dann ist lcd_print_itoa eine Funktion. Die macht
anscheinend irgendwas mit itoa und gibt was auf das LCD aus.
Ob sie das mit/ohne 0 oder Leerzeichen macht, das wissen wir nicht.
Wahrscheinlich/anscheinend nicht - aber wenn uns der TO nicht sagt
welche Libraries er verwendet, dann ist alles nur geraten und stochern
im Nebel.
P.s. Die LCD Funktion solle nicht aus dem Interrupt sondern in der
Hauptprogrammschleife aufgerufen werden.
Aber das ist das 2.te Problem.
>Eine führende Null für eine eistellige Zahl könnte man so einbauen:>> itoa(zahl, buffer, 10);> if(buffer[1] == 0x00)> lcd_data('0');
OMG.
if(zahl < 10) lcd_data('0');
Danach das andere Geraffel.
Du benutzt : lcd_print_itoa();
Du erklärst : itoa();
Du Antwortest : lcd_print ist nur die Funktion um etwas an das LCD zu
senden
Jetzt haben wir schon 3 unterschiedliche Funktionen im Spiel.
Wenn das C ist, dann sind das 3 unterschiedliche Dinge.
Aus lcd_print wird nicht plötzlich lcd_print_itoa nur weil man _itoa
and den Namen dranhängt.
Ich bin fast Sicher die Lösung wäre was in der Richtung
1
if(flag1>=61){
2
sekunde++;
3
flag1=0;
4
5
lcd_set_cursor(7,1);
6
if(sekunde<10)
7
lcd_print("0");
8
lcd_print_itoa(sekunde);
9
10
if(sekunde>60){
11
sekunde=0;
12
minute++;
13
lcd_set_cursor(4,1);
14
if(minute<10)
15
lcd_print("0");
16
lcd_print_itoa(minute);
17
if(minute>=59){
18
minute=0;
19
stunde++;
20
lcd_set_cursor(1,1);
21
if(stunde<10)
22
lcd_print("0");
23
lcd_print_itoa(stunde);
24
if(stunde>23){
25
stunde=0;
26
}
27
}
28
}
29
}
Und das im Hautprogramm aufgerufen.
Aber halt nur geraten.
ok, erstmal vielen Dank für die ganzen Hilfestellungen.
@Frank, deine Idee bringt mir aufjedenfall die führenden Nullen aber ich
überschreibe mir tortzdem bei der Ausgabe auf dem LCD irgendwann meine
weiteren Zeilen und Spalten mit irgendwelchen Zahlen.
Was mich wundert, dass das manchmal sofort, manchmal erst nach 3 Minuten
passiert.
Ich inkrementiere jetzt nur noch das Flag über den Interrup, der Rest
läuft im Hauptprogramm. Es scheint jetzt zu funktionieren, keine
komischen Zeichen mehr und nichts wird überschrieben. Hauptproblem war
dann wohl meine Strukturierung.
Vielen Dank für die ganzen Hilfen!!!