Forum: Mikrocontroller und Digitale Elektronik Wie funktioniert .db?


von Hagrid (Gast)


Lesenswert?

Guten Abend,
heute Mittag habe ich etwas mit einer 7-Segmentanzeige herum gespielt 
und diese testweise beschaltet.
Konkretes habe ich damit noch nicht vor, allerdings bietet so eine 
Anzeige ja eine menge Möglichkeiten. Sollte es jemanden interessieren 
kann man sich hier den Code angucken. Momentan ist nicht mehr als die 
Initialisierung der Anzeige und eines Timers (CTC Mode) da. Ebenfalls 
wollte ich mal gucken wie das mit dem Zugriff auf den RAM aussieht. 
Deshalb die Speicherung der Bytes im RAM.

http://pastebin.com/wgC61hfZ

Soweit so gut. Allerdings gibt es ja auch hier auf der Seite ein 
7-Segment Tutorial.(Siehe: 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_7-Segment-Anzeige)
Nun verstehe ich die direktive .db nicht so ganz.
Auf einer anderen Seite habe ich gelesen, Zitat: ,,Der DB-Befehl erzeugt 
8-Bit Zahlen, und fügt sie an der aktuellen Stelle im Programmcode ein. 
"
Woher weiß der µC nun worauf sich die Zahl bezieht, bzw. wie er drauf 
zugreifen soll?
Mit den Zeilen:
1
 
2
...
3
 ldi temp, 0b01010000 ;0
4
 sts null, temp
5
...

Weiß der Controller ja, dass mit Null das entsprechende Bitmuster 
gemeint ist.

: Verschoben durch User
von Mike (Gast)


Lesenswert?

Hagrid schrieb:
> http://pastebin.com/wgC61hfZ

Versuch es doch mal als Dateianhang

von Bitflüsterer (Gast)


Lesenswert?

Lies bitte mal den Abschnitt "Expressions" in der Hilfe zum 
AVR-Assembler, wie er mit dem AVRStudio mitgeliefert wird.

Das beantwortet nur einen Teil Deiner Frage, sollte aber helfen die 
Frage sinnvoll nach Themen aufzuteilen und neu zu formulieren. Im Moment 
vermischst Du mehrere Dinge, die sich mit Gewinn für das Verständnis 
voneinander trennen lassen.

von Bitflüsterer (Gast)


Lesenswert?

Ich will mal etwas direkter auf Deine Frage antworten, aber es werden, 
wie ich Deinem ersten Post entnehme, danach noch Fragen offen bleiben, 
die Du aber erstmal lernen musst, präziser zu formulieren.

Hagrid schrieb:
> ...
> Auf einer anderen Seite habe ich gelesen, Zitat: ,,Der DB-Befehl erzeugt
> 8-Bit Zahlen, und fügt sie an der aktuellen Stelle im Programmcode ein.
> "
Genau. Der Assembler (nicht die CPU) wird angewiesen im Speicher einen 
bestimmten Wert abzulegen.

> Woher weiß der µC nun worauf sich die Zahl bezieht, bzw. wie er drauf
> zugreifen soll?

Ich habe beim Lesen das Problem, dass ich nicht weiß, was genau Du mit 
"der uC weiß" meinst

Es ist (aus meiner Sicht) sehr wichtig, dem uC nicht menschliche 
Eigenschaften oder Fähigkeiten zu unterstellen. Auch nicht in Gedanken. 
Der uC weiss nichts. An sich wäre das nicht weiter wichtig. Aber bei 
einer Frage woher der uC irgendwas weiß, scheitere ich schon daran, das 
der uC eben überhaupt nichts weiß - die Frage "woher" er etwas weiß ist 
dann sinnlos.

Der uC erhält in dem Programm Anweisungen (wie "LDI"). Diese Anweisungen 
sind streng zu unterscheiden von Anweisungen an den Assembler (wie z.B. 
".db").

