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.
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.
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
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
Für die 600 Meßwerte steht genug RAM zur Verfügung.
Der Quarz sollte dann eine passende Frequenz (20 MHz z.B.) haben um mit
NOP die entrollte Schleife vom Timing her zu frisieren.
Hauptproblem wird die Verzögerung durch den Interrupteinstieg sein.
Und die Verarbeitunggeschwindigkeit.
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.
Dennis Heynlein schrieb:> CPI Z, 800 ist wohl etwas umfangreicher.
Ach komm, CPI + CPC kostet gerade mal einen Zyklus mehr als bei 8Bit.
Sind dann 7 Zyklen, also ist noch ein NOP nötig, um auf 8 zu kommen.