Forum: Mikrocontroller und Digitale Elektronik MSP430 ADC hängt bei Polling auf Interrupt


von Christoph (Gast)


Lesenswert?

Hi,
mein Problem ist, dass der AD-Wandler meines µC (MSP430F1610) in 
halbwegs unregelmäßigen Abständen stehen bleibt.

Das die Stelle, an der er passiert:
1
float pt_get()
2
{ 
3
        float temp;
4
5
        ADC12CTL0 &= 0xfffd; // ENC aus um Konfig zu ändern (stoppt am Ende der Sequenz)
6
        ADC12IFG &= 0xfffe;  // Interrupt flag löschen
7
        ADC12CTL0 |= ENC + ADC12SC;  //ADC12 wieder starten
8
        pt_data.count++;
9
        while( !(ADC12IFG & 0x0001));
10
        pt_data.adc = ad_get_int(0);
11
  temp = pt_data.adc * ADC_REF_EXT / (1<<12);  // AD-Wert --> Spannung

Der ADC läuft im "Repeat sequence of channels"-Mode frei durch.
Deshalb soll das Programm in der while-Schleife auf den nächsten 
Wandlerwert warten, da zuvor Messkanal erst durchgeschaltet wurde.
Nur bleibt er eben in der while-Schleife immer wieder hängen.
Dabei steht dann im ADC12IFG: 0x000E. Die ADC12 Kontrollregister sehen 
im Debugger eigentlich richtig aus (ENC, ADC12ON und ADC12SC sind 
gesetzt), aber der Wandler liefert keine neuen Werte, ergo kein neues 
Interrupt-flag und ich kommen nicht mehr aus der Schleife raus. Bleibt 
er hängen, ist das BUSY-Bit durchgehend 1.
Wenn ich via Debugger ADC12ON erst Null und dann wieder Eins setzte, 
läuft er weiter.
Was mich jedoch am meiste wundert ist, dass das Programm immer wieder 
nach der gleichen Anzhal Zyklen stehenbleibt. (pt_get() wird in 
2ms-Intervallen aufgerufen)
Ich habe das Programm bis jetzt 14 mal durchlaufen lassen, dabei sind 
Hänger im Bereich des 55. bis 394. Zykluses aufgetreten. Dabei waren:
55: 3mal
89: 3mal
123: 2mal
191: 2mal

Nehme ich die while-Schleife raus, treten keine Hänger auf...

Hat jemand ne Idee, wo der Fehler liegen könnte und vor allem in welche 
Richtung ich suche sollte?
Wieso beeinflusst das Polling überhaut den ADC?

Danke schonmal im Vorraus.

Gruß Christoph

und noch was: alle Interrupts sind in dem Programmbereich aus. (GIE = 0)

von Jörg S. (joerg-s)


Lesenswert?

Wieso wurstet das pt_get() Programm in den ADC Registern rum wenn du 
doch sagst: "Der ADC läuft im "Repeat sequence of channels"-Mode frei 
durch."? Du musst doch die Wandlung nur einmal anstossen und er wandelt 
dann ewig weiter bist du ihn stoppst. Wenn du jedesmal von Hand neu 
startest, ist das der "sequence of channels" Mode.

von Christoph (Gast)


Lesenswert?

Jau, komplett frei läuft er nicht durch :)
Ich hab mehrere Eingänge, die ich abtaste. Dauert insgesamt irgendwas im 
zweistelligen µs-Bereich. Alle 2ms brauche ich dann die Spannung am 
PT-Element und das relativ schnell. (Den ersten richtigen Wert nach dem 
Aufschalten der Referenzspannung). Deswegen das Löschen des 
Interrupt-Flags mit anschließendem Polling. Dann läuft er wieder frei 
weiter.
Kann gut sein, dass das noch nicht die optimale Lösung ist, so konnte 
ich aber bestehenden Code weiterverwenden. Und bevor ich da 
weiterbastel, würde ich doch ganz gerne wissen, wieso da diese Hänger 
auftreten...

