Hallo Leute,
ich bin echt ratlos und benötige Hilfe.
Und zwar habe ich hier ein Board mit einem Am186er, an den über ein PLD
2 AD7606 AD-Wandler angeschlossen sind (Offenbar übersetzt der das
externe Memory-Interface der MCU in Steuersignale für die AD-Wandler).
Nun möchte ich die AD-Wandler mit einer festen Rate auslesen, die Daten
etwas mitteln und dann raussenden (das ganze soll durch eine
Statemachine an- und abschaltbar sein etc.).
Mein Problem ist jetzt folgendes: Die Hardware ist zwar so aufgebaut,
dass man mit dem integrierten DMA-Controller auf einmal alle AD-Kanäle
einlesen kann, allerdings muss man manuell einen Wert an die
I/O-Addresse schreiben, um die Konvertierung zu starten. Wenn ich das
nun bei fester Abtastrate machen will, bleibt mir daher eigentlich nur
einen Timer zu benutzen, der den Wert schreibt und dann einen
DMA-Transfer zum Auslesen startet. Bei 10kHz Abtastrate kommt da aber
ein ganz schönes Interrupt-Gedöns zusammen. Ab ca. 30kHz geht die MCU
dann alleine durch die Interrupts in die Knie, an Weiterverarbeitung der
Daten ist dann überhaupt nicht zu denken.
Der Sample-Code zu dem Board benutzt immer Endlos-Schleifen um hohe
Datenraten zu erreichen, aber ich weiß nicht, wie ich bei einer
Endlos-Schleife noch die Kommunikation einbauen soll, ohne dass die
Abtastrate absolut ungleichmäßig wird oder wie ich damit überhaupt die
Abtastrate vernünftig steuern soll. Wenn man Daten aufnimmt, will man
doch wohl immer eine gleichmäßige und irgendwie kontrollierbare
Abtastrate erzielen Oo.
Hat da von euch jemand eine Idee? Ich komme ja aus der Welt der
Highlevel-Entwicklung und dort hat man ja immer schön seine Timer und
alles funktioniert so reibungslos...
Des weiteren verstehe ich im Handbuch zum Controller
(support.amd.com/TechDocs/21684.pdf Kapitel 9 und 10 sind dafür wohl das
interessante) nicht, was genau ich tun muss, um den DMA-Controller durch
den Timer zu steuern, bzw. was es überhaupt bewirkt, das zu tun. Bezieht
sich das darauf, dass die einzelnen Wörter eines Transfers zu den
Timer-Zeiten übertragen werden, oder startet der Timer immer einen
kompletten Transfer? Ich habe viel rumprobiert, aber diese
Funktionalität nicht in irgendeiner Weise zum laufen gebracht. Finde die
echt bescheiden beschrieben und habe nirgendwo im Internet
weitergehendes gefunden. Hat von euch da jemand Erfahrung?
Viele Grüße
Oder der Gedankengang in die andere Richtung... Gibt's irgendwie
wartbare Programmiertechniken, um vernünftiges Timing nur durch
Timer-Polling "in einem Ausführungssthread" hinzubekommen, also nicht
interruptgetrieben, aber trotzdem annähernd nebenläufig? Ich stelle mir
das höllisch vor, aber vielleicht kann man sowas ja einigermaßen gut
hinbekommen?
Ansonsten nehme ich jetzt einfach die Interrupt-Taktik mit entsprechend
niedriger Abtastrate, das ist irgendwie wohl der schmerzloseste Weg.
DMA heisst normalerweise, dass man nicht bei jedem einzelnen Transport
einen Interrupt an der Backe hat. Es stecken hier doch 2 Aufgaben drin:
(1) Zyklisch einen Wandlerwert auszulesen und in einen Puffer zu
schreiben.
(2) Im gleichen Zyklus eine neue Wandlung anzustossen.
Wenn sich das nicht ohne Interrupts automatisieren lassen sollte, dann
ist DMA für den Allerwertesten. Ich habe freilich nicht recht
verstanden, welcher Teil nun das Problem ist.
Je nach Art der Wandler kann man die auch freilaufend in vollem Galopp
arbeiten lassen, um lediglich ab und zu per Timer getriggert einen Wert
rauszufischen. Das Risiko ist dann aber eine Schwebung, die sich aus den
verschiedenen Zyklen ergibt.
Aus dem Datasheet des Wandlers ergibt sich eigentlich eine ziemlich
klare Arbeitsweise für zyklische Wandlung: Ein Timer stösst die Wandlung
per CONVSTA/B Pins an und das BUSY Signal stösst seinerseits einen
DMA-Burst an, der die Daten der Channels abholt.
Die Fähigkeiten des DMA Controllers habe ich grad nicht eruiert, aber
wenn der solche Bursts nicht selber hin bekommt, dann besteht die
Aufgabe des Businterfaces letztlich darin, aus dem BUSY Signal des
Wandlers ein DMA-Request Signal zu zaubern, das mit fallendem BUSY
anfängt und nach komplettiertem Burst endet - also eigentlich nur einen
Zähler darstellt. Dann läuft das ganze vollautomatisch ohne Interrupts.
Hallo!
Danke für die ausführlichen Antworten!
Folgende Probleme:
1. laut Schaltplan des Boards sind die Busy-Pins der AD-Wandler
überhaupt nirgends angeschlossen.
2. DRQ0 ist angeschlossen an einen Pin-Header
3. DRQ1 ist angeschlossen an einen FT232
Ich kann nicht genau sagen, wie der Interface-PLD arbeitet, aber dort
sind die Adressbits 4 bis 7 angeschlossen sowie /RD und /W, also nehme
ich mal an, er generiert aus den Adressbits und /RD bzw. /W
Conversion-Start-Kommandos und Chipselect-Signale für die
Peripherie-ICs, an die er dann auch angeschlossen ist. Das passt auch
gut zu den Adressen, die in den Samples verwendet werden um die
AD-Wandler anzusprechen, von den Bitpositionen her.
Das stellt sich dann wie gefolgt dar, ein Schreibzugriff auf die
IO-Adresse 0x160 startet die Wandlung an beiden AD-Wandlern.
Danach kann ich mit jeweils 8 Lesezugriffen auf die Adressen 0x120 und
0x130 die 16 Kanäle auslesen. Da die unteren Bits nicht angeschlossen
sind, kann ich also auch den DMA-Controller nehmen und 16 Worte startend
ab 0x120 lesen.
Also ist die Situation, dass die beiden Wandler von außen keinen
DMA-Transfer initiieren können, ich muss das alles auf der MCU regeln,
nur die Frage ist wie am besten.
Zunächst habe ich einfach eine Endlosschleife mit AD-Lesen, Berechnen,
Serial-Lesen, Serial-Schreiben geschrieben. Aber das erfüllt natürlich
überhaupt keine Ansprüche an irgendwelche präzisen Abtastzeiten und ich
habe auch gar keine Kontrolle über die Abtrastrate, wenn ich mal von
NOPs absehe...
Daher versuche ich jetzt irgendwie das beste aus der Situation zu
machen, die Hardware scheint mir schon etwas verkorkst zu sein und der
DMA-Controller hilft mit auch nur sehr bedingt, weil er die Adressen
nicht automatisch zurücksetzen kann. Ansonsten hätte ich gesagt, ich
nehme einen DMA-Controller der wie oben beschrieben durch den Timer auf
die 0x160 schreibt (startet Konversion), und den anderen, um am selben
Timer immer 16 Worte von 0x120 zu lesen.
Geht aber leider auch nicht -.-
Viele Grüße
BastiDerBastler schrieb:> 2. DRQ0 ist angeschlossen an einen Pin-Header> 3. DRQ1 ist angeschlossen an einen FT232
Dann ist DMA für die ADCs nicht vorgesehen.
> ich muss das alles auf der MCU regeln, nur die Frage ist wie am besten.
Oder am Board rumbasteln.
Ich geb's auf, ich verstehe nicht, wie man für 40€ AD-Wandler auf ein
Board bauen kann, aber das so verhunzt, dass man sie nicht vernünftig
verwenden kann. Ich werde die Timer-Lösung wählen, so verhält sich das
Gerät dann nach außen wenigstens vernünftig, mit dem Mega-Jitter muss
man sich dann halt abfinden.
Nur eine Frage noch:
16x IO lesen vom Quellcode sollte effizienter sein als 2x schreiben um
den DMA einzustellen und danach den DMA-Interrupt zu behandeln, oder?
Dann verzichte ich lieber komplett auf DMA...