Hallo liebes Forum,
wer von euch Profis hilft einem Neuling auf dem Gebiet AVR & ASM?
Folgendes Problem:
STK 500
AVR Studio 4.13
ATMEGA 8515
Ich habe diesen CODE (soll aus einer "db" daten rausholen und diese an
die LEDs weitergeben) und es kommt andauert die Fehlermeldung:
AVR Simulator: Stack Underflow at 0x0015
AVR Simulator: Invalid opcode 0xffff at address 0x00ffff
@ Yatko Jaens (denim)
>AVR Simulator: Stack Underflow at 0x0015>AVR Simulator: Invalid opcode 0xffff at address 0x00ffff
Hast du auch im Simulator den 8515 eingestellt? Das ist eine getrennte
Einstellung vom Projekt!
MFG
Falk
ich weiss.. schäm mich auch... aber komme nicht weiter...
hab da das tut auch durchgelesen, alles aufeinmal verstehen ist auch
echt schwer...
Hatte mir das Buch von Günter Schmitt "Microcomputertechnik mit
Controllern der Atmel AVR-Risc Familie" geholt, aber da blicke ich auch
ncith durch... da geht es wirklich ins eingemachte...
Habe mir hier sämtliche Tipp Tutorials angeschaut und mich an die
Empfehlungen gehalten und entsprechendes Equipment gekauft. Und es wird
ja empfohlen ASM zu programmieren, das ist aber wirklich ncith so
einfach. Ich überlege ob ich nicht lieber direkt mit C anfangen sollte,
da dort solche Probleme wohl nicht passieren können...
Vielen Dank das Du mir helfen möchtest :)
ok, vielen dank! habs hinbekommen, habe statt dem ret ein rjmp auf
lcd_flash_string gemacht. Du hast mir den richtigen Denkanstoss gegeben
:)
Habe aber noch eine andere Frage:
Das scheint ja normal zu sein bei dem STK 500 das die LEDs leuchten bei
LOW. Gibt es da auf dem Brett eine Einstellung das man es umkehrt, also
bei LOW auch die entsprechende LED dunkel bleibt?
>Das scheint ja normal zu sein bei dem STK 500 das die LEDs leuchten bei>LOW.
Ja.
>Gibt es da auf dem Brett eine Einstellung das man es umkehrt, also>bei LOW auch die entsprechende LED dunkel bleibt?
Nein, zum Glück nicht. Denn wenn es die gäbe und man würde sie mal so
und mal so konfigurieren, dann käme man blos noch durcheinanderer.
Man merkt sich einfach
L -> LED an
H -> LED aus
und gut ist.
ok, vielen Dank an alle :)
der code sieht jetzt so aus (ich schäm mich auch)
ich glaube das was da bei lcd_flash_string_2 passiert ist nicth ganz
korrekt oder? wenn ich da ncith drin habe, wird R30 nicht auf 26
zurückgestellt und zählt einfach weiter...
1
lcd_flash_string_2:
2
pop temp
3
4
ldi ZL, LOW(text*2) ; ist das schlimm wenn das hier andauernd wiederholt wird, oder gibt es einen anderen weg?
>wenn ich da ncith drin habe, wird R30 nicht auf 26>zurückgestellt und zählt einfach weiter...
So ist es.
Und passieren wegen dem Aufrufen der Zeilen tut da garantiert nix.
Während Dein Programm läuft und Dein ATmega8515 mit 8 MHz getaktet ist,
wird die Instruktion 'dec r17' in der w0-Routine schließlich auch
ungefähr 2.6 Millionen mal pro Sekunde (klar, wieso so oft?) ausgeführt,
und sie geht nicht kaputt dadurch.
@ Yatko Jaens (denim)
Irgendwie hab ich die Befürchtung, dass du das noch nicht wirklich
verstanden hast.
Hier mal eine Musterlösung.
Und der klare Hinweis.
- rcall ruft Unterprogramme auf. Die müssen IMMEr mit ret abgeschlossen
werden.
- rjmp verzweigt im Programablauf. Damit sollte man sorgsam umgehen, um
keinen Spaghetticode zu produzieren, so wie du im Moment.
- Wer STRINGs als Binärzahlen kodiert hat einen an der Waffel
1
.include "m8515def.inc"
2
.def temp=r16
3
4
ldi temp, LOW(RAMEND)
5
out SPL, temp
6
ldi temp, HIGH(RAMEND)
7
out SPH, temp
8
9
ldi temp, 0xFF ; Port b = Ausgang
10
out DDRB, temp
11
12
ldi ZL, LOW(text*2) ; Adresse des Strings in den
13
ldi ZH, HIGH(text*2) ; Z-Pointer laden
14
15
rcall lcd_flash_string
16
17
main:
18
rjmp main ; Endlosschleife, nix mehr zu tun
19
20
text:
21
.db "Test",0 ; Stringkonstante, durch eine 0
22
; abgeschlossen
23
24
lcd_flash_string:
25
push temp
26
lcd_flash_string_1:
27
lpm temp, Z+
28
cpi temp,0
29
breq lcd_flash_string_2
30
out PORTB,temp
31
rjmp lcd_flash_string_1
32
lcd_flash_string_2:
33
pop temp
34
ret
MfG
Falk
P.S. Wie kann man ein schönes, korrektes Beispiel aus dem tutorial nur
so böse verstümmeln . . . ?
@ AVRFan (Gast)
>Diese beiden Zeilen...> ldi ZL, LOW(text*2)> ldi ZH, HIGH(text*2)>gehören.. .>lcd_flash_string:> push temp> [--> hierhin! <--]>So ist es.
Nööö, das ist schon OK. Z ist ein Parameter.
MFg
Falk
@ AVRFan (Gast)
>gesehen? Z wird dadurch hochgezählt, aber das sollte man nicht>unbegrenzt machen.
Das macht man auch nicht, wenn man prüft, ob das gelesene Zeicghen eine
Null ist. Siehe meine korrigierte Version, oder gleich das Original
hier.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher#Flash-ROM_2
MfG
Falk
Nochmals vielen Dank für eure Ratschläge!
Sieht gut aus. Ich arbeite dann mal eure Texte gleich durch.
>- Wer STRINGs als Binärzahlen kodiert hat einen an der Waffel
Oder langeweile :D -> Binär war aus dem Grunde, weil das Steuerdaten für
die LEDs sein sollten. Da sehe ich besser welche LEDs an bzw aus sein
sollen/sind. Gibt es noch eine andere Möglichkeit Daten in Array zu
schreiben und sie rauszuholen? Das war das einzige was ich gefunden
habe. Eigentlich benötige ich statt der 0 (oder einem FF ) ein Zeichen
was ncith in diesem Bereich liegt, denn ich kann dann diese
Kombinationen der LED gar nciht mehr nutzen.
Später kommt da noch ein Multiplexer hinter, dann muss ich sowieso nicht
so hoch zählen. Aber jetzt kann ich dann z.b. 0x00 oder 0b00000000 nicht
nutzen, weil das natürlich mit cpi temp,0 matched.
>Das macht man auch nicht, wenn man prüft, ob das gelesene Zeicghen eine>Null ist.
OK, aber wenn man die Z-Ladezeilen (ldi ZL... ZH...) in der
Initialisierung ganz oben lässt, ist man auf einen einmaligen Aufruf
von 'lcd_flash_string' beschränkt (ab dem zweiten Mal kommt Nonsens
raus). Das halte ich für keinen guten Programmierstil.
Meine Idee:
@ AVRFan (Gast)
>OK, aber wenn man die Z-Ladezeilen (ldi ZL... ZH...) in der>Initialisierung ganz oben lässt, ist man auf einen einmaligen Aufruf>von 'lcd_flash_string' beschränkt (ab dem zweiten Mal kommt Nonsens>raus). Das halte ich für keinen guten Programmierstil.
Was ist beschränkt? Das ist ein einfaches grundgerüst, das sehr einfach
und SICHER erweitert werden kann.
Und du musst wohl auch noch mal nde Unterschied zwischen rcall und rjmp
durcharbeiten . . .
>lcd_out_text1:> ldi ZL, low(2*text1)> ldi ZH, low(2*text1)> rjmp lcd_flash_string
@ Yatko Jaens (denim)
>Oder langeweile :D -> Binär war aus dem Grunde, weil das Steuerdaten für>die LEDs sein sollten. Da sehe ich besser welche LEDs an bzw aus sein
Ok, das ist was anderes.
>sollen/sind. Gibt es noch eine andere Möglichkeit Daten in Array zu>schreiben und sie rauszuholen? Das war das einzige was ich gefunden
Warum? Ist die nicht gut genug?
>habe. Eigentlich benötige ich statt der 0 (oder einem FF ) ein Zeichen>was ncith in diesem Bereich liegt,
???
Welchen Bereich zwischen 0x00..0xFF willst sonst in einem BYTE nutzen?
>so hoch zählen. Aber jetzt kann ich dann z.b. 0x00 oder 0b00000000 nicht>nutzen, weil das natürlich mit cpi temp,0 matched.
Dann nimm eine andere Zeichen. Idealerweise wird das als Konstante
definiert, das ist übersichtlich und einfach anzupassen.
1
.equ data_end = 0xC5
2
3
....
4
5
.db 1,2,3,4,5,data_end
6
7
. . .
8
9
cpi temp, data_end
Das gleiche kann man auch mit diversen LED-Zuständen machen, dann ist
der Datensatz besser lesbar.
Mfg
Falk
>>sollen/sind. Gibt es noch eine andere Möglichkeit Daten in Array zu>>schreiben und sie rauszuholen? Das war das einzige was ich gefunden>> Warum? Ist die nicht gut genug?
ok, dann scheine ich da auf dem richtigen weg zu sein
>>habe. Eigentlich benötige ich statt der 0 (oder einem FF ) ein Zeichen>>was ncith in diesem Bereich liegt,>> ???> Welchen Bereich zwischen 0x00..0xFF willst sonst in einem BYTE nutzen?
ich dachte ehr an sowas hier:
>Das ist ein einfaches grundgerüst, das sehr einfach>und SICHER erweitert werden kann.
Na klar, ich hab ja ein Beispiel dafür gegeben.
>Und du musst wohl auch noch mal nde Unterschied zwischen rcall und rjmp
? (Alle "lcd_out_text..."-Routinen werden natürlich mit 'rcall'
aufgerufen)
@ AVRFan (Gast)
>? (Alle "lcd_out_text..."-Routinen werden natürlich mit 'rcall'>aufgerufen)
Und was soll das? Das bringt nur Kuddelmuddel und zusätzlichen
Programmcode. Was spricht gegen die zwei ldi für den Z-Pointer gefolgt
von dem rcall? Und das immer direkt, wenn irgendwo Text/Daten ausgegeben
werden sollen.
@ Yatko Jaens (denim)
>ich dachte ehr an sowas hier:>.db 1,2,3,4,5,"ENDE"
Schau dir mal mein letztes Posting an . . .
MfG
Falk
@ Falk Brunner
>>.db 1,2,3,4,5,"ENDE">Schau dir mal mein letztes Posting an . . .
ja, aber dann kann ich kombination der LEDs 0xc5 nicht nutzen
(0b11000101) weil das ja dann der stopper ist. mir würde ja ein
buchstabe reichen aber die werden ja wohl automatisch umgerechnet. Also
heisst das jetzt in klartext: man kann nur aus dem bereich 0x00 - 0xff
ein "stopper" wählen, richtig (byte)?
@ Yatko Jaens (denim)
>heisst das jetzt in klartext: man kann nur aus dem bereich 0x00 - 0xff>ein "stopper" wählen, richtig (byte)?
Ja. Wenn das nicht reicht weil du alle 8 Bit im Byte für deine LEDs
nutzen willst, kannst du
a) die einzelnen Werte mit 16 Bit kodieren, .dw 1234; dann hast du genug
Kodes
b) die Anzahl der Daten an die erste Stelle des Datenblocks schreiben
MfG
Falk
@ Falk
Danke:)
Ich wähle A, denn B kommt nicht in Frage, weil sich der Inhalt ändert
(zur Zeit zwar nicht, aber später). Es sei denn es gibt sowas wie
dw.length (wie bei JS oder PHP)
Zu A: wenn ich angenommen das Ganze mit .dw machen würde und mein
stopper 0x100 sein würde, kommt bei -> "cpi temp, 0x100" out of range
weil der wahrscheinlich nur 8 bit kann. Wie könnte man denn dann ein
16bit Wert prüfen?
Sorry, bin wirklich totaler anfänger... komme aus der PHP / JS Welt..
Schöne Grüße aus Dortmund!
Oktay
>Was spricht gegen die zwei ldi für den Z-Pointer gefolgt>von dem rcall?
Man kann die ldi-ldi-rjmp-Dreierpakete schön zusammen mit den .DB- oder
.DW-Zeilen in eine "Daten"-Includedatei auslagern und danach
"vergessen". Im Programmcode kommt man dann mit einer einzigen Zeile für
den Aufruf aus. Ich nutze grundsätzlich immer (auch die kleinste)
Möglichkeit aus, die einen Code einfacher zu überblicken und/oder
leichter verstehbar macht.
@ AVRFan (Gast)
>>Gibt es da auf dem Brett eine Einstellung das man es umkehrt, also>>bei LOW auch die entsprechende LED dunkel bleibt?>>Nein, zum Glück nicht.
also, ich hab das mit dem invertieren LEDs dann so gelöst:
@ Yatko Jaens (denim)
>Ich wähle A, denn B kommt nicht in Frage, weil sich der Inhalt ändert>(zur Zeit zwar nicht, aber später). Es sei denn es gibt sowas wie>dw.length (wie bei JS oder PHP)
Aber sicher.
1
daten_anfang:
2
.db (daten_ende-daten_anfang)*2, 1,2,3,4,5,6,7
3
daten_ende:
>weil der wahrscheinlich nur 8 bit kann. Wie könnte man denn dann ein>16bit Wert prüfen?AVR-Tutorial: Arithmetik
MfG
Falk