Forum: Mikrocontroller und Digitale Elektronik MSP430F2616: ADC12 - Interne Temperatur messen


von DegreeC (Gast)


Lesenswert?

Hallo!

Ich habe vor mir einen MSP430F2616 liegen. Hier möchte ich gern die 
interne Temperatur messen.

In den Codebeispielen habe ich diesen Code gefunden:
1
//******************************************************************************
2
//  MSP430x26x Demo - ADC12, Sample A10 Temp and Convert to oC and oF
3
//
4
//  Description: A single sample is made on A10 with reference to internal
5
//  1.5V Vref. Software sets ADC12SC to start sample and conversion - ADC12SC
6
//  automatically cleared at EOC. ADC12 internal oscillator times sample
7
//  and conversion. In Mainloop MSP430 waits in LPM0 to save power until
8
//  ADC10 conversion complete, ADC12_ISR will force exit from any LPMx in
9
//  Mainloop on reti.
10
//  ACLK = n/a, MCLK = SMCLK = default DCO ~ 1.045MHz, ADC12CLK = ADC12OSC
11
// 
12
//  Uncalibrated temperature measured from device to devive will vary do to
13
//  slope and offset variance from device to device - please see datasheet.
14
//
15
//             MSP430F261x/241x
16
//             -----------------
17
//         /|\|              XIN|-
18
//          | |                 |
19
//          --|RST          XOUT|-
20
//            |                 |
21
//            |A10              |
22
//
23
//  B. Nisarga
24
//  Texas Instruments Inc.
25
//  September 2007
26
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
27
//******************************************************************************
28
29
#include  <msp430x26x.h>
30
31
int long temp;
32
int long IntDegF;
33
int long IntDegC;
34
35
void main(void)
36
{
37
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
38
  ADC12CTL0 = SHT0_8 + REFON + ADC12ON;     // Internal ref = 1.5V
39
  ADC12CTL1 = SHP;                          // enable sample timer
40
  ADC12MCTL0 = SREF_1 + INCH_10;            // ADC i/p ch A10 = temp sense i/p
41
  ADC12IE = 0x001;                          // ADC_IFG upon conv result-ADCMEMO
42
  ADC12CTL0 |= ENC;
43
44
  while(1)
45
  {
46
    ADC12CTL0 |= ADC12SC;                   // Sampling and conversion start
47
    _BIS_SR(CPUOFF + GIE);                  // LPM0 with interrupts enabled
48
49
//  oF = ((x/4096)*1500mV)-923mV)*1/1.97mV = x*761/4096 - 468
50
//  IntDegF = (ADC12MEM0 - 2519)* 761/4096
51
    IntDegF = (temp - 2519) * 761;
52
    IntDegF = IntDegF / 4096;
53
54
//  oC = ((x/4096)*1500mV)-986mV)*1/3.55mV = x*423/4096 - 278
55
//  IntDegC = (ADC12MEM0 - 2692)* 423/4096
56
    IntDegC = (temp - 2692) * 423;
57
    IntDegC = IntDegC / 4096;
58
59
    _NOP();                                 // << SET BREAKPOINT HERE
60
  }
61
}
62
63
#pragma vector=ADC12_VECTOR
64
__interrupt void ADC12ISR (void)
65
{
66
    temp = ADC12MEM0;                       // Move results, IFG is cleared
67
    _BIC_SR_IRQ(CPUOFF);                    // Clear CPUOFF bit from 0(SR)
68
}

Bei Raumtemperatur liefert mir der ADC immer 0x0B3D, was nach der 
Berechnung für °C eine "0x03" ergibt.

Was mache ich falsch?

Gruß
DegreeC

von Hannes H. (mui)


Lesenswert?

wenn man 0xB3D in obige Formel für °C einsetzt, erhalte ich 
19°C...Klammer beachtet? :-)

von Jürgen M. (Gast)


Lesenswert?

0xB3D hex -> 2877 dec

IntDegC = ((2877 - 2692) * 423)/4096  = 19.105°C, da Interger also
19°C.

von DegreeC (Gast)


Lesenswert?

Hannes H. schrieb:
> Klammer beachtet? :-)

Hallo!

Was heißt Klammer beachtet. Hab doch den Code 1:1 übernommen.
Also wenn diese Gleichung
1
IntDegC = (ADC12MEM0 - 2692)* 423/4096
stimmt (Rundungsfehler jetzt mal nicht betrachtet), dann steht hier das 
gleiche:
1
IntDegC = (temp - 2692) * 423;
2
IntDegC = IntDegC / 4096;

Nur hier
1
((x/4096)*1500mV)-986mV)*1/3.55mV
 hat der Programmierer einen Klammerfehler...

Gruß
DegreeC

von DegreeC (Gast)


Lesenswert?

Äh... das hat irgendwas mit dem Datentyp zu tun!
Habe mir ein typedef für die Temperatur und das Sampleergebnis gemacht.

Beim Sampleergebnis (temp) habe ich das "long" vergessen. Irgendwie 
konnte er damit nicht rechnen. Bin drauf gekommen, als ich das 
Sampleergebnis auf einen festen Wert eingestellt habe.
Bei 0x0B45 kam, 0x03EE7 statt 0x13EE7 raus. Bei 0x0B46 kam, 0x0408E 
statt 0x1408E raus...

Wenn Copy&Paste, dann richtig... ;)

Aber eigentlich sollte ja ein 16bit-Integer für den 12Bit-ADC 
ausreichen, oder?

von Johnny B. (johnnyb)


Lesenswert?

DegreeC schrieb:
> Aber eigentlich sollte ja ein 16bit-Integer für den 12Bit-ADC
> ausreichen, oder?

Für den Wert vom ADC reicht er ja auch, aber wenn Du diesen Wert noch 
multiplizierst eben nicht mehr...

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.