Umgebung AVR-Studio 4.0, Atmega8
Habe ich folgendes richtig verstanden:
RAMEND ist eine 16bit-Variable und gibt mir das Ende des SRAM(speichers)
an. Weil RAMEND 16bit groß ist und die Register in der Regel nur 8bit,
muss ich RAMEND mit LOW oder HIGH auftrennen, um einmal "nur" die Bits
0-7 (LOW) und zum anderen die Bits 8-15 (HIGH) zu bekommen?
Und der uC füllt von selber das SRAM von vorne, um z.B. Sprungadressen
etc. zu speichern und damit ich nicht damit "kollidiere", fülle ich den
Speicher bei selbstgemachten Anwendungen einfach von hinten?
SRAM
Begin
uC-Sprungadressen etc.
uC-Sprungadressen etc.
uC-Sprungadressen etc.
.
.
.
.
eigene Variable
eigene Variable
eigene Variable
eigene Variable
eigene Variable
Ende
Hi
>RAMEND ist eine 16bit-Variable und gibt mir das Ende des SRAM(speichers)>an.
Bei kleineren AVRs gibt es das auch in 8 Bit.
>Und der uC füllt von selber das SRAM von vorne, um z.B. Sprungadressen>etc. zu speichern und damit ich nicht damit "kollidiere", fülle ich den>Speicher bei selbstgemachten Anwendungen einfach von hinten?
Genau umgekehrt. Der Stackpointer wird aud RAMEND gesetzt und bewegt
sich in Richtung RAM-Anfang. Deine Variblen platzierst an den Anfang.
MfG Spess
PC-Anfaenger schrieb:> Umgebung AVR-Studio 4.0, Atmega8>> Habe ich folgendes richtig verstanden:>> RAMEND ist eine 16bit-Variable
Fast.
RAMEND ist einfach nur eine konstante Zahl, die dir im Assembler zur
Verfügung steht.
(Um das Korinthenkacken zu verstehen: Eine Variable ist etwas, das man
per Programm auch ändern kann)
> und gibt mir das Ende des SRAM(speichers)
genau
> an. Weil RAMEND 16bit groß ist und die Register in der Regel nur 8bit,> muss ich RAMEND mit LOW oder HIGH auftrennen, um einmal "nur" die Bits> 0-7 (LOW) und zum anderen die Bits 8-15 (HIGH) zu bekommen?
exakt
> Und der uC füllt von selber das SRAM von vorne, um z.B. Sprungadressen> etc. zu speichern und damit ich nicht damit "kollidiere", fülle ich den> Speicher bei selbstgemachten Anwendungen einfach von hinten?
Genau anders rum.
Der Stack beginnt am hinteren (oberen) Ende und wächst nach unten (hin
zu kleineren Adressen)
Deswegen beginnen deine Speicherbelegungen im SRAM bei den kleinen
Adressen. Aber das weiß der Assembler alles und vergibt die
Reservierungen entsprechend.
Danke für die Antworten.
Mal ne Frage - SRAM und Stack - ist das identisch, ist mit SRAM zufällig
S(tack)RAM gemeint? Weil in dem Tutorial ist mal von SRAM und mal von
Stack die Rede, ich dachte, es wären zwei verschiedene Speicher-Arten,
so wie das EEPROM auch etwas anderes wie das SRAM ist.
Hi
>Mal ne Frage - SRAM und Stack - ist das identisch, ist mit SRAM zufällig>S(tack)RAM gemeint?
Nein. SRAM ist die Abkürzung für Static RAM. Der Stack ist ein
Speicherbereich im RAM (welcher auch immer), der vom Controller
verwaltet wird.
MfG Spess
Ich versuche grade das Kapitel SRAM aus dem AVR-Tutorial zu verstehen.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_SRAM
Ich habe das erste Beispielprogramm gestartet und will im Debugger
sehen, was passiert. In einer Unterprogrammzeile timer0_overflow wird
mit
lds temp1, PWMCount aus dem Speicher der Wert an der Speicherstelle
PWMCount in temp1 geladen.
Meine Frage nun, wo kann ich im Debugger den Speicher sehen, da gibt es
das Fenster "Memory" und ich kann in Unterklassen wählen zwischen
I/O
Data
EEPROM
Program
Register
I/O denke ich mal ist das gleiche wie das Fenster I/O-View, Register
wird mir nur die Register anzeigen, EEPROM ist ein anderes Kapitel und
hat nix mit SRAM zu tun. Also bleiben Data und Programm übrig, wobei ich
mir aber nun nicht sicher bin, ob der Wert auch in Program stehen könnte
- oder steht der gesichterte Wert an der Stelle PWMCount irgendwo in dem
Fenster DATA?
Hi
>Also bleiben Data und Programm übrig, wobei ich>mir aber nun nicht sicher bin, ob der Wert auch in Program stehen könnte>- oder steht der gesichterte Wert an der Stelle PWMCount irgendwo in dem>Fenster DATA?
Der RAM wird in Data dargestellt. Aber dort hast du keine Zuordnung zu
deinen 'Variablen'.
Du kannst aber im Debug-Mode über View->Watch ein Fenster aktivieren in
dem du deine 'Variablen' eintragen kannst. Da wird dir dann der Inhalt
angezeigt.
MfG Spess
Hi
Der Grund für verschiedene Speicher (bereiche) ist die Physik. Ein SRAM
ist nicht stabil und verändert sich bei Spannungsausfall. Bei Wiederkehr
können zufällige Werte drin stehen. Dafür aber ist er unbegrenzt
beschreibbar. Da ständig irgendwelche Adressen gemerkt oder Variablen
verändert werden, darf der Speicher durch Schreibvorgänge nicht
"zerstört" werden. Genau dies ist aer bei einem Flash-Ram der Fall.
Scherlich, erst nach einigen tausend Schreibvorgängen, aber wenn man
bedenkt, das ein µC mit 16 MHz getaktet ungefähr 1 Mio. Schreibvorgänge
durchführen kann, wär der Flash sehr schnell hin....
Dem EEPRom ergeht es ebenso. Auch er "verbraucht" sich bei
Schreibvogängen. Es sind zwar schon ein paar 10000, aber eben das selbe
Problem. Durch die ständigen erforderlichen SChreibzugriffe auf den
Speicher überlebt ein EEProm dies nicht allzulange und so hat schon
manch einer seine Controller geschlachtet, weil er einfach den Hinweis
im Datenblatt keine Beachtung geschenkt hat. Ich denke, nun ist es klar:
.DSEG für ständige Schreibzugriffe unbegrenzt, dafür aber flüchtig bei
Spannungsausfall
.CSeg für Programm, da begrenzte Schreibzyklen
.ESeg für Programmparameter, die sich in begrenzter Häufigkeit ändern
dürfen oder zur Datenrettung bei detektiertem Netzausfall und einer
kleinen Gangreserve.
Gruß oldmax
Ich verstehe grade den Speicher nicht. Ich habe mir jetzt in dem Fenster
Memory mal alle möglichen Teile angesehen.
Die Adresse ist immer 6stellig mit Hexadecimalzahlen
Register fängt z.B. an bei 00:00:00 und hört bei 00:00:1E auf. Da 1E_hex
= 31_decimal ist, sind das die einzelnen Register.
Data fängt an bei
00:00:60 und geht bis 00:04:5E
Ich komme damit nicht klar, warum manche Speicherstellen immer wieder
bei 00:00:00 anfangen, es müsste doch eigentlich einmal bei 00:00:00
beginnen, zB. Programm oder so und geht bis zu seinem MaxWert und danach
müsste dann z.B. Data kommen, Data fängt ja z.B. hier auch erst bei
00:00:60 an und nicht bereits ab 00:00:00?
Und wenn ich drei HexPaare habe, dann habe ich ja 16^6-1
Adressierungsmöglichkeiten bzw. 2^24-1 Speicherstellen, brauch ich denn
überhaupt so viel Adressraum für 1kB Speicher?
spess53 schrieb:> Variablen
schon klar, aber hinter einem Variablen-Namen müsste doch eine
Speicherstelle "verborgen" sein, so könnte doch z.B. die Variable
PWMcount in dem Fallbeispiel z.B. die Speicheradresse 00:00:FF haben???
Ich habe jetzt noch nicht kapiert, ob ich die Speicheradresse von
"Variable" dierekt zuordne, oder vergibt der Compiler die
Speicheradresse für Variable, ohne dass ich es weis? Wenn ja, hat der
Compiler dann einen Schutz, dass er nicht zweimal die gleiche
Speicherstelle einer Variablen zuordnet?
PC-Anfaenger schrieb:> Register fängt z.B. an bei 00:00:00 und hört bei 00:00:1E auf. Da 1E_hex> = 31_decimal ist, sind das die einzelnen Register.>> Data fängt an bei>> 00:00:60 und geht bis 00:04:5E>> Ich komme damit nicht klar, warum manche Speicherstellen immer wieder> bei 00:00:00 anfangen, es müsste doch eigentlich einmal bei 00:00:00> beginnen, zB. Programm oder so und geht bis zu seinem MaxWert und danach> müsste dann z.B. Data kommen, Data fängt ja z.B. hier auch erst bei> 00:00:60 an und nicht bereits ab 00:00:00?
Programm und Data sind in verschiedenen Speicherbereichen untergebracht.
der Programmbereich hat seine eigene Zählung
Der Datenbereich hat seine eigene Zählung.
> Und wenn ich drei HexPaare habe, dann habe ich ja 16^6-1> Adressierungsmöglichkeiten bzw. 2^24-1 Speicherstellen, brauch ich denn> überhaupt so viel Adressraum für 1kB Speicher?
In deinem µC nicht.
Aber es gibt ja auch noch andere µC aus der gleichen Hersteller-familie,
die dann entsprechend mehr Speicher haben. Und dann brauchst du die
Adressiermöglichkeit.
Ich hab mal folgende Rechnung gemacht:
Data fängt erst bei 00:00:60 an, ich fragte mich, was kommt davor.
Addiere ich 3F (IO_View geht von 00:00:00 bis 00:00:3F) und 1F (Register
geht von 00:00:00 bis 00:00:1F), dann komme ich auf 5E, dann vlt. noch
ein Reserve-Bit, dann bin ich bei :60.
Könnte ich also sagen, dass IO_View und Register auch im SRAM sind, Data
aber erst ab ..:60 beginnt, weil davor IO_View und Register kommen und
Register und IO-View können sich auch so oft verändern, so dass die auch
nicht in das EEPROM (ESEG) bzw. in das CSEG dürfen, wegen der begrenzten
Schreibzyklen???
Karl Heinz Buchegger schrieb:> Aber es gibt ja auch noch andere µC aus der gleichen Hersteller-familie,> die dann entsprechend mehr Speicher haben. Und dann brauchst du die> Adressiermöglichkeit.
Danke fuer den Hinweis, also ist das softwarebedingt so, dass das
Fenster 6 Hexadecimalzahlen anzeigt, obwohl die für mein Modell Mega8
das nicht gebraucht würde aber dann evtl. für eines dieser
32bit-Modelle?
PC-Anfaenger schrieb:> Speicherstelle "verborgen" sein, so könnte doch z.B. die Variable> PWMcount in dem Fallbeispiel z.B. die Speicheradresse 00:00:FF haben???
Ja, könnte sie.
> Ich habe jetzt noch nicht kapiert, ob ich die Speicheradresse von> "Variable" dierekt zuordne, oder vergibt der Compiler die> Speicheradresse für Variable,
das macht der Assembler/Compiler.
> Compiler dann einen Schutz, dass er nicht zweimal die gleiche> Speicherstelle einer Variablen zuordnet?
Du musst zwischen 2 Dingen trennen.
Wenn du Assembler programmierst, dann fordert du mit
PWMCount .db
1 Byte an. Punkt. Damit ist für dich die Sache erledigt. Der Assembler
liest dein Programm in einem Rutsch und teilt deinen
Speicheranforderungen Speicheradressen zu.
Wenn wir von einem Compiler reden, dann reden wir von einer Hochsprache,
wie zb C.
Der C Compiler übersetzt das Programm und filtert ebenfalls alle
Speicheranforderungen (im globalen Speicher) raus. Er erzeugt ein sog.
Object-File, welches im Grunde schon Machinencode, garniert mit
Zusatzinfo (zb. welche Speicheranforderungen existieren).
Nach dem Compiler kommt der Linker zum Zug. Seine Aufgabe ist es,
mehrere Object-Files zu einem Komplettprogramm zusammenzubauen. Dazu
sieht er sich wieder die Speicheranforderungen in den einzelnen
Object-Files an und weist ihnen Speicher zu.
Hi
>Register fängt z.B. an bei 00:00:00 und hört bei 00:00:1E auf. Da 1E_hex>= 31_decimal ist, sind das die einzelnen Register.
$1F = 31
>Ich komme damit nicht klar, warum manche Speicherstellen immer wieder>bei 00:00:00 anfangen, es müsste doch eigentlich einmal bei 00:00:00>beginnen, zB. Programm oder so und geht bis zu seinem MaxWert und danach>müsste dann z.B. Data kommen, Data fängt ja z.B. hier auch erst bei>00:00:60 an und nicht bereits ab 00:00:00?
Das sind bei AVRs psysikalisch getrennte Speicher. Also können die auch
alle mit Null anfangen. Aus diesem Grund gibt es auch verschiedene
Befehle um auf RAM, Flash oder EEPROM zuzugreifen.
>Und wenn ich drei HexPaare habe, dann habe ich ja 16^6-1>Adressierungsmöglichkeiten bzw. 2^24-1 Speicherstellen, brauch ich denn>überhaupt so viel Adressraum für 1kB Speicher?
Bei mir (AVR-Studio 4.19) gibt es keine Doppelpunkte bei den Adressen.
Ansonsten ist die sechsstellige Adresse nur eine Darstellungsfrage.
>Ich habe jetzt noch nicht kapiert, ob ich die Speicheradresse von>"Variable" dierekt zuordne, oder vergibt der Compiler die>Speicheradresse für Variable, ohne dass ich es weis?
Die Speicherstellen werden vom Assembler in der Reihenfolge vergeben in
der du die sie definierst.
>Wenn ja, hat der>Compiler dann einen Schutz, dass er nicht zweimal die gleiche>Speicherstelle einer Variablen zuordnet?
Ja.
MfG Spess
PC-Anfaenger schrieb:> Könnte ich also sagen, dass IO_View und Register auch im SRAM sind, Data> aber erst ab ..:60 beginnt, weil davor IO_View und Register kommen und> Register und IO-View können sich auch so oft verändern, so dass die auch> nicht in das EEPROM (ESEG) bzw. in das CSEG dürfen, wegen der begrenzten> Schreibzyklen???
Der eigentliche Grund ist ein anderer, aber ja: so kann man das sagen.
Man kann jedes Register wie eine SRAM Zelle ansehen und mit genau den
gleichen Methoden darauf zugreifen.
Für dein Programm sieht es so aus, als ob im Speicher ganz vorne bei den
kleinen Adressen erst mal alle Register im Speicher liegen. Und erst
danach kommt der Speicherteil, in dem du gefahrlos Werte ablegen kannst.
Physikalisch ist das im µC zwar anders realisiert, aber das bedeutet ja
nicht, dass sich das für dein Programm auch anders darstellen muss.
Vielen Dank fuer Eure vielen Erklärungen, jetzt hab ich schon eine ganze
Menge gelernt heute.
spess53 schrieb:> Die Speicherstellen werden vom Assembler in der Reihenfolge vergeben in> der du die sie definierst.
gut,
also wird in dem Beispiel in dem Tutorial zu erst im .dseg
PWMCount .BYTE 1 definiert mit einem Bype länge,
dann OCR_1
dann OCR_2
... auch jeweils mit einem Byte länge, und da der Speicher Data bei :60
anfängt, hat also PWMCount die Speicheradresse $0060, OCR_1 $0061, OCR_2
$0062
und wenn dort stünde:
PWM_Count .BYTE 5,
dann hätte PWM_Count immer noch die Adresse $0060, aber OCR_1 dann die
Adresse $0065(also fünf bit weiter)??
spess53 schrieb:> Bei mir (AVR-Studio 4.19) gibt es keine Doppelpunkte bei den Adressen.> Ansonsten ist die sechsstellige Adresse nur eine Darstellungsfrage.
bei mir auch, aber mit den Doppelpunkten fand ich es schreibtechnisch
etwas übersichtlicher.
Mal noch ne Frage, angenommen, ich würde mir ne Variable mit 3Byte
definieren:
.dseg
Vaiable1 .BYTE 3
dass müsste doch zu Fehlern führen, oder?
Und wenn ich schreiben würde
Variable1 .BYTE 2
und würde die dann verwenden wollen, z.B. in das 16bit-Paar XL/XH bzw.
r26,r27 zuordnen wollen, dann müsste ich wieder schreiben:
ldi XH, HIGH(Variable1)
ldi XL, LOW(Variable1)
??
PC-Anfaenger schrieb:> also wird in dem Beispiel in dem Tutorial zu erst im .dseg>> PWMCount .BYTE 1 definiert mit einem Bype länge,> dann OCR_1> dann OCR_2>> ... auch jeweils mit einem Byte länge, und da der Speicher Data bei :60> anfängt, hat also PWMCount die Speicheradresse $0060, OCR_1 $0061, OCR_2> $0062
Fast.
Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf
einer gerade Adresse. Also rundet der Assembler selbstständig auf.
Aber abgesehen davon stimmt es.
> bei mir auch, aber mit den Doppelpunkten fand ich es schreibtechnisch> etwas übersichtlicher.
Das ist keine so gute Idee.
Wir können nicht in deinen Kopf schauen und auch nicht dir über die
Schulter schauen. Schreib die Dinge so, wie du sie am Bildschirm liest.
Dann kann ich bei mir auf dne Bildschirm schauen, suchen wo bei mir die
exakt gleiche Angabe am Bildschirm steht und weiß (hoffentlich) wo du
hingeschaut hast beim Ablesen.
PC-Anfaenger schrieb:> .dseg>> Vaiable1 .BYTE 3>> dass müsste doch zu Fehlern führen, oder?
Warum sollte es?
> Und wenn ich schreiben würde>> Variable1 .BYTE 2>> und würde die dann verwenden wollen, z.B. in das 16bit-Paar XL/XH bzw.> r26,r27 zuordnen wollen, dann müsste ich wieder schreiben:>> ldi XH, HIGH(Variable1)> ldi XL, LOW(Variable1)
Das macht etwas anderes. Das lädt die Adresse, also wo Variable1
gespeichert ist. Wenn du den Inhalt der Variable1 willst, musst du
andere Befehle verwenden.
Beides kann sinnvoll sein. Es kann sinnvoll sein, die Adresse einer
Variablen zu laden, es kann aber auch sinnvoll sein, ihren Inhalt zu
laden.
Du musst unterscheiden zwischen der Nummer, die aussen auf einem
Briefkasten draufsteht (zb in einer Wohnsiedlung) und der Zahl, die auf
ein Zettel steht, die im Briefkasten drinn liegt. Beides ist nicht
dasselbe.
Das eine ist seine Adresse (die steht draussen drauf, damit der
Briefträger weiß in welchen er einwerfen muss), das andere ist der
Inhalt (zb die Steuernachzahlung in Euro).
Es kann jetzt sinnvoll sein, mit den Adressnummern der Briefkästen zu
rechnen. Es kann aber auch sinnvoll sein, mit dem Inhalt eines
bestimmten Briefkastens zu rechnen. Es kann auch sinnvoll sein, zuerst
mit der Adressnummer der Briefkästen zu rechnen und dann mit der Zahl
die man daraus erhält sich den Inhalt dieses errechneten Briefkastens
anzusehen.
Hi
>Fast.>Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf>einer gerade Adresse. Also rundet der Assembler selbstständig auf.
Beim Flash, ja. Im Ram wird (vom Assembler) nichts auf geradzahlige
Adressen gebracht.
>.dseg>Vaiable1 .BYTE 3>dass müsste doch zu Fehlern führen, oder?>Und wenn ich schreiben würde>Variable1 .BYTE 2>und würde die dann verwenden wollen, z.B. in das 16bit-Paar XL/XH bzw.>r26,r27 zuordnen wollen, dann müsste ich wieder schreiben:>ldi XH, HIGH(Variable1)>ldi XL, LOW(Variable1)
Dann hast du die Adresse in X. Du willst aber den Inhalt haben:
spess53 schrieb:> Hi>>>Fast.>>Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf>>einer gerade Adresse. Also rundet der Assembler selbstständig auf.>> Beim Flash, ja. Im Ram wird (vom Assembler) nichts auf geradzahlige> Adressen gebracht.
Danke für die Korrektur.
Da war ich jetzt verwirrt :-)
Karl Heinz Buchegger schrieb:> Es kann jetzt sinnvoll sein, mit den Adressnummern der Briefkästen zu> rechnen. Es kann aber auch sinnvoll sein, mit dem Inhalt eines> bestimmten Briefkastens zu rechnen. Es kann auch sinnvoll sein, zuerst> mit der Adressnummer der Briefkästen zu rechnen und dann mit der Zahl> die man daraus erhält sich den Inhalt dieses errechneten Briefkastens> anzusehen.
Also wie diese Pointer bei C? Weil das ist ja dann das gleiche, wenn ich
den Inhalt einer Variablen haben wollte, dann musste ich glaub ich immer
ein kaufmännisches & davorsetzen.
spess53 schrieb:> Dann hast du die Adresse in X. Du willst aber den Inhalt haben:> lds XL,Variable1> lds XH,Variable1+1
Das low/high würde hier nicht funktionieren?
lds XL, LOW(Variable) wenn ich Variable zuvor mit dseg als
2Byte-Variable gekennzeichnet habe? Oder ist die Variable auch nur 1Bit
groß, ich habe aber dem Compiler durch .Byte 3 gesagt, dass er dahinter
noch zwei zusätliche Bytes freihalten soll?
Karl Heinz Buchegger schrieb:> PC-Anfaenger schrieb:>>> .dseg>>>> Vaiable1 .BYTE 3>>>> dass müsste doch zu Fehlern führen, oder?>> Warum sollte es?
Darum hab ich auch gefragt, ob Variable1, wenn sie als 3Byte-Variable
deklariert ist, nicht mit einem 16Bit-Befehl funktioniert, weil ich doch
mit dem Befehl adiw ja auch eine 16-Bit-Zahl verändere, dann dürfte das
ja bei einer 3Byte-Zahl ja nicht klappen und es müsste ein Fehler
kommen. Wenn ich aber nun einfach sage, die Variable1 ist auch wenn
.BYTE 3dahinter steht, vom Wert her auch nur 1 Byte groß, es werden aber
zwei Byte dahinter Platz gelassen und ich muss dann dahinter so drauf
zugreifen:
spess53 schrieb:> Dann hast du die Adresse in X. Du willst aber den Inhalt haben:> lds XL,Variable1> lds XH,Variable1+1
Und so müsste ich ja dann ohne Probleme auch eine 24-Bit-Zahl verwenden
können, wenn ich einfach schreibe
.dseg
Variable_24bit .BYTE 3
Und dann könnte ich mir theoretisch selber drei Variablen benennen
z.B.
WL = r20 WL = W_low
WM = r21 WM = W_middle
WH = r22 WH = W_high
Und dann könnte ich mir die Variable dann so zum Bearbeiten laden:
lds WL, Variable_24bit
lds WM, Variable_24bit+1
lds WH, Variable_24bit+2
Karl Heinz Buchegger schrieb:> Fast.> Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf> einer gerade Adresse. Also rundet der Assembler selbstständig auf.
Dazu hab ich mir überlegt - dass würde ja bedeuten, angenommen, mein
Adressraum ginge von 0 bis F, dann hab ich 16 Adressen. Soll eine
Varible immer 16Bit haben, dann kann ich max. 8 Varialben benennen. Will
ich aber nur 8bit-Variablen haben, dann kann ich auch maximal 8
Variablen benennen, weil der uC nun immer auf gerade Adresse aufrundet?
Naja, es wird schon seinen Grund haben, warum das so ist.
PC-Anfaenger schrieb:> spess53 schrieb:>> Dann hast du die Adresse in X. Du willst aber den Inhalt haben:>> lds XL,Variable1>> lds XH,Variable1+1>> Das low/high würde hier nicht funktionieren?
Du musst dir klar machen, was der Befehl LDS überhaupt tut.
Im Beispiel von oben: LDS ist die Anweisung:
Geh zum Briefkasten 'Variable1' (das ist irgendeine Zahl) und schreib
den Inhalt des Zettels ab und übertrage ihn in dein Notizbuch unter 'XH'
(was gleichbedeutend mit R27 ist)
Sowohl auf dem Zettel, als auch unter XL, können Werte von 0 bis 255
(nämlich genau das, was mit einem Byte möglich ist) abgelegt werden.
Kein Mensch braucht da ein Low oder ein High
LDI R17, Low( Variable )
macht aber ganz was anderes.
Das sagt, wieder am Beispiel:
Nimm die Nummer vom Briefkasten und schreibe diese Nummer in dein
Notizbuch unter dem Stichwort R17.
Jetzt kannst du aber tausend Briefkästen haben. Die Nummer des
Briefkastens passt nicht mehr in 1 Byte. Wenn du also die NUmmer des
Kastens in R17 laden willst, dann hast du ein Problem: sie passt nicht
hinein. Also musst du dich entscheiden welchen Teil der Nummer du haben
willst.
> lds XL, LOW(Variable) wenn ich Variable zuvor mit dseg als> 2Byte-Variable gekennzeichnet habe?
...
> Darum hab ich auch gefragt, ob Variable1, wenn sie als 3Byte-Variable> deklariert ist,
Ich glaube, du machst dir da vom Begriff 'Variable' eine etwas falsche
Vorstellung ....
> nicht mit einem 16Bit-Befehl funktioniert, weil ich doch> mit dem Befehl adiw ja auch eine 16-Bit-Zahl verändere, dann dürfte das> ja bei einer 3Byte-Zahl ja nicht klappen und es müsste ein Fehler> kommen.
... denn für den Assembler gibt es keine Variablen. Für den existeren
nur Speicherzellen, die eine Adresse haben und in jeder Speicherzelle
wird ein Byte gespeichert welches gelesen und geschrieben werden kann.
Was du mit diesem Speicher machst, mit welchen Befehlen du welches Byte
angreifst, das ist ganz alleine dein Bier. Das interessiert weder den
Assembler noch den µC. Die führen nur uneingeschränkt deine Befehle aus.
Wenn du dir 50 Bytes in Folge reservierst, aber immer nur das 5.te davon
benutzt um dort Werte zu speichern oder zu lesen, dann ist denen das
auch recht. Da kommt die Anweisung: Schreibe den Inhalt von R18 in die
Speicherzelle mit der Adresse 52 und genau das macht der µC dann auch.
Ob das das erste Byte oder das zweite oder das 5.te Byte von
Variable .BYTE 10
ist, interessiert ausser dem Programmierer keinen und kein Mechanismus
schützt dich davor, da einen Fehler zu machen.
'Variablen' gibt es nur in Hochsprachen. Wir verwenden den Begriff
manchmal im Assembler um anzudeuten, dass es sich um Speicher handelt,
der vom Programm verändert werden kann, aber all das was in einer
Hochsprache dann noch am Begriff 'Variable' hängt, existiert im
Assembler schlicht und ergreifend nicht, bzw. liegt in der Hand des
Programmierers.
PC-Anfaenger schrieb:> Karl Heinz Buchegger schrieb:>> Fast.>> Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf>> einer gerade Adresse. Also rundet der Assembler selbstständig auf.>> Dazu hab ich mir überlegt - dass würde ja bedeuten, angenommen, mein> Adressraum ginge von 0 bis F, dann hab ich 16 Adressen. Soll eine> Varible immer 16Bit haben, dann kann ich max. 8 Varialben benennen. Will> ich aber nur 8bit-Variablen haben, dann kann ich auch maximal 8> Variablen benennen, weil der uC nun immer auf gerade Adresse aufrundet?> Naja, es wird schon seinen Grund haben, warum das so ist.
Vergiss das. Das war ein Fehler von mir.
Du findet nichts statt.
Hi
>Das low/high würde hier nicht funktionieren?
Nein. Variable1 bezeichnet eine Adresse, auf der sich ein Byte befindet,
nicht was dort abgelegt ist. Wenn beispielsweise Variable auf die
Adresse $0123 zeigt ergäbe der Ausdruck LOW(Variable) den Wert $23 und
High(Variable) den Wert $01. Und das wären dann die Adressen von denen
du mit lds liest:
lds XL, $0023
lds XH, $0001
>Darum hab ich auch gefragt, ob Variable1, wenn sie als 3Byte-Variable
deklariert ist, nicht mit einem 16Bit-Befehl funktioniert,....
16-Bit-Befehle können bei AVRs nur auf Register zugreifen, nicht auf den
Speicher. Wenn du also z.B. zu einem 24-Bit Wert etwas addieren willst
muss er erst aus dem Speicher gelesen werden.
>Und so müsste ich ja dann ohne Probleme auch eine 24-Bit-Zahl verwenden>können, wenn ich einfach schreibe....
Bevor du anfängst mit 16-, 24-, ..Bit Werten zu hantieren solltest du
dich erst mal mit dem Handwerkszeug, sprich Befehlssatz,
Adressierungsarten, Wirkung der Befehle auf die Flags,
Assembler-Direktiven, Assembler-Expressions, Assembler-Funktionen usw.
vertraut machen.
>Karl Heinz Buchegger schrieb:>> Fast.>> Speicher Allokierungen sind beim AVR aus technischen Gründen immer auf>> einer gerade Adresse. Also rundet der Assembler selbstständig auf.
Im RAM nicht. Siehe:
Beitrag "Re: Frage zu RAMEND"
Und der Flash ist Word-Organisiert (16 Bit). Dort abgelegte Bytes
beginnen an (durch die Byte-Brille gesehen) an einer geraden Adresse.
Liegen aber dann ohne Abstand hintereinander (2 Byte pro Word).
MfG Spess
Ich hab nochmal kurz eine generelle Frage zu in den Speichern abgelegten
Variablen.
Wenn ich eine Veränderung vornehmen möchte, z.B. eine Zahl zu einer im
SRAM gespeicherten "Variable" (ich schreib das jetzt einfach, auch wenn
ich nun gelernt hab, dass Variable nicht der richtige Begriff ist)
dazuaddieren möchte - dann geht dies nicht dierekt, sondern ich muss
erst den Inhalt der Speicherstelle in einen Register holen, die
Veränderung im Register machen und dann den Wert vom Register an die
Speicherstelle kopieren -hab ich das so richtig verstanden? Und wenn das
beim SRAM so ist, dann müsste das später beim EEPROM auch so sein - nur
halt mit anderen Befehlen, die EEPROM-spezifisch sind und nicht
SRAM-spezifisch?
In diesem Beitrag von etwas weiter oben hast Du mir den Link gegeben:
spess53 schrieb:> Im RAM nicht. Siehe:> Beitrag "Re: Frage zu RAMEND"
Dieser Link zeigt nicht nur auf die Seite, sondern auch noch auf die
Zeile, so dass man nicht danach suchen muss. Mich würde mal
interessieren, wie Du das gemacht hast. Das könnte auch praktisch sein,
wenn man z.B. aus dem AVR-Tutorial aus einem Kapitel auf eine einzelne
Stelle am Ende verweisen möchte. Wenn ich so einfach nur den Link
kopiere, der oben in der Adress-Zeile des Browsers steht, komme ich
immer nur auf den Seitenanfang und der Leser müsste dann z.B. weit
scrollen, bis der zu der gewünschten Stelle kommt.
Hi
Einfach mit dem Cursor auf den Titel in der orangenen Titelzeile des
Beitrags gehen, Rechtsclick und im Menu 'Linkadresse kopieren'
auswählen. Dann mit Einfügen in deien Beitrag kopieren.
MfG Spess