Forum: Mikrocontroller und Digitale Elektronik Uhr mit ATmega8 Wochentage aus "Stringtabelle" lesen oder wie?


von Olli R. (downunderthunder42)


Lesenswert?

Hallo,

ich wollte zur Übung mit meinem eine Uhr basteln.
Die Ausgabe erfolgt auf einem LCD.

Die Uhrzeit usw. wird schon angezeigt.

jetzt frage ich mich, wie ich es machen kann, dass Strings "Montag", 
"Dienstag" etc.  "Januar", "Februar" etc. in Abhängigkeit des Wertes 
einer Zählvariablen ausgegeben werden können?

Mein erster Ansatz sieht wie folgt aus:

*******************************************
wochentag:
    rjmp    text_1
    rjmp    text_2
    rjmp    text_3
    rjmp    text_4
    rjmp    text_5
    rjmp    text_6
    rjmp    text_7



text_1:
                   .db "Montag",0
text_2:
       .db "Dienstag",0
text_3:
       .db "Mittwoch",0
text_4:
       .db "Donnerstag",0
text_5:
       .db "Freitag",0
text_6:
       .db "Sonnabend",0
text_7:
       .db "Sonntag",0

******************************
um zwischen den einzelnen Strings zu wechseln, würde ich eine 
Zählvariable, die von 0 bis 6 zählt verwenden und davon abhängig machen, 
ob nun Montag, Dienstag oder so weiter ausgeben werden soll?

Gibt es soetwas wie "einen bedingten Speicherzugriff"? oder wie könnte 
man da vorgehen?

von H.Joachim S. (crazyhorse)


Lesenswert?

du willst sicher nicht wirklich auf die Stringtabelle springen, denn 
dann würde das dort stehende als Code interpretiert.
Du solltest das Z-Register mit der Adresse des jeweiligen ersten 
Zeichens laden und von dort aus mittels lpm die Bytes holen. Aber aus 
dem Ärmel schüttel ich Assembler inzwischen auch nicht mehr :-(

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

So einfach kannst du hier nicht indirekt zugreifen, weil die einzelnen 
Zeichenketten unterschiedliche Längen haben.

Ergo: text_1, ... text_7 ebenfalls in eine Tabelle eintragen, und 
zweifach indirekt zugreifen. D.h. im ersten Zugriff wird text_n, also 
die Adresse der Zeichenkette gelesen, und damit wird dann auf die 
eigentliche Zeichenkette zugegriffen.

Was die konkrete Syntax angeht: da kennst du den Atmel-Assembler besser 
als ich ;-)

von Olli R. (downunderthunder42)


Lesenswert?

Johann L. schrieb:
> So einfach kannst du hier nicht indirekt zugreifen, weil die einzelnen
> Zeichenketten unterschiedliche Längen haben.
>
> Ergo: text_1, ... text_7 ebenfalls in eine Tabelle eintragen, und
> zweifach indirekt zugreifen. D.h. im ersten Zugriff wird text_n, also
> die Adresse der Zeichenkette gelesen, und damit wird dann auf die
> eigentliche Zeichenkette zugegriffen.
>
> Was die konkrete Syntax angeht: da kennst du den Atmel-Assembler besser
> als ich ;-)

Naja das wird sich noch zeigen!




Also gut ergo zweifach indirekt zugreifen! dann werde ich mich mal an 
die Arbeit machen.

von Spess53 (Gast)


Lesenswert?

Hi

>Gibt es soetwas wie "einen bedingten Speicherzugriff"? oder wie könnte
>man da vorgehen?

Du willst doch nicht zu deinem Text springen?
1
 
2
     ldi r16,1                  ; Tag der Woche in r16
3
4
     ldi ZL, low(wochentag<<1)  ; Tabellenadresse nach Z
5
     ldi ZH,High(wochentag<<1)
6
7
     lsl r16                    ; r16 x2
8
     clr r17                    ; Null
9
10
     add ZL,r16
11
     adc ZH,r17                 ; Offset addieren
