Forum: Mikrocontroller und Digitale Elektronik Berechnungen in C fehlerhaft


von H. D. (lactobacillus)


Lesenswert?

Hallo,
ich versuche ein BMP180 an einem MSP430 mit CCS6 zum Laufen zu bekommen. 
Leider sind die Ergebnisse der Berechnungen völliger Quatsch:

B5 ist definiert als long und abhängig von der Temperatur zur Zeit 3446.
1
long B6;
2
B6 = B5-4000;


B6 = -272302634

von Test (Gast)


Lesenswert?

Womit gestestet ? Womit und wie ausgegeben ? Womit kompiliert ? Womit 
den Wert von b5 geprüft ?

Wie in 99% der fälle wird es anwendungsfehler sein...mit mehr details 
lässt der sich auch finden ;)

von ??? (Gast)


Lesenswert?

Was hat B5 für einen Datentyp ?

von R. F. (rfr)


Lesenswert?

Eine Prise meer source, bitte!

Danke

Robert

von Thomas (Gast)


Lesenswert?

du musst dein B6 als signed deklarieren und ggf. je nach compiler vorher 
b5 auch auf signed umcasten, wenns nicht automatisch passiert

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Thomas schrieb:
> du musst dein B6 als signed deklarieren

long ist signed.

von foobar (Gast)


Lesenswert?

Der Code

unsigned a = 3446;
unsigned b = 4000;
long c = a - b;

würde doch a-b unsigned berechnen und anschließend auf signed long 
casten, oder?

von (prx) A. K. (prx)


Lesenswert?

foobar schrieb:
> würde doch a-b unsigned berechnen und anschließend auf signed long
> casten, oder?

Beim MSP430 ja, aber nicht casten, sondern konvertieren. Nur kommt dabei 
kein -272302634 raus.

von foobar (Gast)


Lesenswert?

auch wieder wahr...

Dann wären vielleicht doch ein etwas umfangreicherer Codeauszug und ein 
paar Infos über die Umgebung hilfreich.

von Dirk B. (dirkb2)


Lesenswert?

-272302634 sind 0xEFC4FDD6
                    0xFDD6 sind -554 Das Ergebnis

Wo kommt der Müll im HighWord her?

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> foobar schrieb:
>> würde doch a-b unsigned berechnen und anschließend auf signed long
>> casten, oder?
>
> Beim MSP430 ja, aber nicht casten, sondern konvertieren. Nur kommt dabei
> kein -272302634 raus.

Allrdings ist dieses Ergebnis in Hex 0xEFC4FDD6

und das unsigned Ergebnis von 3446 - 4000 macht 0xFDD6

Aufffallend ist, dass das Lower-Word übereinstimmt. Da steckt irgendwo 
ein Datentypfehler im nicht gezeigten Code.
Fazt, und man möchte hinzufügen: eigentlich so wie fast immer, zeig 
deinen ganzen Code und nicht nur die 3 Zeilen, die du für relevant 
hältst Denn wenn dort der Fehler wäre, hättest du ihn (normalerweise) 
längst schon selbst gesehen. Hast du aber nicht. Ergo sizt das Problem 
woanders (ausser das es eigentlich vor der Tastatur sitzt)

von (prx) A. K. (prx)


Lesenswert?

Der erzeugte Code wär möglicherweise auch interessant.

von Mark B. (markbrandis)


Lesenswert?

H. D. schrieb:
> B5 ist definiert als long

Mach Dir das Leben leichter (und Deinen Code portabler) mit:

1
#include <stdint.h>

von Olaf (Gast)


Lesenswert?

Hm... welcher Datentyp ist den 4000? .-)

Olaf

von (prx) A. K. (prx)


Lesenswert?

Olaf schrieb:
> Hm... welcher Datentyp ist den 4000? .-)

Wenns oben nicht gelogen ist, dann steht da
   long = long - int
Und das ist völlig harmlos.

von H. D. (lactobacillus)


Lesenswert?

