Forum: Mikrocontroller und Digitale Elektronik MSP4030F2013 Poti einlesen


von Opachl (Gast)


Lesenswert?

Hallo ich möchte gerne einen Drehpoti einlesen.

Für meine Schaltung habe ich aber P1.0 bis P1.5 schon verbaut.

Daher wollte ich den Poti an P1.6 bzw P1.7 anschließen. doch irgendwie 
bekomme ich keine Daten.

Ich initialiesiere meine Hardware so :
1
#include "msp430x20x3.h"
2
3
// port 1 configuration11
4
#define P1OUT_INIT      0x20
5
#define P1DIR_INIT      0x1F
6
#define P1REN_INIT      0x20
7
#define P1IES_INIT      0x20
8
#define P1IE_INIT      0x20
9
10
#define WDT_STOP      WDT_PW + WDTHOLD  
11
#define INIT_RSEL      15
12
#define INIT_DCO                        3
13
#define INIT_MOD                        26
14
#define INIT_DCOCTL      (INIT_DCO << 5) + INIT_MOD
15
16
#define TACTL_INIT                      TASSEL1 + MC0
17
#define TACCTL0_INIT                    CCIE
18
#define TIMER_COUNT0                    16000
19
20
#define INIT_BCSCTL1      INIT_RSEL    
21
#define INIT_BCSCTL2                    0
22
#define INIT_BCSCTL3                  0 
23
24
//ADC INIT
25
#define INIT_SD16CTL                    SD16SSEL1
26
#define INIT_SD16INCTL0                 SD16INCH_3
27
#define INIT_SD16CCTL0                  SD16SC + SD16UNI
28
#define INIT_SD16AE                     SD16AE3
29
30
void Init_Mcu (void)
31
{
32
   DCOCTL = INIT_DCOCTL;
33
   BCSCTL1= INIT_BCSCTL1;   
34
   BCSCTL2 = INIT_BCSCTL2;
35
   BCSCTL3 = INIT_BCSCTL3;
36
37
   TACCR0 = TIMER_COUNT0;
38
   TACCTL0 = TACCTL0_INIT;   
39
   TACTL = TACTL_INIT;   
40
   
41
   SD16CTL = INIT_SD16CTL;
42
   SD16INCTL0 = INIT_SD16INCTL0;
43
   SD16CCTL0 =  INIT_SD16CCTL0;
44
   SD16AE = INIT_SD16AE;
45
}
46
47
void Init_Ports (void)
48
{
49
  P1OUT = P1OUT_INIT;
50
  P1REN = P1REN_INIT;
51
  P1DIR = P1DIR_INIT;
52
  P1IES = P1IES_INIT;
53
  P1IFG = 0;
54
  P1IE = P1IE_INIT;
55
}
56
57
void main (void)
58
{
59
      WDTCTL = WDT_STOP;
60
      Init_Ports ();
61
      Init_Mcu ();  
62
      _EINT();
63
64
  while (1)
65
  {
66
           XXXXXXX // Meine Funktionen
67
        }

Wäre nett wenn ihr mir sagen könntet wo hier mein Fehler liegt evt lese 
ich die Daten auch falsch ein.

Der Poti selbst ist an +5V und -5V angeschlossen der Abgreifer liegt 
zurzeit an P1.6.

Ich brauche für meine Funktion eine Dauerkonvertierung da ich mit Hilfe 
des Poti die Geschwindigkeit einer Funktion beinflussen möchte. Die 
Funktion benötigt dazu einen UINT Wert als Übergabe den ich vom poti 
haben wollte.

Es handelt sich um einen F2013 den ich mit IAR programmiere.

Danke schon mal für evt Hilfe ;)
mfg Opachl

von Matze (Gast)


Lesenswert?

Guck dir mal die Beispielprogramme zum Thema "ADC" von TI an, ich kann 
bei dir von der Wandlung nichts finden. oder willst du nur wissen ob der 
Pin HIGH oder LOW ist?

P.S. die Spannung überm Poti zwischen -5 und 5V ist doof, weil der ADC 
seinen Wert zwischen 0V und Vref misst, also wäre die spannung 0 und 5V 
am Poti angebracht.