von Jörg S. (Gast)


Lesenswert?

Also noch mal zum mitschreiben :)

Du machst "Repeat sequence of channels", dann willst du irgendwann einen 
speziellen AD Eingang wandeln, dazu stoppst du die "Repeat sequence of 
channels" und wandelst einmal einen Eingang und startest danach  wieder 
"Repeat sequence of channels"? Richtig?

von Stefan (Gast)


Lesenswert?

Wenn Du während "Repeat sequence of channels" eine "single-channel, 
single conversion" einschieben willst, dann solltest Du das dem ADC12 
auch sagen:
1
ADC12CTL1 &= ~CONSEQ_3;
Danach natürlich wieder aktivieren!

von Christoph (Gast)


Lesenswert?

1
Also noch mal zum mitschreiben :)
2
3
Du machst "Repeat sequence of channels", dann willst du irgendwann einen
4
speziellen AD Eingang wandeln, dazu stoppst du die "Repeat sequence of
5
channels" und wandelst einmal einen Eingang und startest danach  wieder
6
"Repeat sequence of channels"? Richtig?

Nicht ganz :)
Ich bleibe im "Repeat sequence of channels"-Mode.
Also anfangs läuft er frei durch. Dann halte ich ihn durch das 
Rausnehmen von ENC am Ende der Sequenz (Kanal 3) an und lösche das 
Interrupt-Flag für Kanal 0. Dann wird er wieder gestartet und läuft 
weiter im "Repeat sequence of channels"-Mode. Da der ADC nach der 
Unterbrechung bei Kanal 0 anfängt zu sampeln, welchen ich zu diesem 
Zeitpunkt ja haben will, dürfte es schnell genug sein. Durch das Polling 
erkenne ich schlussendlich, wann mein Wert anliegt.

Ich hoffe mal das ich mich jetzt klar ausgedrückt habe. :)

Die Lösung ist aber sicherlich, wie oben auch geschrieben, noch nicht 
optimal.
1
Und bevor ich da
2
weiterbastel, würde ich doch ganz gerne wissen, wieso da diese Hänger
3
auftreten...

von Stefan (Gast)


Lesenswert?

>Dann halte ich ihn durch das
>Rausnehmen von ENC am Ende der Sequenz (Kanal 3) an
Du wartest aber nicht auf die letzte Conversion von Kanal 3 sondern 
startest sofort eine neue Sequenz. Da kommen sich wahrscheinlich zwei 
Sequenzen in die Quere.

Siehe User-Guide Kap ADC12:

"...Resetting ENC during a sequence or repeat-sequence mode stops the
converter at the end of the sequence...
...Any conversion mode may be stopped immediately by setting the
CONSEQx = 0 and resetting ENC bit. Conversion data are unreliable."

"If no EOS bit is set and a sequence mode is selected, resetting the ENC 
bit does not stop the sequence. To stop the sequence, first select a
single-channel mode and then reset ENC."

von Christoph (Gast)


Lesenswert?

>Du wartest aber nicht auf die letzte Conversion von Kanal 3 sondern
>startest sofort eine neue Sequenz. Da kommen sich wahrscheinlich zwei
>Sequenzen in die Quere.

Volltreffer. Oh man und ich saß da stundenlang davor und hab den Fehler 
nicht gesehen. -.-
1
ADC12CTL0 &= 0xfffd; // ENC aus um Konfig zu ändern (stoppt am Ende der Sequenz)
2
ADC12IFG &= 0xfffe;  // Interrupt flag löschen
3
while(ADC12CTL1 & ADC12BUSY);
4
ADC12CTL0 |= ENC + ADC12SC;  //ADC12 wieder starten
5
while( !(ADC12IFG & 0x0001));
6
pt_data.adc = ad_get_int(0);

Jetzt läuft alles wie es soll.

Ist zwar ein bißchen viel Gepolle, aber das stört erstmal nicht. :)

Danke für die Hilfe!

Gruß, Christoph

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.