> Mit den Zeilen:
>
>
1
> ...
2
>  ldi temp, 0b01010000 ;0
3
>  sts null, temp
4
> ...
5
>
>
> Weiß der Controller ja, dass mit Null das entsprechende Bitmuster
> gemeint ist.

Nein. Das weißt höchstens Du, weil Du einen Blick in die ASCII-Tabelle 
geworfen hast.
Der uC führt gewisse Operationen aus, die zum einen so gestaltet sind 
und die zum anderen solchermaßen benannt sind, dass der Mensch wiederum 
die Ergebnisse in konsistenter Weise interpretieren kann (nachdem er das 
in geeigneter Weise mit den Eingangsdaten getan hat).

Das ist ein Unterschied zu "der uC weiß". Der uC interpretiert nämlich 
nichts, mißt den Daten und Operationen keine "Bedeutung" zu.

Es ist nun durchaus nicht ungewöhnlich, dass Profis solche Ausdrücke 
benutzen. Das ist insbesondere für den Anfänger verwirrend. Aber der 
Profi "weiß", dass er einen mehrstufigen Interpretationsvorgang salopp 
zusammenfasst. Der Anfänger weiß das nicht und stellt deswegen die 
falschen Fragen.

Verstehe mich recht. Ich will nicht, das Du keine Fragen stellst. Aber 
es scheint mir in Deinem Fall noch zu früh die Fragen auf diese Weise zu 
stellen.

Von ".db" musst Du wissen, dass es den Assembler anweist ein Datum an 
eine bestimmte Stelle zu schreiben. Um sich darauf etwa in einem 
Ladebefehl zu beziehen, gibt es Labels, die wiederrum eine 
Speicheradresse bedeuten. Das musst Du erstmal begreifen.

von Hagrid (Gast)


Lesenswert?

Mir geht es hierbei speziell um das .db
Im Vorfeld wollte ich erwähnen, dass ich das Problem gelöst habe indem 
ich die Bitmuster in den RAM schreibe und dort auslese.

Nun ist mir allerdings aufgefallen, dass sich die Sache auch anders 
angehen lässt. Undzwar mit der .db direktive.


Bitflüsterer schrieb:
> Lies bitte mal den Abschnitt "Expressions" in der Hilfe zum
> AVR-Assembler, wie er mit dem AVRStudio mitgeliefert wird.


Das habe ich soeben gemacht und es hat ein wenig Klarheit in die Sache 
gebracht.

Allerdings verstehe ich da immer noch nicht eine Sache.
Bei der Hilfe vom Atmel Studio steht folgendes:
1
LABEL: .DB expressionlist

In dem 7-Segement Tutorial allerdings:
1
codes:
2
           .db     0b11000000        ; 0: a, b, c, d, e, f
3
           .db     0b11111001        ; 1: b, c
4
           .db     0b10100100        ; 2: a, b, d, e, g
5
           .db     0b10110000        ; 3: a, b, c, d, g
6
           .db     0b10011001        ; 4: b, c, f, g
7
           .db     0b10010010        ; 5: a, c, d, f, g
8
           .db     0b10000010        ; 6: a, c, d, e, f, g
9
           .db     0b11111000        ; 7: a, b, c
10
           .db     0b10000000        ; 8: a, b, c, d, e, f, g
11
           .db     0b10010000        ; 9: a, b, c, d, f, g

Ich habe die Sache so verstanden, dass durch das Label auf das Byte 
zugegriffen wird. Wie erfolgt der Zugriff nun auf die einzelnen Bytes da 
diese keine einzelnes Label haben?

von Easylife (Gast)


Lesenswert?

das label ist "codes" und ab dieser adresse liegen die bytes fuer das 
display hintereinander weg im speicher. also im grunde ein 
eindimensionales byte-array

von Thomas (kosmos)


Lesenswert?

Weiter oben im Programmcode wird für null ein Byte im SRAM reserviert 
und beim assemblieren wird null durch die Adresse im SRAM reserviert.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Hagrid schrieb:

> Allerdings verstehe ich da immer noch nicht eine Sache.
> Bei der Hilfe vom Atmel Studio steht folgendes:
>
1
> LABEL: .DB expressionlist
2
>
>
> In dem 7-Segement Tutorial allerdings:

Wieso "allerdings"? Da steht doch genau das, was da nach der Hilfe des 
AVR-Studio zu stehen hat. Denn da steht auch, daß das Label optional 
ist, also nicht zwingend erforderlich.

> codes:

Das ist das "Label:"

>            .db     0b11000000        ; 0: a, b, c, d, e, f

Das ist das ".db" und die nachfolgende "expression list"

Alle weiteren ".db" haben halt keine Label.

> Ich habe die Sache so verstanden, dass durch das Label auf das Byte
> zugegriffen wird. Wie erfolgt der Zugriff nun auf die einzelnen Bytes da
> diese keine einzelnes Label haben?

Es kommt drauf an, was genau man mit den Daten machen will.

Ist ab dem Label eine Zeichenkette gespeichert, die man in genau der 
gespeicherten Reihenfolge der Zeichen für eine Ausgabe benötigt, dann 
wird man die Addressierungsart indirekt mit Post-Increment benutzen.

"Indirekt" bedeutet, daß die Adresse für den Zugriff aus einem 
Indexregister kommt, welches man zuvor allerdings mit eben dieser 
Adresse befüllen muß, z.B. so:

 ldi ZL,Low(codes<<1)
 ldi ZH,High(codes<<1)

Z ist also hier das Indexregister und es wird mit der Adresse des ersten 
Zeichens der Zeichenkette gefüttert. Das "<<1" kommt daher, daß im 
Codesegment Word-Adressen benutzt werden, bei byteweisem Datenzugriff 
aber Byteadressen erforderlich sind. Die Byteadresse entspricht der 
Word-Adresse mal zwei, was das gleiche ist, wie einmal bitweise nach 
links geschoben.

Nach dem Laden der Startadresse kann man dann mit

 lpm tmp,Z+

das erste Byte/Zeichen holen und setzt dabei gleich die Adresse im 
Indexregister so, daß sie auf das zweite Byte zeigt, ein erneutes

 lpm tmp,Z+

holt also eben diese zweite Byte. Und das geht dann immer so weiter, bis 
man alle Zeichen der Zeichenkette geholt hat.

Was anderes ist, wenn man "wahlfrei" auf die Zeichen ab dem Label 
zugreifen will, was wohl für Siebensegment-Bitmuster eher relevant wäre.

Auf den Programmspeicher kann man leider weder direkt noch indirekt mit 
Offset zugreifen.
Man muß also auf jeden Fall immer erst wie oben das Z-Indexregister 
laden und im Falle des Zugriffs mit Offset auch noch die Zieladresse 
berechnen, erst dann kann man das gesuchte Datum einlesen.

Man könnte eine kleine Subroutine schreiben, die das für den konkreten 
Fall (mit Offset) tut:

;->R16: Digit-Wert (0..9)
;<-R16: Bitmuster für Siebensegment-Digit
;(Z wird "zerstört")
getpattern:
 ldi ZL,Low(codes<<1)  ;Anfangs-Adresse in's
 ldi ZH,High(codes<<1) ;Indexregister laden

 add ZL,R16            ;Zeichenoffset addieren
 clr R16               ;und eventuell nötigen
 adc ZH,R16            ;Übertrag nicht vergessen

 lpm R16,Z             ;Bitmuster von der berechneten Adresse holen
 ret

BTW: Bei "großen" Controllern mit mehr als 64k Flash reicht diese 
Routine nicht aus, jedenfalls nicht, wenn deine Daten jenseits der 
64k-Grenze stehen. Da ist dann noch ein wenig mehr Zauber nötig.

von Hagrid (Gast)


Lesenswert?

Danke für die ausführliche Erklärung!
Hab es nun verstanden. Habe mir den Wikipedia Artikel zu Indexregistern 
und Padding Bytes durchgelsen. Das hat nochmal bisschen mehr Licht ins 
dunkle gebracht.

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.