Forum: Mikrocontroller und Digitale Elektronik Uhr mit Wochentag und Datum


von Axel H. (mf-futzi)


Lesenswert?

Hallo an alle,

ich beschäftige mich seit kurzem mit uC und Asm. Nach anfänglichen 
Problemen habe ich jetzt endlich mein LCD zum Laufen gebracht und nun 
macht's richtig Spass weiter zu experimentieren (wird zur Sucht).
Aus dem Tutorial habe ich nun die Uhr mit CTC-Modus programmiert und 
funzt toll:-)
Aber wenn man Erfolg hatte will man mehr, sprich Wochentag und Datum.
Aber wie zählt man die Tage der verschiedenen Monate hoch 
(28/29/30/31Tage)? Für die Monate wollte ich auch gerne Jan, Feb, Mär, 
... ausgeben und nicht die Monatszahl.
Im Forum habe ich nichts gefunden, was mir weiterhilft, aber ich bin 
bestimmt nicht der erste, der sowas macht.
Vielleicht kennt jemand einen Link? Oder eine grobe Vorgehenweise, wie 
ich es selbst programmieren kann.

(Atmega8, Assembler)

Danke schon mal
Axel

von AVRFan (Gast)


Lesenswert?

>Aber wie zählt man die Tage der verschiedenen Monate hoch
>(28/29/30/31Tage)?

Du erstellst eine Tabelle mit 12 Einträgen, wo Du die Anzahl der Tage 
der 12 Monate reinschreibst.

>Für die Monate wollte ich auch gerne Jan, Feb, Mär,
>... ausgeben und nicht die Monatszahl.

Du erstellst eine weitere Tabelle mit 12 Einträgen, wo Du die 
Namenskürzel der 12 Monate reinschreibst.

von Axel H. (mf-futzi)


Lesenswert?

Hallo an alle,

über Tabellen habe ich im Tutorial nichts gefunden. Weis jemand, wo 
etwas über die Anwendung von Tabellen (Asm) beschrieben steht?

Danke

von Berti (Gast)


Lesenswert?

es gibt da zwei nette Algorithmen. der eine berechnet den ersten 
Mittwoch(?) des Jahres und der zweite berechnet ob das entsprechende 
Jahr ein Schaltjahr ist.
(kommt alles von der Gaussschen Osterformel?)

von Karl H. (kbuchegg)


Lesenswert?

Axel Hüser wrote:
> Hallo an alle,
>
> über Tabellen habe ich im Tutorial nichts gefunden. Weis jemand, wo
> etwas über die Anwendung von Tabellen (Asm) beschrieben steht?
>

Hier
http://www.mikrocontroller.net/articles/AVR-Tutorial:_7-Segment-Anzeige
findet sich was über Tabellen.
In diesem Beispiel gibt es eine Tabelle, in der das auf die
Anzeige auszugebende Bitmuster enthält, wenn die auszugebende
Ziffer bekannt ist.
Damit kannst du schon mal die Tageszahl pro Monat lösen, mit
Ausnahme des Februars. Der erforert (wenn man es richtig macht)
eine Verrechnung der Jahreszahl. Lass die erst mal beiseite und
konzentriere dich auf die restlichen Monate und nimm den Februar
mit 28 Tagen an (bleibt natürlich nicht so. Irgendwann must du
dich den Schaltjahren stellen. Muss aber nicht gleich sein).

von Niels H. (monarch35)


Lesenswert?

Ich presentiere:
Mein Wecker mit zwei Weckzeiten, LC-Display (16x2), SSRelay als 
"Weckgerätschalter" an Port D.3, ein-tasten-bedinung (low-aktiv an Port 
D.4),  Uhrzeit mit Wochentag und Datum. Belegt den Speicher eines 
AT-Mega8 nur zu 50%.

http://www.monarch.de/svn/work/wecker/

Vieleicht kannst du ja die ein oder andere Codezeile verwenden....

von Sebastian Heyn (Gast)


