Hi,
ich versuche mich derzeit an einem Wecker, da ich etwas sinnvolles mit
einer Echtzeituhr anstellen möchte:)
Die Uhrzeit steht mittlerweile auf meinem LCD Display und ich denke,dass
ich das mit dem "Alarm einstellen" hinbekomme, aber momentan tappe ich
völlig im Dunkeln, was den Vergleich von Uhrzeit und Alarm angeht.
Ungefähr so:
if (Alarmstunde == AktuelleStunde)
{
if (Alarmminute == AktuelleMinute)
{ //Alarm}
}
Ich habe hier einige Threads gefunden, allerdings steige ich da nicht
ganz durch und deshalb bitte ich direkt um Hilfe :)
Mein Code habe ich im Dateianhang beigefügt.
Mit freundlichen Grüßen Flori
Moin,
die zweite Variante ist zwar etwas besser lesbar, allerdings würde ich
davon ausgehen, dass der gleiche ASM Code daraus generiert wird.
mfg Emperor_L0ser
Ich glaube man hat mich etwas falsch verstanden bzw ich habe mich falsch
ausgedrückt^^
Ich wollte eigentlich wissen, wie ich die Variable "Aktuelle Stunde" bzw
"Aktuelle Minute" definieren kann. Deshalb auch der Code.
Gruß
Flori wrote:
> Ich glaube man hat mich etwas falsch verstanden bzw ich habe mich falsch> ausgedrückt^^> Ich wollte eigentlich wissen, wie ich die Variable "Aktuelle Stunde" bzw> "Aktuelle Minute" definieren kann. Deshalb auch der Code.> Gruß
Fang mal damit an, diese Funktion ...
1
voidrtcSendTimeLcd()
2
{
3
lcdGoto(1,1);
4
rtcSendBcdLcd(rtcGetHour());
5
rtcWaitMs(20);
6
lcdWrite(":");
7
rtcSendBcdLcd(rtcGetMinute());
8
rtcWaitMs(20);
9
lcdWrite(":");
10
}
... in 2 Funktionen aufzuteilen. Im Moment erfüllt diese Funktion 2
Aufgaben in einem: Sie holt die aktuelle Uhrzeit und gibt sie am LCD
aus. Das unterteilst du in 2 getrennte Funktionen:
* Eine die die aktuelle Uhrezeit holt und sie in 2 Variablen (Stunde,
Minute) ablegt
* Eine zweite Funktion, die die aktuelle Uhrezeit aus diesen Variablen
ausgibt.
Damit hast du dann automatisch die aktuelle Zeit auch in einer Form
vorliegen, so dass du sie weiterverarbeiten (zb. in Form von Abfragen
auf einen speziellen Zeitpunkt) kannst.
Edit:
Und fang an, deinen Code vernünftig einzurücken. Das ist kein Luxus,
kann aber ungemein hilfreich bei Fehlersuche sein.
...
1
main()
2
{
3
DDRB=0xFF;// Ausgang
4
PORTB=0x00;//
5
6
intalrm=0;// 0 = kein Alarm | 1 = Alarm
7
8
init();//
9
while(true)// Mainloop-Begin
10
{
11
if(alarm==1)
12
{
13
sbi(PORTB,0);//Licht an / Ton an
14
}
15
else
16
{
17
rtcSendTimeLcd();
18
}
19
20
}// Mainloop-Ende
21
}
ist keine vernünftige Einrückung, weil man die Struktur nicht erkennen
kann.
Das hier
1
main()
2
{
3
DDRB=0xFF;// Ausgang
4
PORTB=0x00;//
5
6
intalrm=0;// 0 = kein Alarm | 1 = Alarm
7
8
init();//
9
while(true)// Mainloop-Begin
10
{
11
if(alarm==1)
12
{
13
sbi(PORTB,0);//Licht an / Ton an
14
}
15
else
16
{
17
rtcSendTimeLcd();
18
}
19
20
}// Mainloop-Ende
21
}
ist eine vernünftige Einrückung. Dort kann man sehr gut erkennen, wo ein
Block beginnt und wo er wieder endet, ohne dass man { und } abzählen
muss, bzw. auf Kommentare (die meistens sowieso nicht stimmen) vertrauen
muss um das Ende eines Blocks wiederzufinden. Die jeweils schliessende }
steht genau unter der öffnenden { und der Blockinhalt ist (in diesem
Fall) 2 Leerzeichen eingerückt.
Und nein: Die Ausrede "Das mach ich wenn ich fertig bin" lass ich nicht
gelten.
Hi,
danke für die Antworten.
@Karl heinz Buchegger
Du hast Recht, daran sollte ich arbeiten^^
Ich habe tatsächlich schon mehrere Male vorher versucht die Funktion
aufzuteilen, allerdings sind Versuche wie diese:
Flori wrote:
> aufzuteilen, allerdings sind Versuche wie diese:>>> main()
Es muss
1
intmain()
heissen
> {> DDRB = 0xFF; // Ausgang> PORTB = 0x00; //>> int alrm = 0; // 0 = kein Alarm | 1 = Alarm> int ahour= 15;//Alarmstunde> int amin = 10;//Alarmminute>> int menu = 1;//Menü>> int hour = rtcGetHour();> int min = rtcGetMinute();
OK. Es gibt also zwei Variablen namens hour und min.
Gut. Die kriegen hier erst mal als Wert die aktuelle Uhrzeit.
...
> while (i<1)> {
dann gehts in die Hauptschleife. Die läuft immer und immer
...
> if (menu == 1)> {> lcdGoto(1,1);> lcdWrite(hour);
... gut. hour wird ausgegeben ...
> rtcWaitMs(20);> lcdWrite(":");> lcdWrite(min);
... und auch min wird ausgegeben ...
> rtcWaitMs(20);> lcdWrite(" ");> rtcWaitMs(20);> }>> if (ahour == hour && amin == min)> {
... und dann die bewusste Abfrage, die feststellen soll, ob die
Alarmzeit erreicht ist ...
> printf("alrm = %d\n", alrm);> alrm = 1;> }
... tja.
Und dann ist die Schleife zu Ende.
Nur: Wo, innerhalb dieser Schleife, haben den hour und min eigentlich
eine Chance jemals an neue Werte zu kommen? Eine Variable, der du nichts
zuweist, wird auch ihren Wert nicht verändern.
Um den neuen Wert hatte ich mir bisher gar keine Gedanken gemacht, da
keine Uhrzeit auf meinem LCD erscheint :(
Deshalb dachte ich, dass die Variable irgendwie falsch deklariert
wurde...
Warum also wird die Uhrzeit nicht ausgegeben?!
Gruß
Flori wrote:
> Um den neuen Wert hatte ich mir bisher gar keine Gedanken gemacht, da> keine Uhrzeit auf meinem LCD erscheint :(> Deshalb dachte ich, dass die Variable irgendwie falsch deklariert> wurde...> Warum also wird die Uhrzeit nicht ausgegeben?!
Weil lcd_write die falsche Funktion dafür ist. Da hat der originale
Programmierer, bei dem du geklaut hast, nicht wirklich gut nachgedacht,
welche möglichen Fehler er zulässt, wenn er so einen Haufen lcd_write
Funktionen macht. Insbesondere die Funktion
ist eine Schnappsidee.
Die Funktion, die du willst heisst
rtcSendBcdLcd
Edit: Tu dir selbst einen Gefallen und lösche alle lcdWrite Funktionen.
Und danach ergänzt du die LCD Funktionen mit diesen hier:
Das wichtigste ist hier: Die Funktion für einen bestimmten Datentypen
hat einen eindeutigen Namen. Somit überlässt du es nicht dem C++
Compiler, für dich die richtige Funktion anhand der tatsächlich
übergebenen Datentypen zu bestimmen. Soweit bist du noch nicht, dass du
das in all seinen Feinheiten überblicken könntest.
Für deine Ausgabe benutzt du dann die Funktion lcdWriteBcd
(und die Funktion lcdString entfernst du auch. Ihre Funktion wird durch
lcdWriteString bereits abgedeckt)
Flori wrote:
>> return 0;> } // Mainloop-Ende> }
Was hat das return 0 innerhalb der Mainloop zu suchen?
Sagte ich schon, dass du dir viel Ärger mittels konsequenter Einrückerei
ersparen kannst? Wie kann das sein, dass das 'r' von return und die
unmittelbar darunter stehende } in der selben Spalte sind? Bei einem {
wird konsequent um 2 Leerzeichen eingerückt. Bei einem } wird
konsequent wieder um 2 Leerzeichen rausgerückt. Die letzte } einer
Funktion, muss wieder in der ersten Spalte sein, sonst stimmt was nicht.
Zwischen einer { und der schliessenden } kann es keinen Code geben, der
auf derselben Spalte wie die { } (oder links davon) stehen.
Warum gibst du hier aus, was dir rtcGetHour bzw. rtcGetMinute liefert?
Du hast die schon mal abgefragt und die Ergebnisse in hour bzw. min
gespeichert!
Fang doch erst mal mit kleinen Brötchen an. Dann verhedderst du dich
auch nicht so leicht
1
intmain()
2
{
3
inthour;
4
intmin;
5
6
DDRB=0xFF;// Ausgang
7
PORTB=0x00;//
8
9
init();
10
11
while(1)
12
{
13
hour=rtcGetHour();
14
min=rtcGetMinute();
15
16
lcdGoto(1,1);
17
rtcSendBcdLcd(hour);
18
lcdWrite(":");
19
rtcSendBcdLcd(min);
20
21
//
22
// oder, wenn du wie vorgeschlagen umgebaut hast:
23
//
24
// lcdGoto( 1, 1 );
25
// lcdWriteBcd( hour );
26
// lcdWriteString( ":" );
27
// lcdWriteBcd( min );
28
//
29
}
30
}
Edit: Hab den Aufruf von init() noch vor der Schleife eingefügt.
Flori wrote:
> Das "return 0;" ändert nichts an meiner Lage, selbst wenn es weg wäre> oder verschoben würde....
Doch, das würde es.
Eine Schleife, aus der man mit return aussteigt, wird beendet, selbst
wenn die Schleife eigentlich für immer laufen sollte :-)
ich entschuldige mich an dieser stelle für meine unordentlichkeit.
das funktioniert immer noch nicht.
Mal eine allgemeine Frage:
Wie ist es möglich, dass
Flori wrote:
> Und warum funktioniert das Gesamte dann immer noch nicht?
Was funktioniert denn noch nicht?
Kriegst du eine Anzeige?
Welche?
Wenn Anzeige: Ändern sich die Zahlen?
Hast du bedacht, dass in hour bzw. min die entsprechenden Zahlen als BCD
Zahlen enthalten sind (nach der Art und Weise zu schliessen, wie sie
ausgegeben werden). D.h. um deine Alarmzeit auf 16 Uhr zu setzen,
müsstest du 0x16 zuweisen.
Flori wrote:
> sry war grad ein copy paste.
Hurg. Und ich hab mich schon gewundert, wie du die ganzen lcdWrite
Funktionen am C-Compiler vorbei gekriegt hast.
Wenn du C++ programmierst, dann lass die Dateiendung bei cpp!
Poste deine Files immer so, wie du sie auch durch den Compiler jagst.
Nichts verändern, auch nicht die Dateiendung!
> heißen?
Konsequenterweise wär das ein guter Name.
Ich würd sie allerdings
lcdWriteChar
nennen, damit man im Funktionsnamen auch gleich sieht, dass hier ein
char ausgegeben wird.
Also ich habe jetzt zumindest alle Compilerfehler wegbekommen(Prototyp
zu Lcd...)
Ich bekomme leider überhaupt gar keine Anzeige.Es wird nichts angezeigt.
Nicht einmal das ":"
Im Dateianhang ist nochmal der verbesserte Code. Ich habe mal alle,für
das Problem, wichitgen Funktionen über die Mainschleife gesetzt.
Gruß
Flori wrote:
> Also ich habe jetzt zumindest alle Compilerfehler wegbekommen(Prototyp> zu Lcd...)> Ich bekomme leider überhaupt gar keine Anzeige.Es wird nichts angezeigt.> Nicht einmal das ":"
Dann heist es erst mal abspecken, bis wieder was funktioniert.
1
intmain()
2
{
3
lcdInit();
4
5
lcdWriteData('j');
6
lcdWriteString("juhu");
7
8
while(1)
9
;
10
}
kriegst du eine Ausgabe oder nicht? (Damit testen wir mal, ob deine LCD
Ausgabe grundsätzlich funktioniert. Ab jetzt wird alles in Frage
gestellt und einzeln abgetestet, obs auch funktioniert. Und erst im
Anschluss daran bauen wir das komplette Programm wieder neu auf)
Flori wrote:
> Bei diesem Code ändert sich nichts an der Anzeige. Immer noch "jjuhu".
Gewöhn dir an, bei Tests die Texte ein wenig zu variieren.
Dadurch kannst du sehen, ob tatsächlich das neue Programm in den µC
gebrannt wurde, oder du einen Compiler Fehler im Eifer des Gefechts
übersehen hast.
Du brauchst immer irgendwas in der Form: Erwartete Ausgabe versus
tatsächliche Ausgabe.
> Also muss der Fehler bei der Deklaration bzw "SendBcdLcd" liegen oder?
Nicht notwendigerweise. Da kann nicht viel schiefgehen.
Und dann eine volle Uhr (wenn der lcdGoto funktioniert)
(Verfolg auch mit, welche Änderungen ich jeweils mache. Immer kleine,
testbare Änderungen.
Die Sache mit dem _ lässt mir noch keine Ruhe. Da ist noch was faul)
Flori wrote:
> Das funktioniert. Warum funktioniert das jetzt mit dem "uint8"?
Müsste mit einem int genauso funktionieren.
Ein uint8_t ist ein "8-Bit Integer ohne Vorzeichen", hat also in einer
16 Bit Variable locker Platz.
Aber:
* Die RTC Funktionen liefern einen uint8_t
* Die Ausgabefunktion will einen uint8_t haben
Also warum künstlich einen Wert auf 16 Bit aufblasen, wenn er zur
Ausgabe sowieso wieder auf 8 Bit geschrumpft wird?
Ich schwanke noch, ob es gescheit ist, die einzelnen Werte als BCD Werte
zu lassen, oder ob es nicht besser wäre, da "echte" Zahlen daraus zu
machen. Spätestens wenn es darum geht, die Alarmzeit mit Tastern zu
vergrößern bzw. zu verringern, wären "echte" Zahlen besser.
Komischer Weise kommt der Unterstrich jetzt nicht mehr^^
Ich bedanke mich recht herzlich bei dir für deine Geduld. Ich möchte
mich jetzt verbessern und dann helf ich bei euch mit!
Vielen Dank nochmal. Ich habe echt einiges gelernt.
Hier der Code für diejenigen, die ihn vllt nochmal brauchen:
>Ich schwanke noch, ob es gescheit ist, die einzelnen Werte als BCD Werte>zu lassen, oder ob es nicht besser wäre, da "echte" Zahlen daraus zu>machen. Spätestens wenn es darum geht, die Alarmzeit mit Tastern zu>vergrößern bzw. zu verringern, wären "echte" Zahlen besser.
Daran werde ich mich gleich morgen an die Arbeit machen.
Man kann doch die Alarmzeit über die Taster einstellen und speichern(als
Zahl). Wenn die "Ok Taste" dann gedrückt wird deklariert man zb alarmh
als 0x X.
Der Unterschied ist dir klar?
Bei BCD Zahlen ist jedes Nibble (also 4Bit) als eine Ziffer zu sehen.
Ein Wert von 0x19 repräsentiert also, als BCD Zahl gesehen, die 19.
Wenn man sich das aber dezimal anzeigen lassen würde, würde da aber 25
raus kommen.
Der Nachteil bei BCD Zahlen ist, dass man sich bei Arithmetik selbst um
Überläufe kümmern muss. Nach 0x09 (dezimal 9) kommt nicht 0x0A (dezimal
10), sondern 0x10 (dezimal 16)
> Wenn die "Ok Taste" dann gedrückt wird deklariert man zb> alarmh als 0x X.
Nein, das hilft dir nichts. Wenn du die Alarmzeit einstellst, läuft kein
Compiler mehr. Du musst dich selbst drum kümmern, dass das alles richtig
gehandhabt wird.