Forum: Mikrocontroller und Digitale Elektronik Wie lege ich die Startadresse einer Tabelle fest?


von Maxim (Gast)


Lesenswert?

Es sollen 64 Zahlen in einer Tabelle abgelegt werden. Da sie über 255 
gehen, werden zwei Byte benötigt.

Deshalb muss ich beim Auslesen eines gewünschten Wertes, der sich in der 
Tabelle in der Spalte n befindet, immer zum Z-Pointer 2n addieren. Es 
wäre also nützlich, wenn das Low-Byte des Z-Pointers beim Addieren nicht 
überlaufen würde. Ansonsten müsste ich es ja beachten.

Wenn ich die Tabelle nun so ablege, dass das Low-Byte der Adresse 0 ist, 
kann ich mir sicher sein, dass kein Überlauf stattfindet.

Naja, die Frage steht eigentlich schon in der Überschrift. ;)

Nutze AVR Studio + Assembler

Noch eine Frage: Warum multipliziert man hier die Adresse "daten" mit 
zwei?
ldi ZL, LOW(daten*2)
ldi ZH, HIGH(daten*2)

von Otto (Gast)


Lesenswert?

Hallo Maxim,

1. indem Du den ".org" Befehl verwendest

2. eigentlich ist die Lage der Adresse "wurscht", solange der Zugriff 
über z.B.:

"LD  temp,Z+" erfolgt.

3. Das ist einfach so.....


Gruss Otto

von Maxim (Gast)


Lesenswert?

Hi und Danke.

Bevor ich den Wert aus der Tabelle holle, muss ich ja zuerst das Offset 
(also die Zeilennummer der Tabelle) zum Z addieren.

von Otto (Gast)


Lesenswert?

dafür gäbe es "adiw" (o.ä.)

Gruss Otto

von Karl H. (kbuchegg)


Lesenswert?

Maxim wrote:
>
> Noch eine Frage: Warum multipliziert man hier die Adresse "daten" mit
> zwei?
> ldi ZL, LOW(daten*2)
> ldi ZH, HIGH(daten*2)

Weil der Flash wortadressiert ist und nicht Byteadressiert.
Als Konsequenz daraus rechnet der Assembler in Wörtern und
gibt der eine Adresse als Wortadresse. Du willst hier aber
eine Byteadresse haben, daher *2

von Maxim (Gast)


Lesenswert?

Komisch, wenn ich das hier assembliere:

.ORG 0x0010
.DB 0b10101010

erscheint das Byte an der Adresse 0x0020. Allgemein erscheint das Byte 
im ROM doppelt so weit im Speicher als ich es mit dem .ORG-Befehl 
angebe.

von Maxim (Gast)


Lesenswert?

@Karl heinz Buchegger: Das erklärt natürlich alles. Danke.

@Otto: Der Befehl ADIW funktioniert mit Z nicht:

ADIW Z, R1

oder auch

ADIW ZL, R1

geht nicht.

von Spess53 (Gast)


Lesenswert?

Hi

Der Speicher ist Word-weise organisiert. $10 Word = $20 Byte. Aus diesem 
Grund auch die Multiplikation mit 2. Oder für dich besser: erst den 
Offset addieren und dann
      lsl ZL
      rol ZH
Entspricht einer 16 Bit Multiplikation mit 2.

Abgesehen davon. Du kannst die Tabelle mit einem Label versehen. Dann 
ist es egal wo die Tabelle ist. Zugriff mit:

      ldi ZL,Low(Tabelle)
      ldi ZH,High(Tabelle)

MfG Spess

von Otto (Gast)


Lesenswert?

naja "R1" ist nicht herade eine Konstante.....

Gruss Otto

von Hannes L. (hannes)


Lesenswert?

Hier als Beispiel ein Ausschnitt aus einem Programm für Tiny15:
1
 ldi zl,low(2*sounds)       ;Z-Pointer auf
2
 ldi zh,high(2*sounds)      ;Adressliste
3
 mov wl,num                 ;Soundnummer kopieren
4
 lsl wl                     ;und mal 2
5
 add zl,wl                  ;doppelte Soundnummer
