Hi,
wie oft kann ich einen Register mit pop in den Stack verschieben?
Angenommen, ich habe 50 Messwerte, jeweils 8bit groß - also ein
Register, kann ich die so alle speichern? Wenn ich nun die Messwerte
parallel zum Analysebetrieb übertragen will, dann krieg ich ja immer nur
den aktuellsten Messwert, geht das auch irgendwie, dass ich den
untersten Messwert vom Stapel zuerst uebertrage?
Der Mega48 hat 512 bytes RAM , der Mega88 hat 1024 bytes , vom Platz her
reicht das also dicke. Das Problem ist, nicht den Stack durcheinander zu
bringen, da da ja auch Rücksprungaddressen gespeichert sind, auf jedes
PUSH muss also genau ein POP folgen. Wenn deine Software das beachtet,
spricht nix dagegen , den Stack zu bentzen. Allerdings halte ich es für
einfacher, X und Y register als Zeiger in den RAM zu benutzen, du
könntest z.B. X als Schreibzeiger und Y als Lesezeiger zu benutzen.
D
512 bytes Ram heisst also - ich kann 512mal Register mit pop in den
Speicher legen?
mschoeldgen schrieb:> Allerdings halte ich es für> einfacher, X und Y register als Zeiger in den RAM zu benutzen, du> könntest z.B. X als Schreibzeiger und Y als Lesezeiger zu benutzen.
kannst Du mir vielleicht einen Link / oder so geben, wo cih dazu mehr
lesen kn, in dem avr-Tutorial hab ich dazu nix gefunden :-(
fleissige Honigbiene schrieb:> 512 bytes Ram heisst also - ich kann 512mal Register mit pop in den> Speicher legen?>
Na ja fast. Ein bischen Speicher wirst du ja auch für die Returnadressen
bei Unterprogrammaufrufen brauchen.
> mschoeldgen schrieb:>> Allerdings halte ich es für>> einfacher, X und Y register als Zeiger in den RAM zu benutzen, du>> könntest z.B. X als Schreibzeiger und Y als Lesezeiger zu benutzen.>> kannst Du mir vielleicht einen Link / oder so geben, wo cih dazu mehr> lesen kn, in dem avr-Tutorial hab ich dazu nix gefunden :-(http://www.mikrocontroller.net/articles/AVR-Tutorial:_SRAM
Mikro Oschi schrieb:> Dieses Vorgehen scheint mir extrem unangebracht zu sein...
Welches jetzt ? Die X und Y register sind genau dafür gemacht, mit post
inkrement und pre dekrement und so.
lds r16,X+
sts r16,-Y
ist doch cool :P
Den Stack dafür zu nehmen, halte ich allerdings auch für gewagt, gerade
wegen der Gefahr die Rücksprungadressen zu zermanschen.
fleissige Honigbiene schrieb:> 512 bytes Ram heisst also - ich kann 512mal Register mit pop in den> Speicher legen?
Nööö...
Mit POP holst Du etwas aus em Stack, reinlegen kannst Du es mit Push...
Aber wie Hacky schon schrieb, ist das Unfug. Du solltest Deine Messwerte
in ein Array schreiben, also über die Pointer (x, y oder z) als
Indexregister (wurde auch bereits genannt). Schau mal, was Du zum Thema
"Ringbuffer" findest.
...
Hi
Also, den Stack zur Ablage von Daten zu benutzenist nicht Sinnvoll.
Zumal mit POP etwas vom Stack geholt wird. Mit Push legst du ein
Register ab. Besset ist ein kleiner Ringspeicher. Dafür nimmst du ein
Doppelregister. Da aus deinem Beitrag nicht hervorgeht, welchen µC du
benutzt, nehme ich als Beispiel einen Atmega8. Der hat die oberen 6
Register R26 bis R31 dafür vorgesehen. z.B. R26 und R27 ergeben ein 16
Bit - Register X
Deinen Ringspeicher baust du etwa so auf:
1
Ring_Buffer: .Byte 20 ;z.B. 20 Byte
2
Write_Pos: .Byte 1 ; Schreibzeiger
3
Read_Pos: .Byte 1 ; Lesezeiger
4
Wert: .Byte 1 ; Byte mit Wert
Nun zu einer kleinen Routine, die Daten in den Puffer schreibt
1
Write_Data:
2
LDI XL, Low(Ring_Buffer) ; Anfangsadresse vom Pufferbereich
3
LDI XH, High(Ring_Buffer)
4
LDS Reg_A, Write_Pos ; Wert Schreibzeiger
5
ADD XL, Reg_A ; zur Adresse addieren
6
CLR Reg_B
7
ADC XH, Reg_B ; Überlauf beachten
8
LDS Reg_B, Wert ; Wert holen
9
ST X, Reg_B ; und in Puffer eintragen
10
INC Reg_A ; Schreibzeiger erhöhen
11
CPI Reg_A, 20 ; Grenze prüfen
12
BRLO Store_Write_Pos
13
CLR Reg_A
14
Store_Write_Pos:
15
STS Write_Pos, Reg_A ; und ablegen
16
RET
Wie du un die Daten ausliest, ist letztlich deine Sache, aber in der
Regel sieht die Leseroutine nicht viel anders aus
1
Read_Data:
2
LDS Reg_A, Read_Pos ; Lese und Schreibzeiger vergleichen
3
LDS Reg_B, Write_Pos
4
CP Reg_A, Reg_B
5
BREQ End_Read_Buf ; wenn gleich, dann keine neuen Daten
6
LDI XL, Low(Ring_Buffer) ; Anfangsadresse vom Pufferbereich
7
LDI XH, High(Ring_Buffer)
8
ADD XL, Reg_A ; Lesezeiger zuaddieren
9
CLR Reg_B
10
ADC XH, Reg_B ; Überlauf beachten
11
LD Reg_B, X
12
; Den Wert bearbeiten, versenden oder was auch immer
13
INC Reg_A ;Lesezeiger nachführen
14
CPI Reg_A, 20 ;Grenze prüfen
15
BRLO Store_Read_Pos
16
CLR Reg_A
17
Store_Read_Pos:
18
STS Read_Pos, Reg_A ; und zurückschreiben
19
End_Read_Buf:
20
RET
Diese Routine kannst du z. B. gut bei seriellem Datenempfang anwenden.
Auch die Bedingung First In - First Out(FIFO) ist gegeben.
Gruß oldmax
Du kannst auch direkt die 16-bit Register X,Y und Z inkrementieren:
ADIW X,1 ; addiere 1 zum 16-bit register XH,XL
Spart manchmal ein paar Bytes, musst aber drauf achten, das X nicht über
den RAM hinausgeht. Der Stack liegt am oberen RAM Ende, da also nicht
reinschreiben und ein bisschen Reserve lassen.