12
     lpm r16,Z+
13
     lpm r17,Z
14
     movw ZH:ZL,r17:r16         ; Textadresse nach Z
15
16
     lsl ZL
17
     rol ZH
18
19
     lpm r16,Z+                ; Erster Buchstabe nach r16
20
     
21
    ......
22
23
wochentag:
24
    .dw    text_1
25
    .dw    text_2
26
    .dw    text_3
27
    .dw    text_4
28
    .dw    text_5
29
    .dw    text_6
30
    .dw    text_7
31
32
text_1:  .db "Montag",0
33
text_2:  .db "Dienstag",0
34
text_3:  .db "Mittwoch",0
35
text_4:  .db "Donnerstag",0
36
text_5:  .db "Freitag",0
37
text_6:  .db "Sonnabend",0
38
text_7:  .db "Sonntag",0

MfG Spess

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

Hallo Spess,

ich habe jetzt mal deinen Tipp versucht umzusetzen.


Ich habe in der Hauptschleife (loop) alle Befehle ausser dem Aufruf der 
Stringausgabe "kommentarisiert".

Leider wird nichts auf dem Display ausgegeben (alle Felder am LCD 
leuchten)

Wodran mag das liegen?
Ich weiss, dass man natürlich noch an der Nutzung (also wie viel und 
welche) der Register noch arbeiten kann!

von Peter D. (peda)


Lesenswert?

Bei so kurzen Strings kann man aber auch einfach die Null-Bytes 
abzählen:
1
        ldi     r16, 0                  ; 0 = Montag
2
3
        ldi     ZL, low(wochentag<<1)   ; Tabellenadresse nach Z
4
        ldi     ZH, High(wochentag<<1)
5
        rjmp    _wt2
6
wochentag:
7
        .db     "Montag",0, \
8
                "Dienstag",0, \
9
                "Mittwoch",0, \
10
                "Donnerstag",0, \
11
                "Freitag",0, \
12
                "Sonnabend",0, \
13
                "Sonntag",0
14
_wt1:
15
        lpm     r0, z+
16
        and     r0, r0
17
        brne    _wt1
18
_wt2:
19
        subi    r16, 1
20
        brcc    _wt1
21
22
        lpm     r16, Z+                 ; Erster Buchstabe nach r16


Peter

von Spess53 (Gast)


Lesenswert?

Hi

>.def wochentag_nr_h = r26
>.def wochentag_nr_l = r27

Tausche mal die Register.

MfG Spess

von Olli R. (downunderthunder42)


Lesenswert?

Spess53 schrieb:
>>.def wochentag_nr_h = r26
>>.def wochentag_nr_l = r27
>
> Tausche mal die Register.

Ok cool jetzt klappt's.

Gut wenn schon das Registerpaar r26/r27 verwendet wird, sollte
das register mit der höheren nummer (r27) auch dem Highteil zugeordnet 
werden.

Das hätte ich wohl erst in ewig und 3 Tage nicht gefunden.


Vielen Dank





Peter Dannegger schrieb:
> Bei so kurzen Strings kann man aber auch einfach die Null-Bytes
> abzählen:
>         ldi     r16, 0                  ; 0 = Montag
>
>         ldi     ZL, low(wochentag<<1)   ; Tabellenadresse nach Z
>         ldi     ZH, High(wochentag<<1)
>         rjmp    _wt2
> wochentag:
>         .db     "Montag",0, \
>                 "Dienstag",0, \
>                 "Mittwoch",0, \
>                 "Donnerstag",0, \
>                 "Freitag",0, \
>                 "Sonnabend",0, \
>                 "Sonntag",0
> _wt1:
>         lpm     r0, z+
>         and     r0, r0
>         brne    _wt1
> _wt2:
>         subi    r16, 1
>         brcc    _wt1
>
>         lpm     r16, Z+                 ; Erster Buchstabe nach r16

Werd ich beizeiten auch mal implementieren. Vorerst reicht mir eine 
funktionierende Lösungen --> später geht's dann ans optimieren