von Bernd N (Gast)


Lesenswert?

Ich sehe nirgends einen ADC Code. Vermutlich ist dein F2013 eh schon 
abgeraucht denn mehr als 0 - 0.6V geht da nicht an den Eingängen. Auch 
wenn der ADC differenzeingänge hat, so darf ADC- nicht negativ (< 0 
Volt) werden.

von Dennis (Gast)


Lesenswert?

Matze schrieb:
> also wäre die spannung 0 und 5V
> am Poti angebracht

Beachte bitte, dass die maximal zulässige Spannung für den MSP 3.6V 
beträgt!
Die Eingänge dürfen natürlich auch nicht mehr Spannung sehen - auf die 
Clamp-Dioden würde ich mich hier nicht verlassen, da du ab >Vref eh 
nurnoch 0xFFFF bekommst.

Hier mal ein Beispiel aus einem alten Programm:
1
...
2
3
SD16INCTL0 = SD16INCH_2;                  // Setze Multiplexer auf A2 (INCH_6 fuer Temperatursensor)
4
  SD16CTL = SD16REFON + SD16SSEL_1;         // Referenzspannung intern 1V2 + SMCLK
5
  SD16CCTL0 = SD16IE + SD16SNGL + SD16UNI;  // Interrupt + Single Conversion + unipolar
6
7
_BIS_SR(LPM1_bits + GIE);                 // Low-Power-Mode 1 + Globaler Interrupt aktiviert
8
...
9
#pragma vector=SD16_VECTOR                  // ISR nach fertiger Wandlung
10
__interrupt void Wandler (void)
11
{
12
  ergebnis_adc = SD16MEM0;                  // Wandlungsergebnis auslesen
13
...}

So holt sich dein Controller das Ergebnis in der ISR selbst und schiebt 
es in deine Variable. Diese solltest du dann global als volatile 
deklarieren.

von Dennis (Gast)


Lesenswert?

Er hier muss natürlich noch irgendwo auftauchen. Idealerweise dann in 
der ISR, nachdem du das Ergebnis abgeholt hast:
1
SD16CCTL0 |= SD16SC;                  // Starte Wandlung (SC: Start Conversion)

von Dennis (Gast)


Lesenswert?

Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des 
üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe 
das bisher auch nur bei den TI-Examples gesehen.

von Opachl (Gast)


Lesenswert?

Danke schon mal für die viele Anregungen

Bernd N schrieb:
> Ich sehe nirgends einen ADC Code. Vermutlich ist dein F2013 eh schon
> abgeraucht denn mehr als 0 - 0.6V geht da nicht an den Eingängen. Auch
> wenn der ADC differenzeingänge hat, so darf ADC- nicht negativ (< 0
> Volt) werden.

Das war ein Fehler meinerseits die gesamte Schaltung wird über den 
USB-Dongle
ez430-F2013 betrieben dieser hat ja eine Spannungsbegrenzung.

Somit ist der Chip noch vollig i.O.

Dennis schrieb:
> Er hier muss natürlich noch irgendwo auftauchen. Idealerweise dann in
> der ISR, nachdem du das Ergebnis abgeholt hast:SD16CCTL0 |= SD16SC; 
// Starte Wandlung (SC: Start Conversion)


muss das wirklich gemacht werden ? ich habe im ersten beitrag eine 
Continuos mode eingestellt. Und ihm in der Main Routine durch definition 
das erste mal Eingeschaltet.

Dennis schrieb:
> Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des
> üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe
> das bisher auch nur bei den TI-Examples gesehen.

Danke werds in Zukunft mal berücksichtigen bin noch total neu auf im uc 
Bereich

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Opachl schrieb:
> Dennis schrieb:
>> Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des
>> üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe
>> das bisher auch nur bei den TI-Examples gesehen.

Begründung:

> #define INIT_SD16CCTL0  SD16SC + SD16UNI

Wenn man, was beim Testen und Herantasten an eine Funktion geschehen 
kann, versehentlich zweimal den gleichen Ausdruck addiert

