Forum: Compiler & IDEs Struct Problem.


von Jörg E. (jackfritt)


Lesenswert?

Hallo zusammen, bitte nich steinigen ist mein erster Versuch damit.

Ich habe verschiedene Messwerte die ich in einer Struct ablegen möchte.
Es wird immer HI und LOW byte eingelesen. Den 16 bit wert möchte ich 
dann
in Wert1 speichern und ausgeben wollen.
Ich würde gerne bq2084.V ausgeben wollen aber folgendes geht nicht.
Wert1 = bq2084.V;
Dort gibs nen ../main.c:300: error: incompatible types in assignment

Kann mir jemand helfen ?

Danke...
1
typedef struct {
2
  uint8_t high;
3
  uint8_t low;
4
} be_unint16_t;
5
6
typedef struct {
7
  int8_t high;
8
  int8_t low;
9
} be_int16_t;
10
11
struct
12
  {
13
    be_unint16_t Charge_mA;
14
    be_unint16_t Charge_Voltage;
15
    be_int16_t mA;
16
    be_unint16_t V;
17
    be_unint16_t Temp;
18
    be_unint16_t Full;
19
} bq2084;
20
21
22
23
  uint16_t Wert1=0;
24
  uint8_t i2cMessageBuf[I2C_MESSAGE_BUFFER_MAX_SIZE];
25
  uint8_t Buffer[20];
26
27
  bq2084.V.high=i2cMessageBuf[2];
28
  bq2084.V.low=i2cMessageBuf[1];
29
  //Wert1 = ( (uint16_t) i2cMessageBuf[2] << 8) | i2cMessageBuf[1];
30
  Wert1 = ( (uint16_t) bq2084.V.high << 8) | bq2084.V.low;
31
  //sprintf( Buffer, "Spannung: %u mV", Wert1 );
32
  ultoa ( Wert1,Buffer ,10);
33
  uputs ( Buffer );
34
  uputs ( LINEFEED );
35
  Wert1 = bq2084.V;
36
  ultoa ( Wert1,Buffer,10);
37
  uputs ( Buffer );

von Karl H. (kbuchegg)


Lesenswert?

Jörg Esser schrieb:

> in Wert1 speichern und ausgeben wollen.
> Ich würde gerne bq2084.V ausgeben wollen aber folgendes geht nicht.
> Wert1 = bq2084.V;
> Dort gibs nen ../main.c:300: error: incompatible types in assignment
>
> Kann mir jemand helfen ?

Schaun wir uns die Dinge mal an:

>   Wert1 = bq2084.V;

Welcher Datentyp steht links vom = ?
Da ist die Variable Wert1 und die hat den Datentyp uint16_t

Welcher Datentyp steht rechts vom = ?
Da ist die Variable bq2084.V
bq2084 ist vom Datentyp 'struct anonym' und innerhalb dieser Struct gibt 
es einen Member V, der vom Datentyp be_int16_t (der ein typedef für eine 
struct ist) ist.

Somit steht da, datentypmässig gesehen

  uint16_t = be_int16_t;

Was lässt dich jetzt glauben, die beiden wären zuweisungskompatibel? 
Links vom = steht ein primtiver Datentyp, der für einen 16 Bit Integer 
ohne Vorzeichen steht, rechts vom = steht ein Datentyp der für eine 
komplette Struktur steht.

Du musst mit Datentypen agieren, wie in der Physik mit Einheiten. WEnn 
da zum SChluss rauskommt, dass du eine Formel gebaut hast, in der nach 
AUflösen aller Datentypen rauskommt

     Meter = Sekunden

dann hast du wohl was falsch gemacht. Einziger Unterschied: In C klopft 
dir der Compiler auf die Finger, wenn du versuchst Äpfel mit Birnen zu 
verrechnen.

von Jörg E. (jackfritt)


Lesenswert?

Und wiedermal erkenne ich das Mathe nie meine Stärke war ;)

Für mich ist bq2084.mA ein be_unint16_t und nich bq2084.V
oder übersehe ich was ?
Struct be_unint16_t sind doch 2 mal uint8_t also ein uint16_t oder ?

Ich bin immer noch hilflos ;)

Thx,

Jörg

von Karl H. (kbuchegg)


Lesenswert?

Jörg Esser schrieb:
> Und wiedermal erkenne ich das Mathe nie meine Stärke war ;)

Da gehts nicht um Mathe.
Es geht ganz einfach darum, dass es in einer Programmiersprache wie C 
nicht einfach nur darum geht links und rechts vom = einfach irgendwas 
hinzuschreiben, sondern dass es neben den Variablennamen auch noch 
Datentypen gibt, die zusammenstimmen müssen. So wie ein Stössel zwar in 
ein Loch passt, aber eben nur dann wenn die Stösselform auch zur 
Lochform passt.

> Für mich ist bq2084.mA ein be_unint16_t und nich bq2084.V
> oder übersehe ich was ?
1
struct
2
  {
3
    be_unint16_t Charge_mA;
4
    be_unint16_t Charge_Voltage;
5
    be_int16_t mA;
6
    be_unint16_t V;            <-----------  was steht da als Datentyp?
7
    be_unint16_t Temp;
8
    be_unint16_t Full;
9
} bq2084;

> Struct be_unint16_t sind doch 2 mal uint8_t also ein uint16_t oder ?

Nö.
2 uint8_t sind erst mal nur 2 uint8_t. Nicht mehr und nicht weniger. Das 
du der Meinung bist, die beiden Bytes könnte man zu einem 16-Bit 
Datenytp zusammenfassen, mag schon sein, interessiert aber den Compiler 
nicht. Für den ist eine Struktur, die aus 2 uint8_t besteht noch lange 
nicht dasselbe wie ein uint16_t