Lesenswert?

Hier mal mein schlecht Dokumentierter Code




$regfile = "m8def.dat"
$crystal = 16000000

Config Timer1 = Timer , Prescale = 256
On Timer1 Timer_irq
Const Timervorgabe = 3036


Dim Year As Integer                                         'jahr
Dim Month As Byte                                           'monat
Dim Dayofmonth As Byte                                      'tag

Dim Timerbit As Bit                                         'if this bit 
is set then count another second

Dim H As Integer 
'hilfsvariable
Dim Sj As Bit 
'schaltjahrbit

Dim Tz As Byte                                              'tagesziffer
Dim Mz As Byte 
'monatsziffer
Dim Jz As Byte 
'jahresziffer
Dim Jhz As Byte 
'jahrhunderziffer
Dim Wt As Byte 
'wochentag:0=so, 1=mo etc


Dim Hr As Byte
Dim Minu As Byte
Dim Seco As Byte


Dim Jahrstring As String * 5
Dim Jzh1 As Byte                                            'hilfbyte1 ( 
letzten beiden stellen)
Dim Jzh2 As Byte                                            'hifsbyte2
Dim Jzh3 As Byte                                            'hilfbyte3
Dim Jzh4 As Bit

'Startdatum


Enable Timer1
Enable Interrupts

Do

If Timerbit = 1 Then
Timerbit = 0

Seco = Seco + 1

If Seco = 60 Then
Minu = Minu + 1
Seco = 0
End If

If Minu = 60 Then
Hr = Hr + 1
Minu = 0
End If

If Hr = 24 Then
Hr = 0
Dayofmonth = Dayofmonth + 1
End If

'Monatssprung für Februar kann erst nach Schaltjahr-check gemacht 
werden.

If Month = 1 Or Month = 3 Or Month = 5 Or Month = 7 Or Month = 8 Or 
Month = 10 Then
If Dayofmonth = 32 Then
Month = Month + 1
Dayofmonth = 1
End If
End If

If Month = 4 Or Month = 6 Or Month = 9 Or Month = 11 Then
If Dayofmonth = 31 Then
Month = Month + 1
Dayofmonth = 1
End If
End If

If Month = 12 And Dayofmonth = 32 Then
Month = 1
Dayofmonth = 1
Year = Year + 1
End If


'Schaltjahrerkennung
Sj = 0                                                      'erstmal 
gehen wir von einer 0 aus
H = Year Mod 4

If H = 0 Then                                               'durch 4 
teilbar?
H = Year Mod 100
Sj = 1                                                      'Ja dann 
schaltjahr
End If

'durch 100 teilbar??
If H = 0 Then                                               'ja dann
H = Year Mod 400                                            'durch 400 
teilbar
If H = 0 Then
Sj = 1
Else                                                        'ja dann 
schaltjahr
Sj = 0
End If                                                      'nein dann 
nicht
End If

If Sj = 1 Then Print "     Schaltjahr ";
If Sj = 0 Then Print "Kein Schaltjahr ";

If Month = 2 And Sj = 1 And Dayofmonth = 30 Then
Month = Month + 1
Dayofmonth = 1
End If

If Month = 2 And Sj = 0 And Dayofmonth = 29 Then
Month = Month + 1
Dayofmonth = 1
End If




' Wochentag berechnen
Tz = Dayofmonth Mod 7

'Monatsziffer
If Month = 1 Then Mz = 0
If Month = 2 Then Mz = 3
If Month = 3 Then Mz = 3
If Month = 4 Then Mz = 6
If Month = 5 Then Mz = 1
If Month = 6 Then Mz = 4
If Month = 7 Then Mz = 6
If Month = 8 Then Mz = 2
If Month = 9 Then Mz = 5
If Month = 10 Then Mz = 0
If Month = 11 Then Mz = 3
If Month = 12 Then Mz = 5