6
 adc zh,null                ;mit Übertrag addieren
7
 lpm                        ;L-Byte Soundadresse holen
8
 mov r1,r0                  ;und sichern
9
 add zl,eins                ;Z-Pointer (L-Byte) auf Flash erhöhen
10
 adc zh,null                ;mit evtl. Übertrag im Carry
11
 lpm                        ;H-Byte holen
Die "Klimmzüge" mit LPM und Z-Pointer-Erhöhung sind aufgrund des 
eingeschränkten Befehlssatzes (gegenüber Mega16) erforderlich.

Zum Adresse * 2 sei noch angemerkt, dass das nur dann der Fall ist, wenn 
der Z-Pointer für den Befehl LPM vorbereitet wird. Siehe auch Hilfe zum 
Befehl LPM. Es gibt auch andere Befehle, die mit Z-Pointer arbeiten, die 
Befehlsreferenz ist Dein Freund.

Tip: Solltest Du Hilfe zu einem ASM-Befehl benötigen, dann setze mal den 
Cursor des Editors in AVR-Studio auf den entsprechenden Befehl und schau 
mal, was passiert, wenn Du dann die F1-Taste betätigst.

...

von Maxim (Gast)


Lesenswert?

Irgendwie funktioniert mein Programm nicht richtig.

Es sollen die Daten aus der Tabelle ausgelesen und in PortD geschrieben 
werden. Da Ich die Werte mit .DW ablege, müsste ja das High-Byte immer 
255 und das Low-Byte immer 0 sein. Somit sollte am PortD abwechselnd 1 
und 0 anliegen. Das klappt schon beim Debugger nicht.
1
////////////////////////////////////////////////////////////////////////////////////////////////
2
3
START:  LDI R20, 255
4
5
LOOP:  INC R20   //R20 ist ein Zähler
6
    
7
    CPI   R20, 64   //Er soll bis max. 63 Zählen
8
    BREQ  START
9
10
    LDI  ZL, LOW(TABELLE)
11
    LDI  ZH, HIGH(TABELLE)
12
13
    MOV  TEMP, R20
14
    LSL  TEMP         //*2
15
    ADD  ZL, TEMP     //Addiere Offset zum Pointer
16
    LDI TEMP, 0       //mit eventuellem Übertrag
17
    ADC ZH, TEMP
18
19
    LD  TEMP, Z       //Lade Low-Byte aus der Tabelle
20
    OUT  PORTD, TEMP  //und schreibe es nach PortD
21
22
    NOP
23
    NOP
24
    NOP
25
    NOP
26
    NOP
27
28
    LDI  TEMP, 1     //Addiere 1 zum Pointer
29
    ADD  ZL, TEMP    //um an das High-Byte zu kommen
30
    LDI  TEMP, 0
31
    ADC  ZH, TEMP
32
33
    LD  TEMP, Z       //holle das High-Byte
34
    OUT  PORTD, TEMP  //und gib es aus
35
36
    RJMP LOOP
37
38
39
////////////////////////////////////////////////////////////////////////////////////////////////
40
41
TABELLE:  .DW  255
42
      .DW 255
43
      .DW 255
44
      .DW 255
45
      .DW 255
46
      .DW 255
47
      .DW 255
48
      .DW 255
49
      .DW 255
50
      .DW 255
51
      .DW 255
52
      .DW 255
53
      .DW 255
54
      .DW 255
55
      .DW 255
56
      .DW 255
57
      .DW 255
58
      .DW 255
59
      .DW 255
60
      .DW 255
61
      .DW 255
62
      .DW 255
63
      .DW 255
64
      .DW 255
65
      .DW 255
66
      .DW 255
67
      .DW 255
68
      .DW 255
69
      .DW 255
70
      .DW 255
71
      .DW 255
72
      .DW 255
73
      .DW 255
74
      .DW 255
75
      .DW 255
76
      .DW 255
77
      .DW 255
78
      .DW 255
79
      .DW 255
80
      .DW 255
81
      .DW 255
82
      .DW 255
83
      .DW 255
84
      .DW 255
85
      .DW 255
86
      .DW 255
87
      .DW 255
88
      .DW 255
