Forum: Mikrocontroller und Digitale Elektronik Am186er Timing


von BastiDerBastler (Gast)


Lesenswert?

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

von BastiDerBastler (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von BastiDerBastler (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von BastiDerBastler (Gast)


Lesenswert?

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...

von BastiDerBastler (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.