@CrazyHarry:
Danke für den Hinweis. Das war schonmal eine große Hilfe - konnte den XMEGA128A1 bis ca. 55 MHz hochtakten - danach hat er aber gesponnen - für den vewendeten µC liegt hier wohl die Grenze (wie im Datenblatt angegeben).
Habe heute noch fleißig weiter probiert und dabei kam mir eine vermeintlich gute Idee - die jedoch in der Ausführung Zicken macht -warum weiß ich noch nicht.
Ich hatte die Idee, um die ganzen Interupts zu umgehen DMA zu verwenden. Für die Generierung des Analogen Ausgangssigals und den SPI-Lesevorgang kein Problem. Die Initiierung der AD-Wandlung lies sich auch rein Hardwaretechnisch über ein PWM-Timer lösen.
Also bis jetzt habe ich es geschafft alles ohne Software umzusetzten - lediglich beim Absetzten der 4 Bytes mittels SPI gibt es Probleme.
Zum Timing:
Ein Zyklus dauert 5 µs.
Die AD-Wandlung benötigt 1,4 µs vom Zyklusbeginn.
Dann sollen alle 0,5 µs willkürliche Bytes in das SPI-Data-Register geschrieben werden.
Das soll sich so jeden Zyklus wiederholen.
Nach langen Überlegen hatte ich folgende Idee:
Ein separater Timer löst mit jedem Overflow ein DMA-Schreibzugriff auf das SPI-Data-Register aus.
Ein weiterer DMA-Kanal greift zyklisch auf einen Array mit den Timer-Werten zu und schreibt diese in das PER-Register des benannten Timers.
Also so, dass das PER-Register des Timers rein Hardwaremäßig aktualisiert wird, ohne das der µC eine Programmzeile benötigt.
Theoretisch sollte das doch funktionieren? (2 DMA's können vom gleichen Timer ausgelöst werden - das habe ich getestet)
Leider kann ich das ganze nicht im Simulator prüfen - auf dem Board wird mir die Änderung des PER-Registers via DMA unterschlagen.
Hier nochmal der DMA-Zugriff auf das Timer-Register (vereinfacht):
Code:
volatile uint8_t TestNum = 200;
void SetupWriteChannel( DMA_CH_t * dmaChannel )
{
DMA_SetupBlock(
dmaChannel,
TestNum,
DMA_CH_SRCRELOAD_NONE_gc,
DMA_CH_SRCDIR_FIXED_gc,
(void *) &(TCD0.PER),
DMA_CH_DESTRELOAD_NONE_gc,
DMA_CH_DESTDIR_FIXED_gc,
1,
DMA_CH_BURSTLEN_1BYTE_gc,
0,
true
);
DMA_EnableSingleShot( dmaChannel );
DMA_SetTriggerSource( dmaChannel, DMA_CH_TRIGSRC_TCD0_OVF_gc );
}
...
DMA_Enable();
DMA_CH_t * WriteChannel = &DMA.CH1;
SetupWriteChannel( WriteChannel );
DMA_EnableChannel( WriteChannel );
Die Änderung des PER-Werts wird leider nicht übernommen - wo kann hier der Fehler liegen?
Vielen Dank für die Hilfe!
Gruß Erik
Lesezeichen