MSP430 Sprünge bei Erfassung mit ADC12

OP #833036
Lesenswert?

Hallo,

ich erfasse mit dem MSP430F169 eine Spannung zwischen 0,6 und 2,2V 
(Externe Referenz liegt an eREF+ und VeREF-)
Die Messspannung ist an P6.5 / A5 angelegt

Den gemessenen Wert zwischen 0 und 4095 gebe ich auf einem Display aus, 
bzw betrachte ihn im Debugger.

Bei einer langsamen Änderung der Eingangsspannung kann ich nicht alle 
Werte erfassen, es gibt Sprünge im Messwert.

Hier ein Auszug, welche Messwerte möglich sind.
Diese Werte werden durch langsames erhöhen der Eingangsspannung 
angezeigt.
1571  011000100011
1603  011001000011
1619  011001010011
2051  100000000011
2083  100000100011
2115  100001000011
2131  100001010011
2155  100001101011
2259  100011010011
2339  100100100011

Auch beim Debuggen und beobachten des ADC12MEM0 bekomme ich genau diese 
Werte angezeigt.
Es fällt auf, dass immer die letzten 3 Binärstellen "011" sind.
Ich schaffe es also nicht, irgendeinen Zwischenwert bei den obigen 
Messwerten einzustellen. Dieses Problem zieht sich über den gesamten 
Messbereich hin.




Hier mein Code:
Erst mal die Initialisierung...
1
ADinternInit()  //Grundeinstellung AD-Wandler
2
{
3
    ADC12CTL0 = ADC12ON + SHT0_0 + REFON;   // ADC12ON:ADC in Bereitschaft
4
                                  // REFON zwar eingeschaltet, aber nicht verwendet, da externe Spannung ADC12 anschalten,
5
  ADC12CTL1 = SHP;            // Sampling Timer benutzen  (SHP = Sample-and-hold-pulse) Einstellungen werden automatisch vorgenommen
6
            // -----------------------------
7
            // ADC12MCTL0 steuert ADC12MEM0. Das Conversion-Ergebnis steht im 16Bit-Register ADC12MEM0.
8
            // Die führenden 4 Bit sind "0"
9
  ADC12MCTL0 = SREF_6 + INCH_5;    // SREF_6: Referenzspannung einstellen: Verwendet wird: Extern: VeREF+ und Extern: VeREF-
10
                                   // INCH=Input Channel A0 bis A11. Gewählt: P6.5 = A5
11
  ADC12CTL0 |= ENC;       // jetzt anfangen ...   Enable Conversion muß HIGH sein um zu starten
12

13
}

Hier der Aufruf im Programm:
1
int temperaturmessung()
2
{
3
        extern int ADCkty;                  // Die externe Variable ADCkty verwenden
4
        ADC12CTL0 |= ADC12SC;               // Konvertierung durchfuehren
5
        while ((ADC12IFG & BIT0)==0)        // Wenn das Bit 0 auf 1 geht, dann ist ein Wert in ADC12MEM0 geschrieben worden.
6
        {};                                  //warten....
7
        ADCkty=ADC12MEM0;                   // ADCkty den Wert zuweisen(Bereich von 0 bis 4095)
8
}


Da die Messung zeilich nicht kritisch ist, verwende ich keine 
Interrupts, sondern warte auf den Abschluß der Wandlung.

Was muss ich ändern, damit ich auch ALLE Zwischenwerte angezeigt 
bekomme?

Martin
#833130
Lesenswert?

Ich bezweifle dass du  richtiges Programm angehängt  hast.
Bei
1
  
2
int temperaturmessung()
3
..
fällt dir nämlich Rückgabewert(return) und
Compiler kann so etwas nicht Kompilieren.
1
Diese Werte werden durch langsames erhöhen der Eingangsspannung.
Wie  erhöhst du der Spannung? Mit einem Poti?
Ist "langsam" auch  präzis?
Ich meine, nimm besser einer Spindelpoti oder Trimmer mit 10-20 
Umdrehungen.
Nur so ist "langsam" auch "präzis".
OP #833180
Lesenswert?

@Branko:
Rückgabewert ist nicht nötig, da eine externe Variable beschrieben wird.

Einstellgenauigkeit:
20-fach Spindel-Trimmer im Spannungsteiler, mit dem ich die Spannung in 
< mV-Auflösung einstellen kann.
Das kann auch kein Problem sein, da immer wieder die GLEICHEN Werte 
nicht angezeigt werden.


@Jörg:
Portdefinition:
1
P6SEL = 0x20;
2
P6DIR = 0xDF;
3
P6OUT = 0x00;

@Christian:
Ich verwende ADC12CTL1 = SHP. So sollte doch alles soweit automatisch 
funktionieren? Habe keine schnellen Änderungen im Signal.
OP #833272
Lesenswert?

Stimmt, mein Fehler. Hatte zuvor eine Version mit Rückgabewert, die ich 
aber dann geändert habe. Das int hatte ich vergessen wegzunehmen.

Ich habe jetzt nochmal alles zusammengefasst. Dieses Programm liefert 
genau den gleichen Fehler:

Beim drehen am Poti springt der Wert z.B. von 2051 direkt auf 2083 und 
dann auf 2115

Ich lese am Breakpoint den Wert von ADC12MEM0 in IAR aus.
1
#include  <msp430x16x.h>
2
int ADCkty=0;
3
main()
4
{
5
      WDTCTL = WDTPW + WDTHOLD;   // Stop Watchdogtimer
6
// Port init
7
      P1SEL = 0x00;
8
      P1DIR = 0xF3;
9
      P1OUT = 0x03;
10
      P2SEL = 0x00;
11
      P2DIR = 0xEF;
12
      P2OUT = 0x00;
13
      P3SEL = 0x30;
14
      P3DIR = 0xCF;
15
      P3OUT = 0x00;
16
      P4SEL = 0x00;
17
      P4DIR = 0xFF;
18
      P4OUT = 0x00;
19
      P5SEL = 0x00;
20
      P5DIR = 0xFF;
21
      P5OUT = 0x8C;
22
      P6SEL = 0x20;
23
      P6DIR = 0xDF;
24
      P6OUT = 0x00;
25

26
//AD-Init
27
      ADC12CTL0 = ADC12ON + SHT0_0 + REFON + REF2_5V;   // ADC12ON:ADC in Bereitschaft
28
      ADC12CTL1 = SHP;            // Sampling Timer benutzen  (SHP = Sample-and-hold-pulse) Einstellungen werden automatisch vorgenommen
29
      ADC12MCTL0 = SREF_6 + INCH_5;    // Extern: VeREF+ und Extern: VeREF-   INCH=Input Channel A0 bis A11. Gewählt: P6.5 = A5
30
      ADC12CTL0 |= ENC;       // jetzt anfangen ...   Enable Conversion muß HIGH sein um zu starten
31

32

33
for(;;)
34
  {
35
        ADC12CTL0 |= ADC12SC;               // Konvertierung durchfuehren
36
        while ((ADC12IFG & BIT0)==0)        // Wenn das Bit 0 auf 1 geht, dann ist ein Wert in ADC12MEM0 geschrieben worden.
37
        {};                                  //warten....
38
                                            // Das Ergebnis der Wandlung steht in ADC12MEM0 (rechten 12 Bit)
39
        ADCkty=ADC12MEM0;      //BREAKPOINT             // ADCkty behält immer den ADC-Wert.
40
  }// end for
41

42
} //end main

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