'Jahresziffer
Jahrstring = Str(year)
Jahrstring = Right(jahrstring , 2)
Jzh1 = Val(jahrstring)
Jzh2 = Jzh1 Mod 12
Jzh3 = Jzh2 \ 4
Jz = Jzh1 \ 12
Jz = Jz + Jzh2
Jz = Jz + Jzh3
Jz = Jz Mod 7



'jahrhunderziffer
Jahrstring = Str(year)
Jahrstring = Left(jahrstring , 2)
Jzh1 = Val(jahrstring)
Jzh1 = Jzh1 + 4
Jzh4 = 0
Do
If Jzh1 = 19 Then
Jhz = 0
Jzh4 = 1
End If
If Jzh1 = 18 Then
Jhz = 2
Jzh4 = 1
End If
If Jzh1 = 17 Then
Jhz = 4
Jzh4 = 1
End If
If Jzh1 = 16 Then
Jhz = 6
Jzh4 = 1
End If
Jzh1 = Jzh1 - 4
Loop Until Jzh4 = 1

Wt = Tz + Mz
Wt = Wt + Jz
Wt = Wt + Jhz
Wt = Wt Mod 7

If Month < 3 And Sj = 1 Then
If Wt = 0 Then Wt = 6
If Wt = 1 Then Wt = 0
If Wt = 2 Then Wt = 1
If Wt = 3 Then Wt = 2
If Wt = 4 Then Wt = 3
If Wt = 5 Then Wt = 4
If Wt = 6 Then Wt = 5
End If

If Wt = 0 Then Print "So ";
If Wt = 1 Then Print "Mo ";
If Wt = 2 Then Print "Di ";
If Wt = 3 Then Print "Mi ";
If Wt = 4 Then Print "Do ";
If Wt = 5 Then Print "Fr ";
If Wt = 6 Then Print "Sa ";

Print "der " ; Dayofmonth ; "." ; Month ; "." ; Year ; " - " ; Hr ; ":" 
; Minu ; ":" ; Seco
End If                                                      ' timerbit
Loop 
'hauptschleife


Timer_irq:
  Timer1 = Timervorgabe
Timerbit = 1
Return

von AVRFan (Gast)


Lesenswert?

>Damit kannst du schon mal die Tageszahl pro Monat lösen, mit
>Ausnahme des Februars. Der erforert (wenn man es richtig macht)
>eine Verrechnung der Jahreszahl.

Das ist nun wirklich nicht wild - man erstellt einfach eine zweispaltige 
Tabelle.  In der ersten Spalte stehen die Anzahl der Tage in jedem Monat 
für die normalen Jahre, in der zweiten dasselbe für die Schaltjahre:

AnzahlTageImMonat:
.DB 31, 31  ; Januar
.DB 28, 29  ; Februar
.DB 31, 31  ; ...
.DB 30, 30
.DB 31, 31
.DB 30, 30
.DB 31, 31
.DB 31, 31
.DB 30, 30
.DB 31, 31
.DB 30, 30
.DB 31, 31  ; Dezember

In der nächsten Zeit (bis zum Jahr 2099) ist ein Jahr genau dann ein 
Schaltjahr, wenn die Jahreszahl durch 4 teilbar ist.  Das kann man in 
einem Programm leicht überprüfen (Bits Nr. 0 und 1 der Jahreszahl beide 
= 0)

von Axel H. (mf-futzi)


Lesenswert?

Danke erstmal für Eure Beiträge.

Ich werde mich mal mit dem Syntax und Tabellen befassen und melde mich 
sicherlich nochmal, wie es geklappt hat, oder weitere Fragen ;-)

VG
Axel

von Axel H. (mf-futzi)


Lesenswert?

Hallo,

ich hab jetzt noch'ne Frage zu den Tabellen. Aber zuerst mein Code zur 
Ausgabe am LCD:



Ausgabe:      (8+8 LCD)