(Aber: Man kann Casten. Damit kann man den Compiler immer überstimmen, 
indem man selber das Ruder in die Hand nimmt und die Datentypprüfung für 
eine Operation abschaltet oder überstimmt oder eine Konvertierung in 
Auftrag gibt)

von Oliver (Gast)


Lesenswert?

Jörg Esser schrieb:
> Struct be_unint16_t sind doch 2 mal uint8_t also ein uint16_t oder?

Das beide zufällig oder absichtlich die gleiche Anzahl Bits belegen, 
macht sie noch nicht zuweisungskompatibel.

Karl Heinz Buchegger schrieb:
> Somit steht da, datentypmässig gesehen
>   uint16_t = be_int16_t;

So ist es. Das geht halt nicht.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

> Für mich ist bq2084.mA ein be_unint16_t und nich bq2084.V
> oder übersehe ich was ?

Habs jetzt erst gesehen. Da bin ich wohl bei

  uint16_t = be_int16_t;

in die Falsche Zeile zum Copy&Paste gerutscht. Spielt aber keine Rolle, 
denn am eigentlichen Prolem ändert das ja nichts. Ob be_uint16_t oder 
be_int16_t spielt so gesehen keine Rolle. Beides sind Strukturen und 
ganz sicher keine uint16_t.

von Jörg E. (jackfritt)


Lesenswert?

Gut verstanden. Danke euch erstmal. Muss ich wohl nochmal was lesen und 
lernen.

Kann es sein das man besser die Finger davon läßt damit man portierbar 
bleibt?

Ich will das zwar zur Zeit nur auf einem attiny85 laufen lassen, aber 
wenn
ich den Code mal woanders verwende stehen die Chancen gut das es nicht 
wie vorhergesehen funktioniert. (Prozessor und Compilerabhängig.Casten 
geht überall etc.)

Ich habe eigentlich nur damit angefangen um den Code besser lesbar zu 
machen.
Und eventuell ein wenig komfortabler.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Esser schrieb:
> Gut verstanden. Danke euch erstmal. Muss ich wohl nochmal was lesen und
> lernen.
>
> Kann es sein das man besser die Finger davon läßt damit man portierbar
> bleibt?

Ein weises Wort.
Denn: Wie genau die beiden Bytes in einem 16-Bit int im Speicher 
abgelegt werden (in welcher Reihenfolge), wird von C nicht festgelegt. 
Das entscheidet die Plattform (also im weitesten Sinne der Hersteller, 
der die CPU gebaut hat).

Natürlich gibt es Mittel und Wege, wie man die Operation, so wie du sie 
dir vorstellst, implementieren kann. Eine Möglichkeit, umcasten, wurde 
ja schon genannt.

   Wert1 = *(uint16_t*)&bq2084.V;

Der spingende Punkt ist dann eben: Jetzt bist du in der Pflicht. Der 
Compiler ist aus dem Schneider (wie bei allen Casts). WEnn das auf einer 
Plattform nicht funktioniert (aus welchen Gründen auch immer: wegen 
Padding Bytes, wegen unterschiedlicher Endianess, ....), dann hast du 
Mist gebaut und nicht der Compiler.

Die einzig mögliche tatsächlich portierbare Version hast du ja in deinem 
Programm schon benutzt. Wenn du die nimmst, dann kann dir nie irgendwas 
passieren. Du erkaufst dir das möglicherweise mit ein wenig erhöhter 
Laufzeit, bist dafür aber unabhängig.

> Ich habe eigentlich nur damit angefangen um den Code besser lesbar zu
> machen.
> Und eventuell ein wenig komfortabler.

Tja. Das Mittel dazu führt aber eigentlich immer darüber, dass man sich 
Funktionalität in Funktionen auslagert. Mit solchem klein/klein 
Geplänkel erreicht man nicht sehr viel.
1
struct results
2
{
3
    uint16_t Charge_mA;
4
    uint16_t Charge_Voltage;
5
    sint16_t mA;
6
    uint16_t V;
7
    uint16_t Temp;
8
    uint16_t Full;
9
} bq2084;
10
11
...
12
13
  uint8_t i2cMessageBuf[I2C_MESSAGE_BUFFER_MAX_SIZE];
14
15
  ...
16
17
  bq2084.V = toUint16_t( i2cMessageBuf[0], i2cMessageBuf[1] );
18
  uart_put_u16( bq2084.V );
19
  uart_put_s( "\n" );

Noch übersichtlicher geht dann kaum noch. Und der ganze Kleinkram steckt 
in Funktionen.

von Bernd N. (Gast)


Lesenswert?

Magst du mal den Ganzen Code hereinstellen ? Dann könnte man mal 
drüberfliegen.

von Jörg E. (jackfritt)


Lesenswert?

@all
Vielen Dank fürs erklären und die Entscheidungfindung.

@Bernd
Du kannst ja mal vorbeikommen und es dir anschauen ;)
Der Code is mir noch zu peinlich um ihn vorzuzeigen :)

Zuviele
#if 0
#endif
und
/*
*/
ausserdem total viel
//

Wenns mal fertig is stell ich es wohl hier rein.
Soll nen Lader für Li-Ion Akkus werden, die von einem bq2084
überwacht werden. Das alles mit einem kleinen attiny85 und
Kleinkram drumherum. Gespeist von einem AT Netzteil.

Gruss,

Jörg

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.