Forum: Mikrocontroller und Digitale Elektronik Atmega88/48, Anzahl der pop-Zugriffe


von fleissige Honigbiene (Gast)


Lesenswert?

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?

von mschoeldgen (Gast)


Lesenswert?

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

von fleissige Honigbiene (Gast)


Lesenswert?

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 :-(

von Karl H. (kbuchegg)


Lesenswert?

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

von Purzel H. (hacky)


Lesenswert?

Dieses Vorgehen scheint mir extrem unangebracht zu sein...

von mschoeldgen (Gast)


Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

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.

...

von oldmax (Gast)


Lesenswert?

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

von mschoeldgen (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.