; Ausgabe ab 1.Stelle im LCD        ; HIER DEN MONATSNAMEN IM
  ldi ZL, LOW(MonthName *2)           ; LCD AUSGEBEN
     ldi ZH, HIGH(MonthName *2)

  rcall lcd_flash_string

  ldi temp1 , $A8
     rcall lcd_command

; Ausgabe ab 9.Stelle im LCD

     mov   temp1, Stunden      ; Stunden ausgeben
  rcall lcd_number

  ldi  temp1, ':'            ; ':' ausgeben
  rcall  lcd_data

     mov   temp1, Minuten      ; Minuten ausgeben
  rcall lcd_number

  ldi  temp1, ':'      ; ':' ausgeben
  rcall  lcd_data

     mov   temp1, Sekunden      ; Sekunden ausgeben
  rcall lcd_number

     ldi   temp1 , $80
     rcall lcd_command

end_isr:
  reti

.include "C:\Dokumente und Einstellungen\GDWAZH\Eigene 
Dateien\Projekte\lcd-routines.asm"


MonthName:
  .db "Jan",0,0
  .db "Feb",0,0
  .db "Mär",0,0
  .db "Apr",0,0
  .db "Mai",0,0
  .db "Jun",0,0
  .db "Jul",0,0
  .db "Aug",0,0
  .db "Sep",0,0
  .db "Okt",0,0
  .db "Nov",0,0
  .db "Dez",0,0

Wie kann ich jetzt auf eine einzelne Zeile von MonthName zugreifen? Wenn 
ich nun 'Nov' ausgeben möchte, so ist das das 11.Element der Tabelle. 
Aber wie übergeben?

von AVRFan (Gast)


Lesenswert?

Schau Dir mal den Befehl "lpm" an.

von Hannes L. (hannes)


Lesenswert?

Und schau Dir mal Deinen Build-Output an, der hat bestimmt 'ne Menge 
Warnungen. Doppelklick auf die Warnung zeigt Dir den Fehler...

...

von Hannes L. (hannes)


Angehängte Dateien:

Lesenswert?

Im Anhang findest Du eine Routine, die indizierten Text aus Tabelle 
ausgenen kann. Eine zugehörige Tabelle könnte so aussehen:
1
mt:                         ;Indexliste Menütexte
2
.dw mt0,mt1,mt2,mt3
3
.dw mt4,mt5,mtr,mtr
4
.dw mtr,mtr,mt10,mt11
5
.dw mt12,mt13,mt14,mt15
6
7
mt0:    .db 4,   "Pos.Show Rpt.   Home    Up 1    Up 10 ",13
8
        .db      "                Delete  Show-Nr Repeat ",13
9
        .db      "                End     Down 1  Down 10",13
10
        .db      "                Abbruch Del.all Start ",1,0
11
12
mt1:    .db 9,16,"1 Dimmwerte laden       ",9,56
13
        .db      "Speicherplatz-Nr        ",9,96
14
        .db      "(00-63):",1,0
15
16
mt2:    .db 9,16,"2 Dimmwerte speichern   ",9,56
17
        .db      "Speicherplatz-Nr        ",9,96
18
        .db      "(00-63):",1,0
19
20
mt3:    .db 9,16,"3 Auswahl PWM-Kanal     ",9,56
21
        .db      "Kanal-Nr                ",9,96
22
        .db      "(00-15):",1,0
23
24
mt4:    .db 9,16,"4 Dimmwert Kanal ",13,9,56
25
        .db      "einstellen              ",9,96
26
        .db      "(00-99):",1,0
27
28
mt5:    .db 9,16,"5 Dimmtempo beim Wechsel",9,56
29
        .db      "der Dimmwerte           ",9,96
30
        .db      "(00-99):",1,0
31
32
mt10:   .db 9,56,"16-Kanal-Lichtsteuerung ",9,96
33
        .db      " (c)  www.hanneslux.de  ",1,0
34
35
mt11:   .db 9,16,"1 Laden     2 Saven     ",9,56
36
        .db      "3 PWM-Kanal 4 Dimmwert  ",9,96
