MSP430 - ADC

Gast #1305840
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?
Gast #1305909
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?
#1305916
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:
1
-#define SREF_0 0
2
+#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.
Gast #1306106
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.
Gast #1306127
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
1
while ((ADC12CTL1 & ADC12BUSY)==1);
steht das neue Ergebnis da noch nicht drin!

>entweder als Ergebnis 0x00 im ADC12MEM1 oder 0xFFF,
Schreibfehler?
Gast #1306142
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.
Angehängte Dateien:
Gast #1306168
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...?
Gast #1306594
Lesenswert?

Wenn ich in der main folgendes initialisiere:
1
ADC12MCTL0 = INCH_5 + SREF_0;                     
2
ADC12MCTL1 = INCH_6 + SREF_0;
3
ADC12MCTL2 = INCH_5 + SREF_0;
4
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?
Gast #1306662
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..?
Gast #1307015
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:
1
int b1;
2
void main(void)
3
{
4
  
5
  P6SEL = BIT5;
6
  
7
  ADC12CTL0 = ADC12ON + SHT0_0;        
8
  ADC12CTL1 = SHP;        
9
  ADC12MCTL0 = INCH_5 + SREF_0;      //Referenz Veref (1.65V), samplingquelle Vcc (ca.3.3V)              
10
  ADC12CTL0 |= ENC;         
11
  ADC12CTL0 |= ADC12SC;
12
  while ((ADC12CTL1 & ADC12BUSY)==1);      
13
  if ((ADC12IFG & 0x01)==1) b1=ADC12MEM0;
14
  
15
  
16
}

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.
Gast #1307106
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!)

1
> while ((ADC12CTL1 & ADC12BUSY)==1);      
2
> if ((ADC12IFG & 0x01)==1) b1=ADC12MEM0;
einfacher:
1
while( !(ADC12IFG & ADC12IFG0));  
2
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!
Gast #1311529
Lesenswert?

Der Uhrzeit angemessen nur zwei kurze Hinweise ohne den Code im Detail 
durchgegangen zu sein:

1.)
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!
Gast #1312062
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?
Gast #1312068
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
Gast #1312083
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren