mikrocontroller.net

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


Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht 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 :-(

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

Du willst doch nicht zu deinem Text springen?
 
     ldi r16,1                  ; Tag der Woche in r16

     ldi ZL, low(wochentag<<1)  ; Tabellenadresse nach Z
     ldi ZH,High(wochentag<<1)

     lsl r16                    ; r16 x2
     clr r17                    ; Null

     add ZL,r16
     adc ZH,r17                 ; Offset addieren
     lpm r16,Z+
     lpm r17,Z
     movw ZH:ZL,r17:r16         ; Textadresse nach Z

     lsl ZL
     rol ZH

     lpm r16,Z+                ; Erster Buchstabe nach r16
     
    ......

wochentag:
    .dw    text_1
    .dw    text_2
    .dw    text_3
    .dw    text_4
    .dw    text_5
    .dw    text_6
    .dw    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

MfG Spess

Autor: Olli R. (downunderthunder42)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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


Peter

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

Tausche mal die Register.

MfG Spess

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.