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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.