89
      .DW 255
90
      .DW 255
91
      .DW 255
92
      .DW 255
93
      .DW 255
94
      .DW 255
95
      .DW 255
96
      .DW 255
97
      .DW 255
98
      .DW 255
99
      .DW 255
100
      .DW 255
101
      .DW 255
102
      .DW 255
103
      .DW 255
104
      .DW 223

von Karl H. (kbuchegg)


Lesenswert?

Hier

    LDI  ZL, LOW(TABELLE)
    LDI  ZH, HIGH(TABELLE)

musst du die Adresse mal 2 nehmen, weil dir der Assembler
die Adresse von Tabelle als Wortadresse liefert

    LDI  ZL, LOW(2*TABELLE)
    LDI  ZH, HIGH(2*TABELLE)


wohingegen du hier

    MOV  TEMP, R20
    LSL  TEMP         //*2

die Multiplkation mit 2  brauchst oder auch nicht brauchst, je
nachdem, was der Wert in R20 aussagt.

    LD  TEMP, Z       //Lade Low-Byte aus der Tabelle

Schon. Aber dazu muss die Tabelle auch im SRAM liegen. Bei dir
liegt die Tabelle aber im Flash Edit: und daher muss die Adresse
auch mal 2 genommen werden). Daher erfolgt der Ladevorgang
nicht mittels LD TEMP, Z sondern über LPM und das geladene Byte
ist dann im Register R0

ev. solltest du mal die Tutorial Abschnitte

http://www.mikrocontroller.net/articles/AVR-Tutorial:_SRAM
und
http://www.mikrocontroller.net/articles/AVR-Tutorial:_7-Segment-Anzeige

vergleichen. In beiden kommt eine Art von Tabelle vor und beide
zeigen den Unterschied zwischen Auslesen aus SRAM und Auslesen
aus Flash.

von Michael W. (wiebel42)


Lesenswert?

Hannes Lux wrote:
> Die "Klimmzüge" mit LPM und Z-Pointer-Erhöhung sind aufgrund des
> eingeschränkten Befehlssatzes (gegenüber Mega16) erforderlich.
Darf man fragen wie das bei einem Mega16, einfacher geht?
Ich hab das auf einem m169 nämlich genauso gemacht und wäre natürlich 
schwer an Verbesserungsmöglichkeiten interessiert. -wiebel

von Hannes L. (hannes)


Lesenswert?

Michael Waiblinger wrote:
> Hannes Lux wrote:
>> Die "Klimmzüge" mit LPM und Z-Pointer-Erhöhung sind aufgrund des
>> eingeschränkten Befehlssatzes (gegenüber Mega16) erforderlich.
> Darf man fragen wie das bei einem Mega16, einfacher geht?

Man darf... ;-)
1
 ldi zl,low(2*sounds)       ;Z-Pointer auf
2
 ldi zh,high(2*sounds)      ;Adressliste
3
 mov wl,num                 ;Soundnummer kopieren
4
 lsl wl                     ;und mal 2
5
 add zl,wl                  ;doppelte Soundnummer
6
 adc zh,null                ;mit Übertrag addieren
7
 lpm r16,z+                 ;L-Byte nach r16 holen und Pointer erhöhen
8
 lpm r17,z                  ;H-Byte nach r17 holen

Die neueren und größeren AVRs unterstützen bei LPM das Incrementieren 
des Z-Pointers und die Angabe des Zielregisters. Die älteren AVRs 
dagegen kannten nur den Befehl LPM ohne Parameter, das Zielregister war 
immer R0. Auch das ADIW/SBIW gab es bei einigen älteren kleinen AVRs 
nicht. Daher das Addieren von vordefinierten Registern im oberen 
Beispiel, wobei das Vordefinieren von "null" und "eins" den Hauptgrund 
in der Geschwindigkeit hat (kein unnötiges LDI). Das komplette Programm, 
aus dem ich die Zeilen kopierte, kannst Du hier finden:
http://www.hanneslux.de/avr/divers/index.html

@Maxim:
Hast Du eigentlich bei MAXIM nachgefragt, ob Du deren rechtlich 
geschützten Namen als Nick im Forum verwenden darfst? Nicht dass Dich 
der Freiherr noch abmahnt. ;-)

