Frage:
Warum variiert die ADC-Konvertierungszeit?
AndrejaKo
2014-01-04 17:22:17 UTC
view on stackexchange narkive permalink

Ich verwende TI Tiva C TM4C123GH6PM auf einem Launchpad in Kombination mit einem AD 9850 DDS, um einen Frequenzmodulator zu erstellen.

Derzeit habe ich ein extrem einfaches Programm, das im Grunde die Peripheriegeräte des Mikrocontrollers und den AD9850 einrichtet und dann in eine Schleife übergeht, in der das zum ADC des Mikrocontrollers kommende Audiosignal abgetastet und basierend auf den Ergebnissen die Ausgangsfrequenz von angepasst wird das DDS.

Mein Problem ist, dass die Ausführungszeit der Schleife nicht konstant ist.

Die Schleife ist in drei grundlegende Teile unterteilt: Im ersten Teil erhalte ich ein Beispiel vom ADC Im zweiten Teil werden die erforderlichen Einstellungen für den AD9850 berechnet und im dritten Teil werden diese Einstellungen an den AD9850 gesendet.

Nach einigen Zykluszählungen stellt sich heraus, dass der zweite und dritte Teil immer 2670 Taktzyklen dauern. Dies lässt mich mit dem einzigen Verdächtigen zurück, der der erste Teil ist.

Nachdem ich die Ausführungszeit des ersten Teils allein gemessen habe, habe ich festgestellt, dass sie von nur 100 Zyklen bis zu 8000 variiert Fahrräder.

Hier ist ein schönes Diagramm, das ich vom Debugger erhalten habe und das zeigt, wie sich die Anzahl der Zyklen mit der Zeit ändert:

Graph showing on its Y axis number of cycles it took for the ADC to provide a sample and on its X axis number of samples taken

Ich habe in das Datenblatt von geschaut Der Teil und in das Benutzerhandbuch der Tivaware Peripheral Driver Library und ich konnten keinen Grund finden, warum das Sampling so drastischen Jitter haben würde. Die ADC-Abtastung plus Konvertierungszeit wird als 1 Mikrosekunde angegeben, was ungefähr 80 Prozessorzyklen entspricht, da ich mit einer Taktfrequenz von 80 MHz arbeite. Dadurch sieht die Schleifendauer im Bereich von etwa 100 bis 200 Zyklen in Ordnung aus, aber ich habe absolut keine Ahnung, was in dem Fall passiert, wenn die Zeit in Tausenden von Zyklen liegt.

Ich habe auch die Errata für den ADC gelesen und soweit ich sehen kann, trifft keines der zahlreichen Probleme auf meinen Fall zu. Außerdem ist der Teil, den ich habe, ein tatsächlicher TM4-Teil, kein experimenteller XM4-Teil.

Hier ist der problematische Teil des Codes:

  c_start = HWREG (DWT_BASE + DWT_O_CYCCNT); // startet die Zykluszählung
ROM_ADCIntClear (ADC0_BASE, 3); // löscht das Interrupt-FlagADCProcessorTrigger (ADC0_BASE, 1); // Auslösen der Sequenz 1while (! ROM_ADCIntStatus (ADC0_BASE, 3, false)) // Wartet, bis der ADC die Konvertierung abgeschlossen hat {// Besetzt warten, um ersetzt zu werden mit einem ISR irgendwann} ROM_ADCSequenceDataGet (ADC0_BASE, 3, adcData); // AdcData-Zeiger auf Speicherort // zum Speichern von Ergebnissenc_stop = HWREG (DWT_BASE + DWT_O_CYCCNT); // Beendet den Zyklus countc_dur = c_stop-c_start; // Gibt die Anzahl der Zyklen an. Der Aktualisierungs-Haltepunkt wird hier angezeigt.  

