Forum: Mikrocontroller und Digitale Elektronik Ringspeicher in Assembler


von moin (Gast)


Lesenswert?

Hallo
Wie baut man am besten mit einem ATMEGA8 in Assembler einen
Ringspeicher auf, so dass aus je 16 Messwerten (24bit) ein Mittelwert
berechnet und dann ausgeben/gespeichert wird. Es soll bei jedem
Durchlauf ein neuer Messwert hinzukommen und ein alter herausfallen.

Vielen Dank für Vorschläge
Moin

von thkais (Gast)


Lesenswert?

Ich würde es mit einem umlaufenden Pointer machen, dann muß man keine
Speicherinhalte verschieben.

von Jens123 (Gast)


Lesenswert?

Wo ist das Problem???

im Ram die Register definieren und ueber einen Pointer laufen lassen..

Wert schreiben, Pointer ein hoch
Wert schreiben, Pointer ein hoch
Wert schreiben, Pointer ein hoch
Wert schreiben, Pointer ein hoch
...
..
Wert schreiben, Pointer ein hoch
Wenn Pointer = X + 16 Dann Pointer = X + 0

sollte doch nciht so schwer sein ;)

von ...HanneS... (Gast)


Lesenswert?

Geht auch Mittelwert über 256 Messungen?
Dann wirds billiger und braucht nur 2 (und 1 temp.) Register...

 in tmp,adch                ;ADC lesen
 sub awl,awh                ;1/256 subtrahieren, um Platz für
 sbc awh,null               ;den neuen Messwert zu machen
 add awl,tmp                ;Neuen Wert zum alten Wert addieren
 adc awh,null               ;Übertrag auch

...

von Dennis Brücke (Gast)


Lesenswert?

@...HanneS...,

wärst Du so lieb und würdest Du mir die Routine kurz erläutern ? So
richtig komm ich da nicht durch :(

Gruß Dennis

von ...HanneS... (Gast)


Lesenswert?

Hi Dennis...

Ich dachte, es wäre ausreichend kommentiert...
Diese Routine läuft bei mir im Tiny15 in einer Spannungsüberwachung.

;awh enthält den ganzzahligen Anteil des Mittelwertes.
;Dieser wird in der Reset-Routine auf einen Startwert gesetzt.
;Bei mir macht das die erste ADC-Messung vor "Scharfschaltung" der
;Spannungsüberwachung.

;awl enthält den "Nachkomma-Anteil" des Mittelwertes, also
;ein 256tel der Wertigkeit von awh.
;Die Bezeichnungen awh und awl kommen von AnalogWert H/L, da
;es bei mir nunmal (außerhalb des MC) Analogwerte waren.

;Der Neuwert wird nach temp eingelesen, wo der herkommt, ist
;eigentlich egal. In meinem Beispiel ist es ein 8-Bit-Wert vom ADC.

 in tmp,adch                ;ADC lesen

;Der Neuwert soll mit einer Wertigkeit von 1/256 in den
;Mittelwert eingehen. Dazu ist aber zuerst Platz für ihn zu machen,
;indem man 1/256 des momentanen Mittelwertes vom Mittelwert
;subtrahiert. Nun könnte man den (16-Bit-) Mittelwert durch 256
;teilen indem man ihn um 8 Stellen nach rechts schiebt. Dann wäre
;das obere Byte leer und das untere Byte enthält den Wert des
;oberen Bytes. Also kann ich gleich das obere Byte von den beiden
;Bytes subtrahieren, aber um 8 Bits (1 Byte) nach rechts versetzt.
;Da dabei der Subtrahend nicht verändert wird, kann man gleich das
;H-Byte vom L-Byte (mit Übertrag) subtrahieren.

 sub awl,awh                ;1/256 subtrahieren, um Platz für

;Da hier ein Übertrag auftreten kann, muss dieser behandelt werden.
;dazu wird das Carry vom H-Byte subtrahiert. Dies geschieht über
;ein (unteres, "billiges") Register, welches immer 0 enthält und
;demnach "null" genannt wird.

 sbc awh,null               ;den neuen Messwert zu machen

;Nun wird 1/256 des Neuwertes zum Mittelwert (dem jetzt 1/256 seines
;Wertes fehlt) addiert. Anstatt ihn nun durch 8 mal rechtsschieben
;durch 256 zu teilen, wird er einfach um 8 Stellen nach rechts
;versetzt addiert, also in den Nachkommabereich (L-Byte).

 add awl,tmp                ;Neuen Wert zum alten Wert addieren

;Da auch hier ein Übertrag entstehen kann, muss das Carry zum
;H-Byte addiert werden. Dies geschieht wieder durch Addition von
;Null mit Carry.

 adc awh,null               ;Übertrag auch

;Nun steht der neue Mittelwert im H-Byte.

Diese Routine ist sehr sparsam mit Ressourcen (Programmspeicher,
Datenspeicher, Rechenzeit) und filtert in meiner Spannungsmessung
wirkungsvoll Störungen aus.

Um das auf 16-Bit-Werte zu ergänzen, musst du 3 Bytes nutzen.
Die oberen 2 Bytes stellen den Mittelwert dar, das untere den
Nachkomma-Anteil.
Man subtrahiert dann die oberen 2 Bytes um ein Byte nach rechts
versetzt vom Mittelwert (mit Übertrag ins obere Byte) und addiert den
16-Bit-Neuwert in die unteren beiden Bytes (mit Übertrag ins Obere).
Das wars eigentlich schon.

...HanneS...

von ...HanneS... (Gast)


Lesenswert?

Hier die 16-Bit-Version...

Es genügen untere Register:

.def null=r2   ;immer Null (braucht man immer)
.def mwh=r3    ;Mittelwert High
.def mwl=r4    ;Mittelwert Low
.def mw0=r5    ;Nachkommastellen des Mittelwertes
.def nh=r6     ;Neuwert High
.def nl=r7     ;Neuwert Low

mittelwert:
 sub mw0,mwl   ;1/256 des Mittelwertes
 sbc mwl,mwh   ;vom Mittelwert
 sbc mwh,null  ;subtrahieren

 add mw0,nl    ;1/256 des Neuwertes
 adc mwl,nh    ;zum Mittelwert
 adc mwh,null  ;addieren

Benötigt 6 Worte im Flash und 6 Takte zur Ausführung.

...

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.