von Spess53 (Gast)


Lesenswert?

Hi

>Gut wenn schon das Registerpaar r26/r27 verwendet wird, sollte
>das register mit der höheren nummer (r27) auch dem Highteil zugeordnet
>werden.

Nur ein Grund dieses def-Gedödel zu meiden.

MfG Spess

von Olli R. (downunderthunder42)


Lesenswert?

Also ich habe meine Uhr jetzt soweit realisiert:

Wochentage werden angezeigt
Monate habe unterschiedliche Anzahl an Tage
alle 4 Jahre tritt ein Schaltjahr auf
alle 100 Jahre gibt es kein Schaltjahr nach 4 Jahren
außer alle 400 Jahre

ob das alles Sinn macht sei erstmal dahingestellt.

(in 80 oder 400 Jahren wird die Uhr eh keiner mehr nutzen)


Aber egal nun zum nächsten Schritt:

Ich wollte die Uhr jetzt extern über 2 Taster stellen können.

Dazu wollte ich INT0 und INT1 verwenden:

Die eine ISR schaltet zwischen den Stellgrößen (Stunden, Minuten, etc.)
In der anderen ISR wird die jeweilige Stellgröße inkrementiert.

Nun bin ich auf ein Problem gestoßen:

Die Eingänge von INT0 und INT1 scheinen zu prellen.

Immer wenn ich über einen Taster einen Interrupt auslöse, wird der 
jeweilige Zahlenwert gleich um 3, 4 oder 5 erhöht?

wie kann ich den INT0 z.B. entprellen oder hat das damit doch nichts zu 
tun?

von Karl H. (kbuchegg)


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten


Und Tasten muss man keineswegs über Interrupts auswerten. Ganz im 
Gegenteil.

Wenn du deine Tastenabfrage in die jeweilige Hauptschleife reinmachst, 
ist das mehr als schnell genug.

von Olli R. (downunderthunder42)


Lesenswert?

Karl heinz Buchegger schrieb:
> Und Tasten muss man keineswegs über Interrupts auswerten. Ganz im
> Gegenteil.
>
> Wenn du deine Tastenabfrage in die jeweilige Hauptschleife reinmachst,
> ist das mehr als schnell genug.

Ja ok ic glaube ich werde mich mal mit der Methode von dem Herrn 
Dannegger befassen. Irgendwie ist mir das aber noch nicht ganz klar.
Deshalb schaue ich mir das morgen nochmal in aller Ruhe an.

Mir ist aufgefallen, dass dort die unteren Register verwendet werden!

Da mir jetzt auch schon aufgefallen ist, dass man doch recht schnell in 
"Registernotstand" gerät, wollte ich mal fragen, wie das noch mit den 
Registern r0 bis r15 war?
Es können bei denen doch nicht alle Befehle angwendet werden?

ich hab im Datenblatt dazu keine genaue Beschreibung gefunden?

von Spess53 (Gast)


Lesenswert?

Hi

>... wollte ich mal fragen, wie das noch mit den
>Registern r0 bis r15 war?
>Es können bei denen doch nicht alle Befehle angwendet werden?

Richtig:

http://www.atmel.com/atmel/acrobat/doc0509.pdf

Überall wo dort r16...r31 steht geht es mit den unteren Registern nicht.

>Da mir jetzt auch schon aufgefallen ist, dass man doch recht schnell in
>"Registernotstand" gerät,...

Hast du einen Registerschwund? Ich habe immer 32 Register zur Verfügung.
Noch nie einen Notstand gehabt. Aber lass mich raten: du benutzt dieses 
unselige .def-Gedödel und weist Registern eine bestimmte Funktion zu. 
Selbst schuld wenn es dann eng wird. Man muss nicht jeden Sch... 
mitmachen. Und wenn du davon nicht lassen kannst: einige AVRs haben auch 
noch GPIO-Register und RAM die meisten.

MfG Spess

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.