Hier ist der ADC-Setup-Code:

  ROM_SysCtlPeripheralEnable ( SYSCTL_PERIPH_ADC0); // Pin ist PD1 = >channel. AIN6ROM_ADCHardwareOversampleConfigure (ADC0_BASE, 64); 0x40; // Dies aktiviert das Hardware-DitheringADCSequenceConfigure (ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0); // Verwendet ADC0, Sequenz 3 = >FIFO mit einer Länge von eins, höchste Priorität ADCSeCence_te_ Erster und letzter Schritt, wählt ADC0, Sequenz 3, Schritt Null, Kanal 6, // aktiviert Interrupt und beendet SequenzADCSequenceEnable (ADC0_BASE, 3); // Aktiviert Sequenz  

UPDATE: Ich habe den Test mit Pin Wiggling durchgeführt und relativ ähnliche Ergebnisse erzielt. Auf diesem Bild geht ein Pin hoch und dann sofort niedrig, sobald der ADC abgeschlossen ist. Dies erfolgt bei deaktiviertem Dithering und Hardware-Oversampling mit einer Abtastrate von 1 MSa / s und einer FIFO-Puffertiefe von 1. enter image description here

Zweifel, ob es das Problem verursacht, aber ich denke, um das Dithering zu aktivieren, sollte die Syntax eher "HWREG (ADC0_BASE + 0x038) = 0x40" sein. Ich frage mich auch, ob es ein Problem mit der Einrichtung der DWT-Einheit ist, wenn Sie noch nichts Ähnliches getan haben. Es könnte sich lohnen, eine E / A umzuschalten und mit einem Umfang zu messen, um dies aus der Gleichung herauszunehmen.
@PeterJ Ich selbst bin mir nicht sicher über die Syntax ... Auch was ist DWT? Ich kann mit HWREG Pins wackeln, aber selbst wenn ich das benutze, ist die Zeit, die der Pin benötigt, um nach dem Hochsetzen auf Low zu gehen, sehr lang.
OK, DWT scheint Data Watchpoint and Trace zu sein und wird im Datenblatt erwähnt.
@PeterJ Ich habe einige Tests durchgeführt und Sie hatten Recht mit der Einrichtung des Dither-Bits. Vielen Dank, dass Sie diesen Fehler entdeckt haben!
Dies ist keine Antwort, aber die Problemumgehung ist einfach. Aktivieren Sie den ADC * nach * der Überprüfung auf ein Ergebnis und nicht zuvor. Wenn bei der Überprüfung kein Ergebnis vorliegt, verwenden Sie das vorherige erneut. Es gibt keinen Grund, auf den ADC zu warten - lassen Sie ihn arbeiten, um das nächste Sample zu erhalten, während Sie das vorherige verarbeiten.
Wenn mein Code unregelmäßig viel länger dauert als erwartet, liegt dies normalerweise an Interrupts. Manchmal habe ich keinen richtigen Interrupt-Handler, und wenn dieser Interrupt ausgelöst wird, führt er zufälligen Code aus. Manchmal habe ich zu viel Code in einen Interrupt eingefügt. Manchmal ist meine Software in Ordnung, aber Hardware generiert Interrupts schneller als erwartet - [Interrupt Storm] (https://en.wikipedia.org/wiki/interrupt_storm). Könnten Sie einen Schnelltest durchführen, bei dem alle Interrupts vorübergehend deaktiviert sind?
@davidcary In meinem Fall sind alle Interrupts deaktiviert und alle ISRs sind die Standardeinstellung "while (1) {}". Ich verwende das Interrupt-Flag, um festzustellen, ob der ADC fertig ist, aber ich frage ihn nur ab. Der Interrupt selbst ist deaktiviert.
Ich wette, PeterJ meinte WDT, was für Watchdog Timer steht. Wenn es aktiviert ist, wird bei jedem Taktzyklus ein Zähler inkrementiert. Wenn der Zähler überläuft, wird das Mikro zurückgesetzt. Daher sollte der Programmierer den Zähler von Zeit zu Zeit zurücksetzen, um dies zu vermeiden. Die Idee ist: Mein Code schlägt fehl, das Mikro sperrt, aber in wenigen ms wird es vom wdt zurückgesetzt. Überprüfen Sie dies auch.
@Vladimir Cravero Beachten Sie, dass bisher keine WDT-Einheit erwähnt wurde. Außerdem weiß ich genau, was ein Watchdog-Timer ist, und in diesem Fall ist er nicht hilfreich. Es gibt zu wenig Code, um an unbekannten Orten zum Stillstand zu kommen, und es hat keinen Vorteil, das Mikro zurückzusetzen, anstatt es hängen zu lassen. Wenn es hängt, kann ich leicht genau sehen, wo es einen Debugger verwendet, aber wenn es zurückgesetzt wird, habe ich diese wichtige Information verloren.
@AndrejaKo Wenn das wdt aktiviert ist und Sie es nicht zurücksetzen, spielt es keine Rolle, wie viel Code Sie ausführen, das Mikro wird schließlich vom wdt zurückgesetzt. Das wdt-Register ist 32 Bit breit und sollte mehr als 53 Sekunden ausfüllen. Das wdt sollte beim Zurücksetzen ausgeschaltet sein, aber das Verhalten, das Sie erleben, ist einem schlechten wdt ziemlich ähnlich ...
@Vladimir Cravero Aber ich habe die Uhr für die Watchdog-Timer überhaupt nicht aktiviert! In diesem Fall setzt sich der Mikrocontroller nicht selbst zurück. Wenn ja, würde ich das im Debugger sehen. Ich habe Watchdog-Timer auf diesem Mikrocontroller absolut nie aktiviert.
Ja, das habe ich auch nach dem Einchecken im Datenblatt festgestellt. Weißt du, es war nur, um besonders sicher zu sein.
@Vladimir Cravero Ja, ich stimme zu, dass es am besten ist, besonders sicher zu sein und es dann einfach abzuschreiben. Ich habe den Status im Debugger überprüft, nur für den Fall, dass etwas Unerwartetes passiert.
@AndrejaKo Wie hoch ist die Frequenz des ADC-Takts und ist er mit dem TM4-Takt synchron? Ihre Handlung lässt mich denken, dass die ADC-Uhr viel langsamer und nicht mit der TM4 synchronisiert ist, daher das Rauschmuster, aber ich könnte mich irren.
@vrleboss Das ist ein sehr guter Kommentar! Der Takt für den Mikrocontroller wird vom 16-MHz-Kristall abgeleitet, dessen Wellenform in eine PLL geht und dann durch 2,5 geteilt wird. Das Datenblatt sagt Folgendes für den ADC-Takt: `Der größte Teil der ADC-Steuerlogik läuft mit der ADC-Taktrate von 16 MHz. Der interne ADC-Teiler wird automatisch von der Hardware für den 16-MHz-Betrieb konfiguriert, wenn das System XTAL mit der PLL ausgewählt wird. "Meiner Meinung nach sollten beide Takte, da sie von derselben PLL abgeleitet sind, synchronisiert werden, wobei die ADC-Taktperiode 5 beträgt Hauptuhrperioden.
@vrleboss Es ist auch möglich, die ADC-Uhr vom PIOSC und direkt vom MOSC abzuleiten, sodass es sich möglicherweise lohnt, zu prüfen, ob die Uhr irgendwie von dort kommen könnte.
An welcher Stelle befand sich der Analogeingang, als Sie den Jitter in der Umwandlungszeit gemessen haben?Wird es auf einer bekannten Spannung gehalten oder variiert es?Es ist ein langer Weg, aber ich frage mich, ob die gelesene Spannung einen Einfluss hat.Abhängig von der ADC-Methode tritt häufig eine zeitliche Variation auf, um einen Lesevorgang basierend auf dem Eingangspegel abzuschließen.insbesondere in ADCs mit sukzessiver Approximation, die in MCUs üblich sind.
Ich frage mich nur, ob Ihre Signalquelle über alle Frequenzen hinweg eine konstante Impedanz (mehr oder weniger) hat.
@user34920 Nun, mein Signal ist eine Drahtantenne mit zufälliger Länge, also denke ich, dass sie keine konstante Impedanz hat.
Variiert die Konvertierungszeit mit dem gelesenen Wert?Ist es konstant (oder nahe), wenn ein konstanter Wert konvertiert wird?
Fünf antworten:
Scott Seidman
2014-10-09 19:08:27 UTC
view on stackexchange narkive permalink

Während es Gründe gibt, die von anderen beschrieben wurden, woher Ihr Jitter kommen könnte, ist es für Echtzeitsysteme nur eine schlechte Praxis, von Dingen wie der Konvertierungszeit (oder sogar versteckten Zweigen in Funktionsbibliotheken, in denen jeder Zweig unterschiedliche Zeiten benötigt) abhängig zu sein.

Wenn Sie eine niedrige Jitter-Schleifenzeit benötigen, müssen Sie dies tun, indem Sie einen Timer-Interrupt erstellen, um ihn Ihnen zu geben. Wenn Sie Geschwindigkeit benötigen, sollte der Timer durch Ihre Schleifen auf Ihre maximale Zeit eingestellt werden, plus ein wenig Kopffreiheit. Bei einem Timer-Interrupt sollten Sie alles warten, was basierend auf Ihrem letzten ADC-Lesevorgang ausgeführt werden muss, und dann den nächsten ADC-Lesevorgang ausführen.

Ben Jackson
2014-03-31 00:10:43 UTC
view on stackexchange narkive permalink

In diesem Fall setzt sich der Mikrocontroller nicht selbst zurück. Wenn ja, würde ich das im Debugger sehen.

Ich vermute, dass Sie dies immer unter dem Debugger ausführen und adcData ​​code> überwacht haben, weil Es sind interessante Daten. Die IDE bewahrt dies hilfreich zwischen den Läufen. Ich werde weiter vermuten, dass der TI-Prozessor Hardware-Überwachungspunkte bei Speicherschreibvorgängen unterstützt und der Debugger diese verwendet, um Aktualisierungen von adcData ​​code> abzufangen. Jedes Mal, wenn Sie Ihre Schleife durchlaufen, erreicht der Debugger den Überwachungspunkt und stoppt so lange, bis der externe Debugger die Daten ausgelesen und den Chip wieder aufgenommen hat.

Wenn Sie das Bit wackeln ließen und ohne den Debugger liefen Sie könnten diese Theorie testen.

Das Bild vom Oszilloskop wurde mit deaktiviertem Debugger erstellt.
Whistle1560
2014-07-02 09:24:18 UTC
view on stackexchange narkive permalink

Als Nebenbemerkung sollte die ADC-Erfassungszeit begrenzt sein, aber ich habe einige Unterschiede bei der Charakterisierung von Komponenten festgestellt. Das Datenblatt gibt wahrscheinlich ein typisches oder ein "durch Design garantiert". Außerdem kann die Gültigkeit jeder Erfassung aufgrund von Rauschen weder vom Layout noch auf andere Weise garantiert werden.

MPA
2014-09-09 00:06:07 UTC
view on stackexchange narkive permalink

Sie erwähnen keine Interrupts, aber ich sehe, dass Sie ein Interrupt-Flag im Code löschen. Wenn Sie dies noch nicht getan haben, deaktivieren Sie Interrupts global. Wenn andere Interrupts ausgelöst werden, kann dies zu Jitter führen.

Bei einer softwarebasierten Schleife können viele Dinge zu einer unregelmäßigen Ausführung führen. Der zuverlässigste Weg, um genau abgetastete Daten zu erhalten, besteht darin, den ADC mit einer zuverlässigen Quelle wie einem Timer auszulösen (was meiner Meinung nach ohne externe Hardware auf diesem Gerät möglich ist). Das gleiche Timersignal könnte einen ISR auslösen, bei dem Sie das Ergebnis in größerer Freizeit sammeln und verwenden können, oder es könnte DMA auslösen, um Samples in einen Puffer zu kopieren.

Ich empfehle Vorsicht bei Bibliotheken wie TivaWare . Sie werden normalerweise aus Bequemlichkeitsgründen und nicht aus Gründen der Effizienz geschrieben. Wenn Sie den Quellcode aufspüren können, werden Sie wahrscheinlich feststellen, dass sie in diesen Routinen eine bemerkenswerte Menge an Housekeeping durchführen. Sehr oft erzielen Sie eine viel bessere Leistung, wenn Sie direkt auf die Register klicken.

Tanmay
2014-10-09 18:53:08 UTC
view on stackexchange narkive permalink

Es gibt drei am häufigsten verwendete Arten von Analog-Digital-Wandlern.

  • Zählertyp ADC.
  • ADC mit sukzessiver Approximation.
  • ADC vom Flash-Typ.

    1. ADC vom Zählertyp:

      Bei diesem Typ wird der Eingang mit einer digital erzeugten Referenzspannung verglichen. Die Referenzspannung wird schrittweise erhöht Schritt, bis die Referenzspannung größer als die Eingangsspannung ist. Für unterschiedliche Eingangsspannungen ist die Zeit für die Umwandlung unterschiedlich.

    2. ADC mit sukzessiver Approximation:

      Bei diesem Typ wird das gleiche Prinzip angewendet, jedoch auf intelligente Weise. Die erste Eingangsspannung wird mit Va / 2 verglichen (wobei Va die Obergrenze der Eingangsspannung ist), um herauszufinden, in welcher Hälfte sie liegt. Wenn es größer als Va / 2 ist, wird es mit 3Va / 4 verglichen, andernfalls wird es mit Va / 4 verglichen, um herauszufinden, in welchem ​​Viertel es liegt. So etwas wie eine binäre Suche in Computerprogrammen.

    3. Flash-Typ ADC:

      Bei diesem Typ wird die Eingangsspannung mit allen Spannungspegeln gleichzeitig verglichen und der entsprechende Ausgang angegeben. Die für diese Art der Konvertierung benötigte Zeit ist konstant und hängt nicht von der Eingangsspannung ab.

    4. ol>

Weitere Informationen zu ADC finden Sie im PDF: http://www.physics.arizona.edu/~haar/ADV_LAB/ADC.pdf

Ich schlage vor, ein Flash-ADC ist am besten für Ihre Schaltung geeignet. Wenn Sie arbeiten möchten Auf derselben Hardware können Sie zwei Dinge tun.

  1. Ermitteln Sie die maximale Zeit (Ta), die der ADC für die Konvertierung benötigt. Stellen Sie einen Timer-Interrupt auf einen Wert über Ta ein. Jedes Mal, wenn Sie eine Konvertierung anfordern, starten Sie den Timer und führen Sie den Rest des Codes erst aus, nachdem der Interrupt aufgetreten ist. Dies ist nicht der beste Weg, aber Sie erhalten eine ADC-Konvertierung in einer konstanten Zeit. Die Codestruktur sieht ungefähr so ​​aus:

    • (Teil 1):
    • Konvertierungsanforderung
    • Timer-Interrupt einrichten.
    • i = 0;
    • while (i == 0) {} // keine Abfrage erforderlich
    • Daten vom ADC speichern
    • führt Teil 2 und Teil 3 wie zuvor aus

      Interrupt-Serviceroutine für Timer-Interrupt

      • {i = 1;}

    Hinweis: Timer-Interrupt einrichten bedeutet, den Timer auf 0 zu setzen und Interrupts zu aktivieren.

  2. ol>

    ODER

    1. Verwenden Sie den ADC im Freilaufmodus (ADC konvertiert weiter, unabhängig davon, ob eine Konvertierung angefordert wird oder nicht ). Laden Sie jedes Mal, wenn Sie eine Probe entnehmen möchten, diese einfach, ohne eine ADC-Konvertierung anzufordern. keine while-Schleife erforderlich. (Damit diese Methode verwendet werden kann, muss Ihr ADC den Freilaufmodus unterstützen.)
    2. ol>
Ich bin neu im Stapelaustausch und daher nicht an diese Art der Formatierung gewöhnt.Trotzdem danke.Hoffe, es ist jetzt besser lesbar.
Umfassende Antwort.Es gibt verschiedene Arten von ADCs, die in Ihren "Zählertyp" fallen können, z. B. die Integration von ADCs.Steigung, doppelte Steigung und dergleichen, wobei die Vergleichsspannung eine Konstante ist, aber ein Zähler rollt, während das integrierte Signal entleert wird.


Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 3.0-Lizenz, unter der er vertrieben wird.
Loading...