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)
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
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.
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
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.
@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.
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
naja "R1" ist nicht herade eine Konstante..... Gruss Otto
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. ...
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 |
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.
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
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. ;-) ...
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
Ok, es funktioniert. Aber irgendwie wird der ATMega8 jetzt warm!
Du hast sicher keine Wasserkühlung installiert, oder? Daran könnts liegen!
Ne, aber ich habe hier noch zwei 120 Watt Peltier rumliegen. Reichen die? Ich meine, so ein 8-Bit-uC verbraucht ja richtig Strom ...
Du musst bei der Erstinitialisierung des Kühlkörperbausteins Wasserkühlung einstellen. SOnst wird per default Konvektion angenommen ;-)
1 | processor_cooling.init ( c_water ); |
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.
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. ...
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
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.