Port schnell in SRAM schreiben

Gast #3975696
Lesenswert?

Hallo,
stehe vor folgender Aufgabe:
Ich will in einer Interruptroutine über einen Zeitraum von 300µs 600 
Messwerte von einem parallelen 8Bit A/D-Wandler, der an einem Port des 
ATMega1284p hängt ins SRAM schieben um diese anschließend 
weiterzuverarbeiten. Der Interrupt wird nur etwa alle 80ms ausgelöst, so 
dass ich zwischen den Interrupts genügend Zeit habe die Daten 
weiterzuverabeiten. Ich programmiere üblicherweise in C.

Meine Frage:
Kann man die Aufgabe mit C oder Inline-Assembler bewältigen? AVR läuft 
mit 16MHz. Somit hätte ich pro Sample 8 Takzyklen Zeit. Bin in Assembler 
nicht wirklich fit, hab mir aber gerade mal die Instruktiontable 
angesehen und komme zu folgendem Resultat:

loop:
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
CPI Z, 800 --> 1 Zyklun
BRNE loop  --> 1,2 Zyklen

Also gesamt 5-6 Zyklen. Damit könnte ich 2,67MSps in den SRAM schieben, 
ist das korrekt?

Danke.
Persönliche Seite #3975736
Lesenswert?

CPI Z, 800 ist wohl etwas umfangreicher.
Ein CPIW gibt es nicht.

INIT Z
MOV Rcount,200
loop:
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
DEC Rcount --> 1 Zyklus
BRNE loop  --> 1,2 Zyklen

14 Zyklen pro 4 Bytes. (3,5 per Byte)

mov rH, HIBYTE(800)
loop:
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
CPI ZL,LOBYTE(800)  --> 1 Zyklus
CPC ZH,rH --> 1 Zyklus
BRNE loop  --> 1,2 Zyklen

6 Zyklen pro 1 Byte.

Die Methode nennt sich entrollen von Schleifen.
Gast #3975761
Lesenswert?

Tobias schrieb:
> loop:
> IN Rd, A   --> 1 Zyklus
> ST Z+, Rr  --> 2 Zyklen
> CPI Z, 800 --> 1 Zyklun
> BRNE loop  --> 1,2 Zyklen
>
> Also gesamt 5-6 Zyklen. Damit könnte ich 2,67MSps in den SRAM schieben,

Löse die Schleife auf. Kostet Flash, ist aber deutlich schneller. Die 
Anzahl der Werte kannst über die Einsprungadresse berechnen

PC = loop_n + (loop_nm1-loop_n) *(n-x)

loopn:
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
loop_nm1:
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
...
IN Rd, A   --> 1 Zyklus
ST Z+, Rr  --> 2 Zyklen
tue was anderes
Gast #3975814
Lesenswert?

Hallo,

Tobias schrieb:
> Ich will in einer Interruptroutine über einen Zeitraum von 300µs 600
das heißt alle 500ns stehen neu Daten an wie wird denn das 
synchronisiert?

nach 80ms kommt der int und dann werden für 300µs 600bytes aufgenommen?

keine Ahnung wie das in C aufgerufen wird oder beendet wird (InlineAsm)
Das mit dem CPI Z,800 geht so nicht da CPI nur 8bit breit vergleichen 
kann...
rein in asm:

.equ Datastart = $0060            ;speicherpunkt/zelle

Einsprung vom C
rcall    init_ZPOINTER
loop:
IN      RD,A                                   ;1 Zyk
ST      Z+,Rr                                 ;2 Zyk
CPI    ZL,LOW(DataStart+600)   ;1 Zyk
BRNE  loop                                  ;1-2 Zyk
CPI    ZH,High(DataStart+600)   ;1 Zyk
BRNE loop                                  ;1-2 Zyk =
Rücksprung zu C

init_ZPOINTER:
ldi  zh,high(DataStart)
ldi  zl,low(DataStart)
ret
Gast #3976212
Lesenswert?

Hallo,

vielen Dank für die Antworten. 6 Zyklen / Sample sollte also möglich 
sein. Dann gehe ich das Thema so an.

chris schrieb:
> das heißt alle 500ns stehen neu Daten an wie wird denn das
> synchronisiert?
Für die Synchronisierung mit dem ADC würde ich einen vom CPU-Takt 
abgeleiteten Takt generieren und über die Output Compare Unit ausgeben. 
Am Anfang der Interruptroutine will ich dann ebenfalls in Assembler das 
sampling der Daten auf den den Takt synchronisieren.

chris schrieb:
> nach 80ms kommt der int und dann werden für 300µs 600bytes aufgenommen?
Korrekt. Die Daten werden anschließend verrechnet. Bei den Messwerten 
handelt es sich um einen Zündspannungsverlauf. Es sollen die 
Zündspannung, die Brenndauer und die Brennspannung sowie Anomalien des 
Signals vermessen werden.

Dennis Heynlein schrieb:
> Hauptproblem wird die Verzögerung durch den Interrupteinstieg sein.
Da sehe ich in meiner Anwendung kein Problem, da die ersten 5µs des 
Signals für mich uninteressant sind. Starten will ich das Sampling über 
eine eigene Komparatorschaltung ebenfalls Interruptgesteuert. Ein 
zeitlicher Versatz eines gesampleten Datenblocks zum nächsten um ein 
paar µs spielt keine Rolle.

Dennis Heynlein schrieb:
> Und die Verarbeitunggeschwindigkeit.
80ms reichen mir hier auch mit Weiterverarbeitung in C völlig aus.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren