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...
Wobei ich auch x mal blind den DMA anschmeißen könnte und nur ab und zu mal den Interrupt aktivieren könnte um ein Datenpaket endzuverarbeiten...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.