mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 - ADC


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich versuche mit Hilfe des ADC´s einen Spannungswert digital zu 
erfassen. Es geht ersteinmal darum den Wert in ein Memory-Register des 
ADC zu bekommen.
Ersteinmal etwas zum Aufbau. Mit Hilfe des TimerA wird ein 1ms Interrupt 
ausgelöst. In diesem Interrupt soll ein Spannungswert eingelesen werden. 
Dieser liegt nicht dauerhaft an, sondern wird im TimerA -Interrupt 
eingeschaltet und nach kurzer Zeit wieder ausgeschaltet. In dieser 
Zwischenzeit soll dieser Wert eingelesen werden. Ich bekomme jedoch 
entweder als Ergebnis 0x00 im ADC12MEM1 oder 0xFFF, wobei der Pegel aber 
eigentlich nicht größer als die Referenz ist, sondern minimal ca. 1V 
ist. Selbst bei 1V bekomme ich sehr große Werte, meistens aber immer 
0xFFF

Hier mal Auszüge aus dem Quelltext:

in der main:

ADC12CTL0 = ADC12ON + MSC;          // ADC12 ON
ADC12CTL1 = SHP + CONSEQ_1;         // SAMPCON Source
ADC12MCTL0 = INCH_5 + SREF_0 + EOS;
ADC12CTL0 |= ENC;

in der TimerA-ISR:
(Spannungswert EIN)
ADC12CTL0 |= ADC12SC;
while ((ADC12CTL1 & ADC12BUSY)==1);
(Spannungswert AUS)

Wie zu erkennen benutze ich als Referenz AVcc (3.3V). REFON kann ich 
also auslassen oder?
Da das Einlesen nicht nur einmal sondern immer während des erwähnten 
Zeitraumes passieren soll, habe ich mich für Sequenz of Channels 
entschieden. Durch EOS wird dafür nur ADC12MEM0 verwendet. Hat also den 
selben Effekt, als würde ich Repeat-Singel-Channel für MEM0 verwenden 
oder?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso:

Hat jemand ne Idee was das Problem sein kann? Wie lange benötigt die 
Wandlung ungefähr? Mehr als 1ms darf der ADC nicht benötigen.