...

von Michael W. (wiebel42)


Lesenswert?

Hannes Lux wrote:
> Die neueren und größeren AVRs unterstützen bei LPM das Incrementieren
> des Z-Pointers und die Angabe des Zielregisters. Die älteren AVRs
> dagegen kannten nur den Befehl LPM ohne Parameter, das Zielregister war
> immer R0.
Alles klar, danke. Man kann aber via LPM nur und aussschliesslich ein 
postincrement machen, also ein predec oder ein offset, richtig?
Das hilft aber schon gewaltig.

>  Das komplette Programm,
> aus dem ich die Zeilen kopierte, kannst Du hier finden:
> http://www.hanneslux.de/avr/divers/index.html
Klasse Seite, danke. Es kann nicht genug doku geben. ;)
Ich hab erst letztens mit einem Tiny45 den Melodiencode von elm-chan 
getestet, das klingt unglaublich gut, aber ich hab den Code noch nicht 
verstanden, und dann zählt's ja nicht. ;) -> 
http://elm-chan.org/works/mxb/report_e.html
Von daher werd ich mir jetzt erstmal deine Seite zu Gemüte führen. 
-wiebel

von Maxim (Gast)


Lesenswert?

Ok, es funktioniert. Aber irgendwie wird der ATMega8 jetzt warm!

von Simon K. (simon) Benutzerseite


Lesenswert?

Du hast sicher keine Wasserkühlung installiert, oder? Daran könnts 
liegen!

von Maxim (Gast)


Lesenswert?

Ne, aber ich habe hier noch zwei 120 Watt Peltier rumliegen. Reichen 
die? Ich meine, so ein 8-Bit-uC verbraucht ja richtig Strom ...

von Matthias L. (Gast)


Lesenswert?

Du musst bei der Erstinitialisierung des Kühlkörperbausteins 
Wasserkühlung einstellen. SOnst wird per default Konvektion angenommen
;-)
1
processor_cooling.init ( c_water );

von Maxim (Gast)


Lesenswert?

Es ist also völlig normal, dass der ATMega warm wird? Das wurde er bei 
mir noch nie und ich habe nirgendwo davon gehört.

von Hannes L. (hannes)


Lesenswert?

Maxim wrote:
> Es ist also völlig normal, dass der ATMega warm wird? Das wurde er bei
> mir noch nie und ich habe nirgendwo davon gehört.

Wärme (in der Elektronik) kommt nicht mal eben so. Meist entsteht durch 
das Verheizen elektrischer Leistung (Strom mal Spannung). Strom und 
Spannung kann man mit einfachen Mitteln (Multimeter) messen. Beim 
Verdacht, ein Bauteil "wird warm", fällt mir als erstes ein, die 
Stromaufnahme (der Versorgungsspannung) zu messen. Das kann erstmal 
bestätigen oder ausschließen, dass sich der Chip elektrisch erwärmt.

Vor über 15 Jahren hatte ich mal einen 8501-Prozessor, den ich für 
übermäßig warm hielt. Nach Trennen sämtlicher Leitungen von dem 
Heimcomputer kühlte sich die CPU immer noch nicht ab. Sie befand sich im 
Brennpunkt einer 2m entfernten Halogenlampe (Auto-Nebelscheinwerfer ohne 
Streuscheibe) und erwärmte sich daher auch ohne direktes Verheizen von 
Strom in der CPU.

Ehe Du nun den Controller aktiv kühlst, solltest Du die Ursache der 
Erwärmung ermitteln. In Frage käme evtl. zu hohe Betriebsspannung, zu 
hohe Last an den Ausgängen, falsche Programmierung (Kurzschluss am 
versehentlich als Ausgang programmierten Eingangspin), Belastung der 
Schutzdioden durch Eingangspegel außerhalb des 
Versorgungsspannungsbereiches usw. Möglichkeiten gibt es da viele, Du 
kannst durch systematische Fehlersuche eine Möglichkeit nach der anderen 
ausschließen.

...

von Peter D. (peda)


Lesenswert?

