Forum: Mikrocontroller und Digitale Elektronik MSP430 ADC: Wert wird nicht richtig eingelesen


von Andreas (Gast)


Lesenswert?

Hallo Zusammen,

vielleicht kann mir jemand mit meinem ADC weiterhelfen. Ich habe schon 
viele Beträge durchforstet aber so richtig konnte ich meinem Fehler 
trotzdem nicht auf die schlieche kommen.

Mein Problem ist, dass der ADC mir immer im Register ADC12MEM7 den Wert 
0 ausgibt. Also im Debug Modus ist dieser Wert immer 0. Die Rechnung die 
unten stattfindet betrachte ich zunächst garnicht, sondern ich habe mir 
einen Breakpoint in der Zeile  temp_value    = (Vref/4095)*ADC12MEM6; 
eingefügt und betrachte mir im Debug Modus den Wert von ADC12MEM7.
An dem Pin eine Spannung von 0.1V an, sodass eigentlich ein Wert zu 
erwarten ist.

Hier ist der Code meines ADCs:

P6DIR  = 0x27;
P6SEL |= 0xD8;                     // Current Sensor --> ADC Function
ADC12CTL0 = ADC12ON+SHT0_8+MSC+REFON;
ADC12CTL1 = CSTARTADD_0+SHP+CONSEQ_1;
ADC12MCTL3 = SREF_1+INCH_3;       // wert von p 6.3 landet in ADC12MEM3
ADC12MCTL4 = SREF_1+INCH_4;   // wert von p 6.4 landet in ADC12MEM4
ADC12MCTL6 = SREF_1+INCH_6;   // wert von p 6.6 landet in ADC12MEM5
ADC12MCTL7 = SREF_1+INCH_7+EOS;   // wert von p 6.7  ADC12MEM7
                                         //Sequenz End by EOS


ADC12CTL0 |= ENC;                 // los
ADC12CTL0 |= ADC12SC;             // konvertierung starten
wait(10000);
//   while ((ADC12CTL1 & ADC12BUSY) == 1);
current_LNA  = (Vref*ADC12MEM3)/(4095*24e3/5e3);
current_AMPs = (Vref*ADC12MEM7)/(4095*24e3/5e3);
current_MIXER = (Vref*ADC12MEM4)/(4095*1e3/5e3);
temp_value    = (Vref/4095)*ADC12MEM6;


vielleicht sieht ja jemand direkt was ich falsch mache.
ich weiß im Moment leider erstmal nicht weiter.

Viele Grüße,
Andreas

von Jörg S. (joerg-s)


Lesenswert?

>Mein Problem ist, dass der ADC mir immer im Register ADC12MEM7 den Wert
>0 ausgibt.
Und die anderen Wandlungen funktionieren?

Du setzt ENC nach der Wandlung oder vor einer neuen Wandlung wieder 
zurück? Oder willst du nur einmalig wandeln?

von Fabio S. (codehamster)


Lesenswert?

Also ich mache das so
1
void adc_init(void)
2
{
3
    int16 i;
4
5
    // Enable A/D channel A3 to A7
6
    P6SEL |= BIT3 + BIT4 + BIT5 + BIT6 + BIT7;
7
8
    // Turn on and set up ADC12
9
    ADC12CTL0 = MSC + SHT0_2 + ADC12ON + REF2_5V + REFON;
10
    ADC12CTL1 = CSTARTADD_0 + SHS_0 + SHP + ADC12DIV_0 + ADC12SSEL_3 + CONSEQ_1;
11
12
    // Messung Kanal 3
13
    // EOS = 0 / VR+ = VREF+(2.5V) VR- = AVSS(GND) / INCH = A3
14
    ADC12MCTL0 = SREF_1 + INCH_3;
15
    // Messung Kanal 4
16
    // EOS = 0 / VR+ = VREF+(2.5V) VR- = AVSS(GND) / INCH = A4
17
    ADC12MCTL1 = SREF_1 + INCH_4;
18
    // NTC Temperaturmessung
19
    // EOS = 0 / VR+ = VREF+(2.5V) VR- = AVSS(GND) / INCH = A5
20
    ADC12MCTL2 = SREF_1 + INCH_5;
21
    // Batterienspannungsmessung
22
    // EOS = 0 / VR+ = VREF+(2.5V) VR- = AVSS(GND) / INCH = A6
23
    ADC12MCTL3 = SREF_1 + INCH_6;
24
    // Messung des Motorenstrom
25
    // EOS = 1 / VR+ = VREF+(2.5V) VR- = AVSS(GND) / INCH = A7
26
    ADC12MCTL4 = EOS + SREF_1 + INCH_7;
27
28
    ADC12MEM5 = 0x00;
29
    ADC12MEM6 = 0x00;
30
    ADC12MEM7 = 0x00;
31
    ADC12MEM8 = 0x00;
32
    ADC12MEM9 = 0x00;
33
    ADC12MEM10 = 0x00;
34
    ADC12MEM11 = 0x00;
35
    ADC12MEM12 = 0x00;
36
    ADC12MEM13 = 0x00;
37
    ADC12MEM14 = 0x00;
38
    ADC12MEM15 = 0x00;
39
40
    // Delay for reference start-up
41
    for ( i=0; i<0x3600; i++);
42
43
    // Enable conversions
44
    ADC12CTL0 |= ENC;
45
}

und im Timer_A löse ich alle x ms die Messung aus
1
ADC12CTL0 |= ADC12SC;

von Fabio S. (codehamster)


Lesenswert?

ich würde mal das Initialisieren des AD-Wandlers und das Auslösen der 
Messung in 2 verschiedenen Funktionen machen.