Hier die entsprechenden Funktionen. Bei p kommt mist raus, weshalb ich 
mich auf die Suche gemacht habe.
1
int AC1;
2
int AC2;
3
int AC3;
4
unsigned int AC4;
5
unsigned int AC5;
6
unsigned int AC6;
7
int B1;
8
int B2;
9
int MB;
10
int MC;
11
int MD;
12
13
14
long B5;
15
unsigned long p;
16
17
18
19
void Temp180(void){
20
  unsigned int UT;
21
  long X1;
22
  long X2;
23
24
  UCB0CTL1 = UCSWRST;
25
  UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;      // I2C master mode
26
  UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
27
  UCB0BR0 = 0x29;                          // < 400 kHz
28
  UCB0I2CSA = 0x77;                       // address
29
  UCB0CTL1 &= ~UCSWRST;
30
31
32
  //write start temperature
33
  UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
34
  while (!(IFG2 & UCB0TXIFG));
35
  UCB0TXBUF = 0xF4;
36
  while (!(IFG2 & UCB0TXIFG));
37
  UCB0TXBUF = 0x2E;
38
  while (!(IFG2 & UCB0TXIFG));
39
  UCB0CTL1 = UCSSEL_2 + UCTXSTP;
40
  while (UCB0CTL1 & UCTXSTP);
41
42
  _delay_cycles(80000);//5 ms
43
44
45
  //go to register
46
  UCB0CTL1 = UCSSEL_2 + UCTR + UCTXSTT; // I2C RX, start condition
47
  while (!(IFG2 & UCB0TXIFG));
48
  UCB0TXBUF = 0xF6;
49
  while (!(IFG2 & UCB0TXIFG));
50
51
  //read register
52
  UCB0CTL1 = UCSSEL_2 + UCTXSTT; // I2C RX, start condition
53
  while (!(IFG2 & UCB0RXIFG));
54
  UT = UCB0RXBUF<<8;
55
  while (!(IFG2 & UCB0RXIFG));
56
  UT += UCB0RXBUF;
57
58
59
  UCB0CTL1 = UCSSEL_2 + UCTXSTP;
60
  while (UCB0CTL1 & UCTXSTP);
61
62
  //Temp
63
  X1 = (((long)UT-AC6)*AC5)>>15;
64
65
  //X3 = MC;
66
  X2 = ((long)MC<<11)/(X1+MD);
67
68
  B5 = X1 + X2;
69
70
}
71
72
void Pres180(){
73
  unsigned long UP;
74
  long X1;
75
  long X2;
76
  long X3;
77
  unsigned long X4;
78
  long B3;
79
  unsigned long B4;
80
  long B6;
81
  unsigned long B7;
82
83
84
  UCB0CTL1 = UCSWRST;
85
  UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;      // I2C master mode
86
  UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
87
  UCB0BR0 = 0x29;                          // < 400 kHz
88
  UCB0I2CSA = 0x77;                       // address
89
  UCB0CTL1 &= ~UCSWRST;
90
91
92
  //write start pres
93
  UCB0CTL1 = UCSSEL_2 + UCTR + UCTXSTT; // I2C TX, start condition
94
  while (!(IFG2 & UCB0TXIFG));
95
  UCB0TXBUF = 0xF4;
96
  while (!(IFG2 & UCB0TXIFG));
97
  UCB0TXBUF = 0xF4;
98
  while (!(IFG2 & UCB0TXIFG));
99
  UCB0CTL1 = UCSSEL_2 + UCTXSTP;
100
  while (UCB0CTL1 & UCTXSTP);
101
  _delay_cycles(416000);//26 ms
102
103
  //go to register
104
  UCB0CTL1 = UCSSEL_2 + UCTR + UCTXSTT; // I2C RX, start condition
105
  while (!(IFG2 & UCB0TXIFG));
106
  UCB0TXBUF = 0xF6;
107
  while (!(IFG2 & UCB0TXIFG));
108
109
  //read register
110
  UCB0CTL1 = UCSSEL_2 + UCTXSTT; // I2C RX, start condition
111
  while (!(IFG2 & UCB0RXIFG));
112
  UP = UCB0RXBUF;
113
  //blaa[0] = UCB0RXBUF;
114
  while (!(IFG2 & UCB0RXIFG));
115
  UP = (UP<<8) + UCB0RXBUF;
116
  //blaa[1] = UCB0RXBUF;
117
  while (!(IFG2 & UCB0RXIFG));
118
  UP = (UP<<8) + UCB0RXBUF;
119
  //blaa[2] = UCB0RXBUF;
120
121
  UCB0CTL1 = UCSSEL_2 + UCTXSTP;
122
  while (UCB0CTL1 & UCTXSTP);
123
124
  UP = UP>>5;
125
126
127
128
129
  //Pres
130
  B6 = (signed long)(B5)-4000;
131
  X1 = (((B6*B6)>>12)*B2)>>11;
132
  X2 = (AC2*B6)>>11;
133
  X3 = X1 + X2;
134
  B3 = (((((long)AC1<<2)+X3)<<3)+2)>>2;
135
  X1 = (AC3*B6)>>13;
136
  X2 = (((B6*B6)>>12)*B1)>>16;
137
  X3 = (X1 + X2 + 2)>>4;
138
139
  if ((X3 + 32768) < 0){X4 = ~(X3 + 32767);}
140
  else{X4 = X3 + 32768;}
141
  B4 = (AC4*X4)>>15;
142
  B7 = (UP-B3)*(50000>>3);
143
  if (B7 < 0x80000000){p = (B7<<1)/B4;}
144
  else{p = (B7/B4)<<1;}
145
  X1 = (p>>8)*(p>>8);
146
  X1 = (X1*3038)>>16;
147
  X2 = (7357*p)>>16;
148
  p = p + (X1 - X2 + 3791)<<4;
149
150
151
152
153
}

von B. S. (bestucki)


Lesenswert?

A. K. schrieb:
> long = long - int
> Und das ist völlig harmlos.