Hannes Lux wrote:
> Maxim wrote:
>> Es ist also völlig normal, dass der ATMega warm wird?

Nein, da ist definitiv was faul, z.B. kurzgeschlossene IOs, LEDs ohne 
Vorwiderstand usw.


> Vor über 15 Jahren hatte ich mal einen 8501-Prozessor, den ich für
> übermäßig warm hielt.

Hatte ich auch.
Aber das war der alte NMOS-Typ, da ist das normal (~200mA Verbrauch).


Peter

von Michael W. (wiebel42)


Lesenswert?

Hannes Lux wrote:
> Vor über 15 Jahren hatte ich mal einen 8501-Prozessor, den ich für
> übermäßig warm hielt. Nach Trennen sämtlicher Leitungen von dem
> Heimcomputer kühlte sich die CPU immer noch nicht ab. Sie befand sich im
> Brennpunkt einer 2m entfernten Halogenlampe (Auto-Nebelscheinwerfer ohne
> Streuscheibe) und erwärmte sich daher auch ohne direktes Verheizen von
> Strom in der CPU.
Nein, ich frag nicht nach, nein ich frag nicht nach ... ich will das 
bestimmt auch gar nicht wissen .... .... ok, verloren ....
WTF??? Warum? -wiebel

von Maxim (Gast)


Lesenswert?

Habe DDR versehentlich falsch gesetzt. :D

von Simon K. (simon) Benutzerseite


Lesenswert?

Michael Waiblinger wrote:
> Hannes Lux wrote:
>> Vor über 15 Jahren hatte ich mal einen 8501-Prozessor, den ich für
>> übermäßig warm hielt. Nach Trennen sämtlicher Leitungen von dem
>> Heimcomputer kühlte sich die CPU immer noch nicht ab. Sie befand sich im
>> Brennpunkt einer 2m entfernten Halogenlampe (Auto-Nebelscheinwerfer ohne
>> Streuscheibe) und erwärmte sich daher auch ohne direktes Verheizen von
>> Strom in der CPU.
> Nein, ich frag nicht nach, nein ich frag nicht nach ... ich will das
> bestimmt auch gar nicht wissen .... .... ok, verloren ....
> WTF??? Warum? -wiebel

Manche Leute nehmen sowas als Tischbeleuchtung, und? ;)

PS: Ich finde Halogenlampen VIEL VIEL angenehmer von der Lichtfarbe beim 
Arbeiten als normale Glühbirnen.

von Hannes L. (hannes)


Lesenswert?

Simon Küppers wrote:
> Michael Waiblinger wrote:
>> Hannes Lux wrote:
>>> Vor über 15 Jahren hatte ich mal einen 8501-Prozessor, den ich für
>>> übermäßig warm hielt. Nach Trennen sämtlicher Leitungen von dem
>>> Heimcomputer kühlte sich die CPU immer noch nicht ab. Sie befand sich im
>>> Brennpunkt einer 2m entfernten Halogenlampe (Auto-Nebelscheinwerfer ohne
>>> Streuscheibe) und erwärmte sich daher auch ohne direktes Verheizen von
>>> Strom in der CPU.
>> Nein, ich frag nicht nach, nein ich frag nicht nach ... ich will das
>> bestimmt auch gar nicht wissen .... .... ok, verloren ....
>> WTF??? Warum? -wiebel

Hmmm, ääähhh, muss ich das JETZT verstehen?

>
> Manche Leute nehmen sowas als Tischbeleuchtung, und? ;)

Ach sooooo war das gemeint...

Stimmt... - Defektes Glas vom Nebelscheinwerfer entfernt, gefreut, dass 
das Teil so prima bündelt, so an die Zimmerdecke geschraubt, dass es 
direkt auf den Arbeitsplatz strahlt.

>
> PS: Ich finde Halogenlampen VIEL VIEL angenehmer von der Lichtfarbe beim
> Arbeiten als normale Glühbirnen.

HO (Hannes oooch...)


Maxim wrote:
> Habe DDR versehentlich falsch gesetzt. :D

Na prima, dann ist die Ursache ja gefunden. Hoffentlich hat der AVR noch 
keinen Schaden genommen.

...

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.