Dann kannst du mal versuchen mehrere Messungen auszulösen. Wenn die 
Messung beendet ist (Funktion)
Kannst du noch eine weitere Funktion erstellen die dann die Register 
ausliest oder du greifst direkt auf das ADC12_MEMx zu.

von Jörg S. (joerg-s)


Lesenswert?

>ADC12CTL0 |= ENC;
Du brauchst noch etwas um ENC wieder zurück zu setzen. Ansonsten geht 
die Zeile
1
   // Turn on and set up ADC12
2
    ADC12CTL0 = MSC + SHT0_2 + ADC12ON + REF2_5V + REFON;
schief, da ENC noch vom letzten Aufruf gesetzt ist.

von Fabio S. (codehamster)


Lesenswert?

Jörg S,

er kann doch ENC stehen lassen, sofern er einmal den AD-Wandler 
initialisiert und danach separat die Messungen startet, oder habe ich 
jetzt einen Knopf in der Leitung?

von Jörg S. (joerg-s)


Lesenswert?

Wenn die ADC Einstellungen immer alle gleich bleiben, dann kann ENC 
stehen bleiben, ja.

von Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

heute konnte ich endlich Eure Anregung genauer testen. Vielen Dank für 
die vielen Antworten!
Also mein Code sieht jetzt so aus:

eine Initalisierungs Fkt., die ich im Hauptprg einmal aufrufe,
1
void init_ADC(void)
2
{
3
int i;
4
ADC12CTL0 = ADC12ON + SHT0_2 + MSC + REFON;
5
ADC12CTL1 = CSTARTADD_0 + SHP + SHS_0 + ADC12DIV_0 + ADC12SSEL_3 + CONSEQ_1;
6
ADC12MCTL0 = SREF_1 + INCH_3;       
7
ADC12MCTL1 = SREF_1 + INCH_4;
8
ADC12MCTL2 = SREF_1 + INCH_6;   
9
ADC12MCTL3 = SREF_1 + INCH_7 + EOS;     
10
11
ADC12MEM4 = 0x00;
12
ADC12MEM5 = 0x00;
13
ADC12MEM6 = 0x00;
14
ADC12MEM7 = 0x00;
15
ADC12MEM8 = 0x00;
16
ADC12MEM9 = 0x00;
17
ADC12MEM10 = 0x00;
18
      ADC12MEM11 = 0x00;
19
      ADC12MEM12 = 0x00;
20
      ADC12MEM13 = 0x00;
21
      ADC12MEM14 = 0x00;
22
      ADC12MEM15 = 0x00;
23
24
for ( i=0; i<0x3600; i++);
25
ADC12CTL0 |= ENC;                   // los
26
}
und eine "Messfkt", die ich immer wieder aufrufe:
1
void current_meas(void)
2
{
3
int i=0;
4
ADC12CTL0 |= ADC12SC;
5
for ( i=0; i<0xFFFF; i++);  
6
 //while ((ADC12CTL1 & ADC12BUSY) == 1);
7
current_LNA   = (Vref*ADC12MEM0)/(4095*(24e3/5e3));           current_AMPs  = (Vref*ADC12MEM3)/(4095*(24e3/5e3));             current_MIXER = (Vref*ADC12MEM1)/(4095*(1e3/5e3));   
8
temp_value   = (Vref/4095)*ADC12MEM2;
9
}
einen Breakpoint habe ich mir bei current_MIXER gesetzt um mir die 
beiden oberen Werte anzuschauen. Ich bekomme zwar Werte für z.B. 
current_AMPs aber dieser ist in den seltens Fällen richtig und in den 
meisten Fällen einfach "0". Kann es sein als wenn das Samplen irgendwie 
nicht lange genug ist? Allerdings liegt am Pin eine Gleichspannung an.
Ein weiteres Phänomen das machenmal auftritt ist der Vector Fehler der 
als Anhang beifefügt ist.

Vielleicht könntet Ihr mir nochmal ein paar Tipps geben?

Viele Dank.
Gruß,
Andreas

von Andreas (Gast)


Lesenswert?

kann es vielleicht sein, dass ich die Messfkt im HP zu schnell wieder 
aufrufe (Endlosschleife)?

von Andreas (Gast)


Lesenswert?

hm also dieses Vector Problem habe ich in den Griff bekommen. Es lag an 
meiner Initialisierung des Oszillators.

ich habe mal ein absolut abgespecke Version aus den Codebeispielen 
verwenden und meine Auslesefkt. auf ein minimum gekürzt:
1
unsigned int current_meas(void)
2
{
3
    ADC12CTL0 |= ADC12SC + ENC;
4
    ADC12CTL0 &= ~ADC12SC;
5
6
    while ((ADC12CTL1 & ADC12BUSY) == 1);
7
    return (ADC12MEM3);

Die Init Fkt. ist wie oben nur die Zeile
1
 
2
ADC12CLT0 |= ENC

habe ich noch gestricken. Seit dem das Vektor problem nicht mehr 
auftritt ist aber mein Rückgabewert nur noch "0".

Im Moment hab ich keine Idee was ich noch versuchen kann.

Hoffe Ihr könnt mir noch einen Tip geben.

Gruß,
Andreas

von Jörg S. (joerg-s)


Lesenswert?

ADC12CTL0 &= ~ADC12SC;
Ist unnötig.

>Seit dem das Vektor problem nicht mehr auftritt ist aber mein
>Rückgabewert nur noch "0".
Bei allen Kanälen?


Bau doch erst mal ne Einkanalmessung. Wenn die funktioniert ist man erst 
mal sicher das es grundlegend funktioniert.

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.