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.
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.
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.
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?
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
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.
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.