Autor: Иван S. (ivan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hast Du die entsprechenden Portpins als analogen Eingang konfiguriert?
Ist SREF_0 auch wirklich richtig definiert?

Iwan

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort


Ja als AD sind sie konfiguriert. Nur vergessen zu posten.

P6SEL = BIT4 + BIT5 + BIT6;

Testweise werden alle 3 Pins ausprobiert. Demzufolge wird dann natürlich 
auch INCH_4, INCH_5 oder INCH_6 gewählt.

Was meinst du mit SREF_0 definiert? Im User-Guide steht da Bereich von 
AVcc bis AVss. Im Stromlaufplan sehe ich an Pin AVcc (100) dass da 3.3V 
angeschlossen sind. Ist da noch etwas zu beachten?

Autor: Иван S. (ivan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin schrieb:
>
> Was meinst du mit SREF_0 definiert? Im User-Guide steht da Bereich von
> AVcc bis AVss.

Anscheinend hat es da mal Probleme gegeben, in CVS steht nämlich für 
adc12.h:
-#define SREF_0 0
+#define SREF_0 (0<<4)

> Im Stromlaufplan sehe ich an Pin AVcc (100) dass da 3.3V
> angeschlossen sind. Ist da noch etwas zu beachten?

Ich wüsste jetzt auf die Schnelle nichts, bin aber ein n00b.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-#define SREF_0 0
+#define SREF_0 (0<<4)
Das sagt mir jetzt nicht so viel. Heißt das für SREF_0 bis SREF_4 gilt 
immer SREF_0 ..?

Autor: Иван S. (ivan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin schrieb:
>
> -#define SREF_0 0
> +#define SREF_0 (0<<4)
> 
> Das sagt mir jetzt nicht so viel. Heißt das für SREF_0 bis SREF_4 gilt
> immer SREF_0 ..?

Noe, das ist ein Schiebeoperator. damit wird SREF_0 binär 000 (glaub' 
ich).

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Egal, wie lange man die 0 hin und her schiebt, sie bleibt 0.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau. Und wenn schon SREF_0 steht für die Referenz AVcc...?
Das löst mein Problem aber immer noch nicht. Komisch ist auch, dass 
manchmal eben ein etwas kleinerer Wert als 0xFFF drin steht. Wenn ich 
dann nochmal resete und wieder ausführe steht wieder oxFFF drin. Die 
Spannung am Pin ist aber eigentlich nicht größer als Referenz.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>in der TimerA-ISR:
>(Spannungswert EIN)
>ADC12CTL0 |= ADC12SC;
>while ((ADC12CTL1 & ADC12BUSY)==1);
>(Spannungswert AUS)

Bist Du Dir sicher, dass Deine zu messende Spannung während des 
Samplings stabil ist oder schwingt die da noch ein/über? Oder hast Du 
einen ausreichenden Delay zwischen Spannung EIN und ADC-Start?

Wo, wann und wie liest Du ADC12MEM0 aus?
Direkt nach
while ((ADC12CTL1 & ADC12BUSY)==1);
steht das neue Ergebnis da noch nicht drin!

>entweder als Ergebnis 0x00 im ADC12MEM1 oder 0xFFF,
Schreibfehler?

Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also nein ich bin mir nicht sicher ob die zu messende Spannung schon 
stabild ist. Sie ist aus dem Überschwingen schon raus, weil ich eine 
Delay-Zeit eingebaut habe. (ich probiers auch mal mit einer etwas 
größeren) Um das von euch genauer beurteilen zu lassen, müsste ich 
weiter ausholen: Ich hab mal ein Bild gepostet. Auflösung 1V bzw.2V. Ich 
denke das ist stabild genug oder? Die Spannungs die dann aber am Pin 
anliegt, ist zwar leicht verzerrter, das sollte aber ausreichend sein.

Ja das unten war ein Schreibfehler.

Zum Auslesen. Wann steht denn dann das Ergebnis im Speicher-Register?
Bis jetzt habe ich es immer so gemacht: Programm starten, irgendwann 
stoppen. Und mit Software mir das Register anschauen. Aber irgendwie 
vermute ich jetzt, dass das ein Fehler ist oder? Weil ich das Programm 
ja immer zu unterschiedlichen Zeiten stoppe. Zufall eben. Mal im 
Interrupt. Mal gerade nach dem Einlesen. Unterschiedlich halt.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Spannungs die dann aber am Pin
>anliegt, ist zwar leicht verzerrter, das sollte aber ausreichend sein.
Jo mei... schaut net so schlimm aus...zumindest nicht nach 0x0FFF ;-)

>Wann steht denn dann das Ergebnis im Speicher-Register?
Wenn das entsprechende ADC12IFGx gesetzt ist.

Ich würde auch mal lieber den single-channel, single-conversion mode 
auswählen, nichts anderes machst Du ja schließlich!
Ob's das allerdings ist...?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich in der main folgendes initialisiere:
ADC12MCTL0 = INCH_5 + SREF_0;                     
ADC12MCTL1 = INCH_6 + SREF_0;
ADC12MCTL2 = INCH_5 + SREF_0;
ADC12MCTL3 = INCH_6 + SREF_0;

und dann die Conversion mit dem ADC12SC-Bit starte. Also 
Single-Conversion. Werden dann alle 4-Register beschrieben, mit den 
entsprechenden Werten? Oder funktioniert das in Single-Conversion so 
nicht?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nee, nur ADC12MEM0 (solange Du nix an CSTARTADDx in ADC12CTL1 verändert 
hast). Aber ich dachte Du sampelst nur einen ?!

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ich teste halt erstmal. Wäre nich schlecht wenn erstmal einfaches 
Wandeln funktonieren würde.

Heißt also, wenn ich das so machen will wie in meinem letzten post, 
müsste ich 4mal ADC12SC setzen und kurz vorher noch einen neuen 
Startpunkt festlegen..?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du denn mal die Code-Beispiele von TI getestet, um sicherzustellen, 
dass der ADC überhaupt seinen Dienst tun? Hast du die Kondensatoren an 
AVCC und VREF dran, wie im Datenblatt angegeben?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und welche Taktquelle verwendest Du für den ADC12? Welcher MSP430 ist es 
genau, den Du benutzt?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, ohne extra Einstellung wird ja die interne Taktquelle des ADC12 
benutzt, die schwabbelt irgendwo bei 5MHz rum...

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich nutze den MSP430FG4619

Zu den TI-C-Beispielen. Ich habe sie mir angeschaut ja. Ich kann sie 
natürlich nciht einzueins übernehmen, weil ich hier mit einer fertigen 
Baugruppe arbeite und aufpassen muss was ich mit den Pins mache. Um 
Fehler auszuschließen hab ich mal mein C-Programm minimiert und nur 
folgendes ausprobiert:
int b1;
void main(void)
{
  
  P6SEL = BIT5;
  
  ADC12CTL0 = ADC12ON + SHT0_0;        
  ADC12CTL1 = SHP;        
  ADC12MCTL0 = INCH_5 + SREF_0;      //Referenz Veref (1.65V), samplingquelle Vcc (ca.3.3V)              
  ADC12CTL0 |= ENC;         
  ADC12CTL0 |= ADC12SC;
  while ((ADC12CTL1 & ADC12BUSY)==1);      
  if ((ADC12IFG & 0x01)==1) b1=ADC12MEM0;
  
  
}

Also im Prinzip das Gleiche. Und siehe da: Es funktioniert. Was mich 
jedoch gewundert hat ist, dass es ebenso funktioniert wenn ich P6.5 
NICHT als a/d Eingang verwende, also P6SEL weglasse.

Umsomehr wundere ich mich, warum es in meinem kompletten Testprogramm 
nicht funktioniert. Liegt es daran, das ich TimerA-Interrupt, DAC und 
ADC benutze? Mögen die sich nicht? Wenn gewünscht kan ich auch mal 
Auszüge aus meinem kompletten Testprogramm posten.

Autor: Stefan (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
>Was mich jedoch gewundert hat ist, dass es ebenso funktioniert
>wenn ich P6.5 NICHT als a/d Eingang verwende, also P6SEL weglasse.
P6SEL schaltet in diesem Fall nicht die ADC12 Funktionalität des Port6 
frei, sondern deaktiviert dessen digitalen Ein-/Ausgangsbuffer. D.h. der 
jeweilige P6-Pin wird zu einen "reinen" analogen Eingang, was parasitäre 
Ströme durch die CMOS-Gates unterbindet (s. User-Guide!)

> while ((ADC12CTL1 & ADC12BUSY)==1);      
> if ((ADC12IFG & 0x01)==1) b1=ADC12MEM0;
einfacher:
while( !(ADC12IFG & ADC12IFG0));  
b1=ADC12MEM0;


>Umsomehr wundere ich mich, warum es in meinem kompletten Testprogramm
>nicht funktioniert. Liegt es daran, das ich TimerA-Interrupt, DAC und
>ADC benutze? Mögen die sich nicht? Wenn gewünscht kan ich auch mal
>Auszüge aus meinem kompletten Testprogramm posten.
Prinzipiell "mögen" die sich schon, wenn man's richtig macht ;-)
Aber ohne Deinen source code im Detail kann man den Fehler darin wohl 
kaum feststellen!

Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
OK, hier isses.Nich erschrecken, soviel isses nicht. Auch fleißig 
kommentiert.

Autor: Martin (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
push

Autor: Stefan (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Der Uhrzeit angemessen nur zwei kurze Hinweise ohne den Code im Detail 
durchgegangen zu sein:

1.)
volatile int i,a,b1,b2;

2.)
Deine ganzen Delays und Warteschleifen in der Timer-ISR könnten zwar 
zeitlich hinkommen, aber eleganter wäre es sicher, den ADC-Meswert in 
einem ADC-Interrupt abuholen und nicht in der Timer ISR-darauf zu 
warten!

Autor: Martin (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Ich glaube ich komme der Ursache auf den Grund.

Was für folgen kann es haben, wenn AVcc merklich von 3.3V abweicht?? Ist 
dieser Wert vorgegeben oder kann ich den Controller mit "jeder" (laut 
Datenblatt) beliebigen Spannung betreiben, ohne das dies Auswirkungen 
auf den Programmabläufe hat?

Autor: Stefan (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
>Ich glaube ich komme der Ursache auf den Grund.
glaub ich nicht ;-)

>Was für folgen kann es haben, wenn AVcc merklich von 3.3V abweicht??
Was ist merklich ?
1V, 5V 10V ...???

>kann ich den Controller mit "jeder" (laut
>Datenblatt) beliebigen Spannung betreiben, ohne das dies Auswirkungen
>auf den Programmabläufe hat?
Na sicher, sonst würd's TI im DB ja nicht so angeben!
Es ist lediglich so, dass Vcc umso größer sein muss, je schneller der 
MSP getaktet wird. Und zum Programmieren muss Du auch eine 
Mindestspannung einhalten, die größer ist als die minimale 
Betriebsspannung.
Steht aber alles im DB

Autor: Martin (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Bis jetzt bin ich davon überzeugt, dass es an einer schlechten 
Kontaktierung des Pins 100 (Avcc) liegt. Da ich die gleiche Baugruppe 
2mal vorliegen habe, bin ich mir dessen sicher. Bei der 2ten tritt 
dieser Fehler nicht auf.

Werde dies mal beheben und weiter berichten. Habs übrigens auch mit dem 
ADC Interrupt ausprobiert- selber Effekt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.