Nur wenn man keinen Unterlauf produziert, denn dieser erzeugt 
undefiniertes Verhalten.

von Mark B. (markbrandis)


Lesenswert?

H. D. schrieb:
> Hier die entsprechenden Funktionen. Bei p kommt mist raus, weshalb ich
> mich auf die Suche gemacht habe.

Die Variablennamen sind wirklich zum Abgewöhnen :-(

von Joachim B. (jar)


Lesenswert?

B6 ist long B5 ist long also sollte doch das hier reichen:

B6 = B5-4000L;

ich muss doch nix casten ausser die 4000 als L ong zu benennen.

aber ich kenne nur gcc

von Ludger (Gast)


Lesenswert?

Hallo,

b5 sollte bei 25 Grad einen Wert von 4000 haben. B6 ist mit Vorzeichen, 
und ädert das Vorzeichen bei 25 Grad.

Ludger

von H. D. (lactobacillus)


Lesenswert?

Mark Brandis schrieb:
> Die Variablennamen sind wirklich zum Abgewöhnen :-(

Übernomen aus dem Datasheet ...

Joachim B. schrieb:
> B6 ist long B5 ist long also sollte doch das hier reichen:
>
> B6 = B5-4000L;

keine Wirkung:

B5 = 3324;
--> B6 = -1392181924

von (prx) A. K. (prx)


Lesenswert?

Joachim B. schrieb:
> B6 = B5-4000L;
>
> ich muss doch nix casten ausser die 4000 als L ong zu benennen.

Unnötig. B5 ist schon long, also auch 4000.

von Karl H. (kbuchegg)


Lesenswert?

H. D. schrieb:
> Mark Brandis schrieb:
>> Die Variablennamen sind wirklich zum Abgewöhnen :-(
>
> Übernomen aus dem Datasheet ...
>
> Joachim B. schrieb:
>> B6 ist long B5 ist long also sollte doch das hier reichen:
>>
>> B6 = B5-4000L;
>
> keine Wirkung:
>
> B5 = 3324;
> --> B6 = -1392181924

wo hast du den Wert her?
Machst du eine Ausgabe oder bist du in irgendeinem Debugger?
(Hintergrund: Mit diesen Zahlen sieht das so aus, als ob im High-Word 
Schmutz wäre. Das soll es bei Debuggern schon gegeben haben, dass sie 
mit manchen Datentypen nicht zurecht gekommen sind. Letzten Endes sind 
die tatsächlich in B6 vorhandenen Bytes wichtig.)

von H. D. (lactobacillus)


Lesenswert?

Ich benutze Code Composer Studio 6 und die Werte guck ich mir bei einem 
Breakpoint an.

von Karl H. (kbuchegg)


Lesenswert?

Optimizer eingeschaltet?

von H. D. (lactobacillus)


Lesenswert?

Optimization level: 0 (Register Optimizations)

Speed vs. Size trade-offs: None.

von Karl H. (kbuchegg)


Lesenswert?

Nur um sicher zu gehen.
Kannst du mal ein neues Projekt aufsetzen, in dem tatsächlich nur diese 
Berechnung
1
long B6;
2
B6 = B5-4000;
drinn ist (natürlich mit den entsprechenden Variablen und Datentypen wie 
in deinem Projekt) uns sonst nichts anderes?
Hast du dort dasselbe fehlerhafte Ergebnis?

von Ludger (Gast)


Lesenswert?

Hallo,

ich benutze auch die Funktionen aus dem Datenblatt, auf einem AVR.
Funktioniert tadelos.
Wie sehen denn deine Rohwerte für druck und Temperatur aus ?

Ludger

von Bernd K. (prof7bit)


Lesenswert?

Bist Du sicher dass B5 vorher auch wirklich 3446 war? Wie stellst Du das 
fest? Was ist mit dem left shift bei X2 weiter oben, kommt an der Stelle 
vielleicht der Müll in das high word von B5? Ist B5 überhaupt 
initialisiert, wird Temp180() wirklich vor Pres180() aufgerufen? Und 
zwar auch beim ersten Mal? Fragen über Fragen...

von H. D. (lactobacillus)


Lesenswert?

Karl Heinz schrieb:
> Nur um sicher zu gehen.
> Kannst du mal ein neues Projekt aufsetzen, in dem tatsächlich nur diese
> Berechnung
>
1
> long B6;
2
> B6 = B5-4000;
3
>
> drinn ist (natürlich mit den entsprechenden Variablen und Datentypen wie
> in deinem Projekt) uns sonst nichts anderes?
> Hast du dort dasselbe fehlerhafte Ergebnis?

Geht nicht, weil er das wegoptimiert.


Ergänze ich die Funktion von oben durch:
1
  long T5 = 3333;
2
  long T6;
3
4
  T6 = T5 - 4000;
5
6
  B1 = T6;

T5 = -667;
T6 = 1014431077;

Das Ding will mich doch verarschen!

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.