> #define INIT_SD16CCTL0  SD16SC + SD16UNI
> ...
> #define INIT_SD16CCTL0_FINALENDLICHGEHTS INIT_SD16CCTL0 + SD16UNI

dann kommen äußerst interessante Nebenwirkungen dabei heraus.

Wenn man hingegen mit OR (|) arbeitet, kann man einzelne Terme sooft 
verwenden wie man will, es ändert am Ergebnis nichts.


> #define INIT_SD16CCTL0  SD16SC | SD16UNI
> ...
> #define INIT_SD16CCTL0_FINALENDLICHGEHTS INIT_SD16CCTL0 | SD16UNI

Nein, das soll natürlich ganz und gar kein Beispiel dafür sein, wie 
man sich an derartige Dinge herantasten soll, auch nicht dafür, wie 
Quelltext auszusehen hat -- allein, es hilft Nebenwirkungen unschädlich 
zu machen.

Gerade beim Testen und Inbetriebnehmen neuer, einem unbekannter 
Hardwaremodule kann es im Eifer des Gefechts passieren, daß da so eine 
Konstante zweimal auftaucht.

von Opachl (Gast)


Lesenswert?

Ich bins nochmal der ADC geht zwar nun allerdings springen die 
Zahlenwerte zufällig hoch und runter.

BSP:
Wenn ich den Poti zb in die Mittelpostition stelle zeigt das ergebniss 
im Debugmodus beim ersten mal FF an danach ohne den Poti zu verstellen 
einen Wert um 400 danach kommt was mit 3000 raus der 3 te wert ist 
meistens wieder FF.

Ich weiß langsam nicht mehr was nicht stimmt. habe die interne Ref 
(1.2v) auch eingeschaltet der poti selbst hat 10k ohm zur sicherheit des 
uc habe ich allerdings zusätzlich 2x widerstände a 10k ohm drangeklemmt 
somit komm ich also auf einen gesamtwert von 30 k ohm.


Hoffe evt auf eine weitere Idee


danke schonmal

von Bernd N (Gast)


Lesenswert?

Der AD Wandler des F2013 ist mit Vorsicht zu genießen. Überlege mal, 
0-0,6 V bei angeblich 16 BIT was für eine "Schrittweite" wirst du da 
wohl herausbekommen ?

Dann einen Blick ins DB in die Rubrik S/N, wären das wirklich 16 BIT 
dann würde dort 96 dB stehen... steht da aber nicht.

Mit entsprechendem Aufwand bekommst du stabile 14 BIT heraus wobei an 
P1.3 ein 100 nF nach GND gehört. Errata nicht vergessen und dann sieht 
die Initialisierung so aus:
1
    #define VREFOUT  BIT3                          // schalte VREF an Ausgang P1.3
2
3
/*
4
    The SD16_A internal reference can be adjusted to operate within the specification by
5
    writing 0x61 to memory location 0xBF. This corrects the temperature coefficient of the
6
    internal reference and centers the typical voltage to 1.20 V.
7
*/
8
    __no_init char SD16_A @0xBF;                   // center 1,2V temp. drift 50ppm/K (Errata, ADC)
9
10
    P1SEL |= VREFOUT;                              // REFOUT 100nF gegen GND
11
12
    SD16_A = 0x61;                                 // center 1,2V temp. drift 50ppm/K (Errata, ADC)
13
14
    SD16CTL = SD16REFON + SD16SSEL_1 + SD16DIV_0;  // VREF=1.2V, fM=SMCLK (SD16CTL=REF+Taktauswahl)
15
    SD16INCTL0 = SD16INCH_2;                       // ADC Eingang zuweisen (SD16INCH_2)
16
    SD16CCTL0 = SD16UNI + SD16OSR_1024;            // OverSamplingRatio=1024, Messeingang=unipolar
17
    SD16AE = SD16AE4;                              // P1.4 A1+, Eingang freigeben, DVSS=AGND
Für die Wandlung machst du dann mal eine Mittelwertbildung über n 
Schleifen.
1
    SD16CCTL0 &= ~SD16IFG;                         // clear ADC Interrupt Flag
2
    SD16CCTL0 |= SD16SC;                           // AD Wandler starten
3
    while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
