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.
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.