37
        .db      "5 Dimmtempo, statisch   ",9,136
38
        .db      "0 Dynam. Lichtsteuerung ",1,0
39
40
mt12:   .db 9,16,"5 Lichtshow zur Liste   ",9,56
41
        .db      "hinzufuegen             ",9,96
42
        .db      "(00-99):",1,0
43
44
mt13:   .db 9,16,"7 Anzahl Wiederholungen ",9,56
45
        .db      "der Lichtshow           ",9,96
46
        .db      "(00-99):",1,0
47
48
mt14:
49
50
mt15:
51
52
mtr:    .db 9,16,"Reserviert fuer         ",9,56
53
        .db      "spaetere Erweiterungen..",0,0

Es handelt sich hier zwar nicht um Wochentage oder Monatsnamen, sondern 
um Menüpunkte, das Prinzip ist aber dasselbe.

...

von Uwe (Gast)


Lesenswert?

Hi!
>Wenn ich nun 'Nov' ausgeben möchte, so ist das das 11.Element der Tabelle.
nein, Eine Monatsangabe hat doch bei dir 5 Byte oder? Also 10 "deiner" 
Elemente willst du überspringen-> 10 x 5 Byte = 50 Byte, also
     ldi ZL, LOW(MonthName *2)           ; LCD AUSGEBEN
     ldi ZH, HIGH(MonthName *2)
     ldi temp1,50
     clr temp2
     add ZL,temp1
     adc ZH,temp2
       :
       :

sollte Nov ausgeben.


Viel Erfolg, Uwe

von Axel H. (mf-futzi)


Lesenswert?

Hallo Hannes,

keine Fehler, keine Warnungen

von Hannes L. (hannes)


Lesenswert?

Axel Hüser wrote:
> Hallo Hannes,
>
> keine Fehler, keine Warnungen

Dann hast Du in den Einstellungen die Warnungen deaktiviert...
Bei Tabellen (Listen) mit einfachen nullterminierten Texten ist das kein 
Problem, der Assembler hängt halt noch ein Nullbyte an, aber man sollte 
sich trotzdem angewöhnen, die Anzahl der Bytes in einem .db-Eintrag 
geradzahlig zu galten. Das ist in Deinem Code definitiv nicht so:

  .db "Jan",0,0    ; 5 Bytes, ist nicht geradzahlig...
  .db "Feb",0,0
  .db "Mär",0,0

Uwe wrote:
>> Wenn ich nun 'Nov' ausgeben möchte, so ist das das 11.Element der
>> Tabelle.
> nein, Eine Monatsangabe hat doch bei dir 5 Byte oder? Also 10 "deiner"
> Elemente willst du überspringen-> 10 x 5 Byte = 50 Byte, also
>      ldi ZL, LOW(MonthName *2)           ; LCD AUSGEBEN
>      ldi ZH, HIGH(MonthName *2)
>      ldi temp1,50
>      clr temp2
>      add ZL,temp1
>      adc ZH,temp2
>        :
>        :

> sollte Nov ausgeben.

Das wird so einfach nicht gehen, denn es gibt keie .db-Zeile mit 5 
Bytes. Der Assembler hängt da ein 6. Byte an, damit die Anzahl der Bytes 
wieder geradzeilig wird, der Flash ist nämlich wordadressiert, jede 
Zelle fasst zwei Bytes.

Daher ist es besser, eine Indexliste zu führen und eine Ausgaberoutine 
zu schreiben, die mit Indexliste (die die eigentlichen Adressen der 
Texte enthält, die auch noch unterschiedlich lang sein dürfen) arbeitet, 
siehe mein Beispiel.

Abgesehen davon nützt diese Routine sowiso nichts, da der Monat nicht 
als Konstante vorliegt, sondern als Variable.
>      ldi temp1,50
>      clr temp2
funktioniert da nicht...

...

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
Noch kein Account? Hier anmelden.