4
    AvgSum += SD16MEM0;                            // Mittelwert über n Messungen

Kann sein das ich hier andere Eingänge als du verwendet habe, kannst du 
ja wieder an deinen Code anpassen.

OSR mal heraufschrauben und dann wirds schon :-)

von Opachl (Gast)


Lesenswert?

Bernd N schrieb:

>     __no_init char SD16_A @0xBF;                   // center 1,2V temp. >drift 
50ppm/K (Errata, ADC)

Wenn ich das schreibe gibt mir der IAR Compiler einen Fehler aus.

Error[Be009]: memory attributes not allowed on auto variables or 
parameters


Ansonsten sehen meine Inits nun so aus:
1
#define VREFOUT  BIT7                                // schalte VREF an Ausgang P1.7
2
#define INIT_SD16CTL       SD16REFON + SD16SSEL_1 + SD16DIV_0;  
3
#define INIT_SD16INCTL0    SD16INCH_3
4
#define INIT_SD16CCTL0     SD16IE + SD16UNI + SD16OSR_1024;
5
#define INIT_SD16AE        SD16AE6
6
7
//Interrupt Schleife
8
#pragma vector = SD16_VECTOR
9
__interrupt void SD16ISR(void)
10
{
11
   if (SD16MEM0 != 65535)
12
   {     
13
      if(Count != 0)
14
      {
15
         while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
16
         u16_Ergebnis += SD16MEM0;
17
      }
18
      
19
      if(Count == 0) Count = 3;
20
   }
21
}

von Opachl (Gast)


Lesenswert?

Opachl schrieb:
> //Interrupt Schleife
> #pragma vector = SD16_VECTOR
> __interrupt void SD16ISR(void)
> {
>    if (SD16MEM0 != 65535)
>    {
>       if(Count != 0)
>       {
>          while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
>          u16_Ergebnis += SD16MEM0;
>       }
>
>       if(Count == 0) Count = 3;
>    }
> }
Das die neue Variante:
Der Wert springt immer noch sehr heftig leider...

Mir ist weiterhin aufgefallen das der ADC auch nur auf den poti im 
letzten drittel reagiert alle einstellungen kleiner lösen keinen 
Interupt aus.

#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
   if (SD16MEM0 != 65535)
   {
      if(Count1 != 0)
      {
         while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung 
fertig ?
         u16_Ergebnis += SD16MEM0;
         Count1--;
      }

      if(Count1 == 0)
      {
         Count1 = 10;
         u16_Ergebnis_10 = u16_Ergebnis / 10;
         u16_Ergebnis = 0;
      }
   }
}

von Bernd N (Gast)


Lesenswert?

Keine Ahnung was du da machst, versuche es doch erst einmal so wie ich 
es dir gesagt habe. Mittelwert über 512 Werte bilden und dann auf 14 BIT 
herunter:
1
uint16_t getAdcValue (void)
2
{
3
    uint16_t AvgCount = 0;
4
    uint32_t AvgSum = 0;
5
6
    for (AvgCount = 0; AvgCount < 512; AvgCount ++) {
7
        SD16CCTL0 &= ~SD16IFG;                                    // clear ADC Interrupt Flag
8
        SD16CCTL0 |= SD16SC;                                      // AD Wandler starten
9
        while (!(SD16CCTL0 & SD16IFG));                           // AD Wandlung fertig ?
10
        AvgSum += SD16MEM0;                                       // Mittelwert über 512 Messungen
11
    }
12
    return AvgSum >> 11;
13
}

Hast du meine vorhergehenden Erklärungen verstanden ?

Also, 0-0.6V bei 16 BIT = 0,0000091552734375 Volt = 9,1 µV pro Schritt. 
Deine Versorgungsspannung beziehst du über die USB Schnittstelle, was 
glaubst du wie gut die wohl abgeblockt ist ?

Und dann laß mal die ISR weg und mach es mit einer einfachen Schleife 
wie oben gezeigt.

Es wäre hilfreich wenn du mal deinen kompletten Code hier anhängst statt 
die Fragmente. Wie gibst du den Wert aus ? Display, SoftUart... ?

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.