Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage C Funktion


von starter (Gast)


Lesenswert?

Hallo,

ich versuche mit der folgende Funktion das lowByte und das highByte vom 
I2C-Bus in eine Variable einzulesen diese dann zusammenzusetzen und dann 
mit der if Bedingung zu vergleichen. Jetzt weiß ich nicht ob die 
eingelesenen Werte auch wirklich in die Variable geschrieben werden.

Was meint Ihr?
1
void ReadPackVoltage (void)
2
{
3
4
  unsigned int Akkuspannung ,Akkuspannung_Wert1,Akkuspannung_Wert2;
5
6
7
  smb_start_wait(AdresseSlave_1+SMB_WRITE);
8
  smb_write (0x09);
9
  smb_rep_start(AdresseSlave_1+SMB_READ);
10
  Akkuspannung_Wert1 = smb_readAck();
11
  Akkuspannung_Wert2 = smb_readNak();
12
  smb_stop();
13
14
  Akkuspannung = Akkuspannung_Wert1+Akkuspannung_Wert2;
15
16
17
  if(Akkuspannung >= 8000 )
18
  {
19
    PORTB &= ~ (1 << PB2);
20
    
21
  }
22
23
}

von H.Joachim S. (crazyhorse)


Lesenswert?

natürlich nicht.
Das MSB muss vor dem Addieren mit 256 multipliziert werden bzw. 8 x nach 
links geschoben werden.
Ganz ohne Rechnerei: union.

von Peter II (Gast)


Lesenswert?

H.Joachim Seifert schrieb:
> Ganz ohne Rechnerei: union.

nein das auf jeden fall nicht. Der rest ist ok.

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

> Was meint Ihr?

Ich meine, du solltest dir an deinem µC eine Form der Ausgabe 
realisieren. Zb ein LCD oder eine UART.
Dann brauchst du nicht mehr unsere 'Meinungen', sondern der µC sagt dir 
was Sache ist, indem du dir die Zahlenwerte ausgeben lässt.

Im Ernst: Programmentwicklung nach dem Muster 'Stochern im Nebel' ist 
nicht sehr effizient. Irgendeine Form der Ausgabe von Zahlenwerten 
braucht man für ernsthafte SW_Entwicklung praktisch immer. Das gilt um 
so mehr, je unerfahrener man ist.

von starter (Gast)


Lesenswert?

H.Joachim Seifert schrieb:
> natürlich nicht.
> Das MSB muss vor dem Addieren mit 256 multipliziert werden bzw. 8 x nach
> links geschoben werden.
> Ganz ohne Rechnerei: union.

wieso mit 256 multiplizieren mit MSB meinst du das highByte?

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

> wieso mit 256 multiplizieren mit MSB meinst du das highByte?

Weil die 256 auf Byteebene das sind, was für dich die 10 sind, wenn du 
aus den 'Ziffern' 3 und 5 die komplette Zahl 35 zusammensetzen sollst.
1
   3 * 10 + 5  ---> 35
Im Dezimalsystem hast du gerade mal 10 'Ziffern' (mögliche Zustände), 
daher mal 10.
Auf Byte-Ebene hast du 256 verschiedene mögliche Zustände, daher mal 
256. Oder anders ausgedrückt: die Wertigkeit des jeweils nächsthöheren 
Bytes ist um einen Faktor 256 höher.


MSB = Most Significant Byte = HighByte

von starter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> starter schrieb:
>
>> Was meint Ihr?
>
> Ich meine, du solltest dir an deinem µC eine Form der Ausgabe
> realisieren. Zb ein LCD oder eine UART.
> Dann brauchst du nicht mehr unsere 'Meinungen', sondern der µC sagt dir
> was Sache ist, indem du dir die Zahlenwerte ausgeben lässt.
>
> Im Ernst: Programmentwicklung nach dem Muster 'Stochern im Nebel' ist
> nicht sehr effizient. Irgendeine Form der Ausgabe von Zahlenwerten
> braucht man für ernsthafte SW_Entwicklung praktisch immer. Das gilt um
> so mehr, je unerfahrener man ist.

als Ausgabe habe ich leider nur eine Duo LED..

was ja auch für den Test reicht Mir ist halt nicht ganz klar ob man die 
werte über den I2C Bus einfach so in eine Variable ein lesen kann.

Auf dem Ozilloskope passt alles die Werte werden korrekt ausgelesen vom 
slave.

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

> als Ausgabe habe ich leider nur eine Duo LED..


Das ist eher schlecht, um Zahlenwerte zu kontrollieren.


> was ja auch für den Test reicht

Das reicht dir für den Endbenutzer, der das Gerät in Betrieb nimmt. Aber 
für dich als Programmentwickler ist die Situation mehr als 
unbefriedigend.

Wenn du irgendwie kannst, dann sieh zu, dass du irgendeine andere Form 
der Ausgabe FÜR DICH ALS ENTWICKLER in Betrieb nehmen kannst. Die muss 
ja nicht drann bleiben, sondern wird provisorisch angekabelt und wenn 
alles fertig ist, kommt sie wieder weg.
Aber ohne - wie gesagt: Stochern im Nebel. Zumal sich so eine 
Ausgabemöglichkeit innerhalb kürzester Zeit zeitlich gesehen von selbst 
amortisiert.

von Dennis S. (eltio)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Weil die 256 auf Byteebene das sind, was für dich die 10 sind, wenn du
> aus den 'Ziffern' 3 und 5 die komplette Zahl 35 zusammensetzen sollst.
>
1
>    3 * 10 + 5  ---> 35
2
>
> Im Dezimalsystem hast du gerade mal 10 'Ziffern' (mögliche Zustände),
> daher mal 10.
> Auf Byte-Ebene hast du 256 verschiedene mögliche Zustände, daher mal
> 256. Oder anders ausgedrückt: die Wertigkeit des jeweils nächsthöheren
> Bytes ist um einen Faktor 256 höher.

Oder anders gesagt: weil jedes Shiften nach links um eine Stelle den 
Wert verdoppelt. 8 mal shiften entspricht einer Multiplikation mit 256 
und -- wie Karl Heinz Buchegger -- schon gesagt hat "hebt" das Byte an 
die höherwertige Stelle.

Gruß Dennis

von starter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> starter schrieb:
>
>> als Ausgabe habe ich leider nur eine Duo LED..
>
> Das ist eher schlecht, um Zahlenwerte zu kontrollieren.
>
>> was ja auch für den Test reicht
>
> Das reicht dir für den Endbenutzer, der das Gerät in Betrieb nimmt. Aber
> für dich als Programmentwickler ist die Situation mehr als
> unbefriedigend.
>
> Wenn du irgendwie kannst, dann sieh zu, dass du irgendeine andere Form
> der Ausgabe FÜR DICH ALS ENTWICKLER in Betrieb nehmen kannst. Die muss
> ja nicht drann bleiben, sondern wird provisorisch angekabelt und wenn
> alles fertig ist, kommt sie wieder weg.
> Aber ohne - wie gesagt - Stochern im Nebel

okay werde wohl ein Display oder über UART-Converter die Werte an den PC 
übertragen.

Aber vllt kannst du das Vorgehen wie du die Werte aus dem I2C Bus 
grundsätzlich auslesen würdest in eine Variable erläutern.

z.B. habe ich folgendes eingelesen LowByte 01010110 HighByte 00011110 
also
86 & 7680

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

> okay werde wohl ein Display oder über UART-Converter die Werte an den PC
> übertragen.

Wenn du UART hast, passt das.

> Aber vllt kannst du das Vorgehen wie du die Werte aus dem I2C Bus
> grundsätzlich auslesen würdest in eine Variable erläutern.
>

Passt doch so, wie du das hast.

> z.B. habe ich folgendes eingelesen LowByte 01010110 HighByte 00011110
> also
> 86 & 7680

Bitte gewöhn dich drann, dass man auf Byte-Ebene sinnvollerweise in Hex 
arbeitet

01010110  ist hexadezimal 0x56
00011110  ist hexadezimal 0x1E

die beiden Bytes zusammengesetzt sind daher  0x1E56
und das ist dann wiederrum die Dezimalzahl 7766

In Dezimalzahlen zu arbeiten macht dann Sinn, wenn das für dich 
sinnvolle Dezimale-Werte sind oder du die Zahl den Benutzer präsentieren 
musst. Aber zum Arbeiten auf Byte-Ebene ist man mit Hexadezimalzahlen 
besser bedient, eben weil diese Schreibweise genau so gewählt ist, dass 
man im Grunde binär nur ohne die vielen 0-en und 1-en arbeiten kann.


Edit:
mit Arbeiten ist das gedankliche Arbeiten gemeint.
Denn ob Binär- Hexadezimal- oder Dezimal: Es sind alles nur verschiedene 
Schreibweisen für ein und dasselbe: eine Zahl.
Ob man die Anzahl der Sterne in der nächsten Zeile
1
************
als
dezimal 12
hexadezimal 0x0C
oder binär 00001100
anschreibt, ändert nichts daran wieviele Sterne da sind. Diese Menge ist 
immer dieselbe, nur die Schreibweise ist je nach gewähltem Zahlensystem 
eine andere. Welches Zahlensystem man zur 'Programmierarbeit' wählt, 
hängt von den jeweiligen Umständen ab und welches davon das 
zweckmässigste ist. Macht es auf der einen Seite kaum Sinn, eine 
gemessene Temperatur als Hexadezimalzahl auszugeben, so macht es in den 
meisten Fällen auch eher wenig Sinn einen (unspezifizierten) Bytewert 
als Dezimalzahl auszugeben.

von starter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> starter schrieb:
>
>> okay werde wohl ein Display oder über UART-Converter die Werte an den PC
>> übertragen.
>
> Wenn du UART hast, passt das.
>
>> Aber vllt kannst du das Vorgehen wie du die Werte aus dem I2C Bus
>> grundsätzlich auslesen würdest in eine Variable erläutern.
>>
>
> Passt doch so, wie du das hast.
würde es denn rein von der Logik so funktionieren?

void ReadPackVoltage (void)
{

  unsigned int Akkuspannung ,Akkuspannung_Wert1,Akkuspannung_Wert2;


  smb_start_wait(AdresseSlave_1+SMB_WRITE);
  smb_write (0x09);
  smb_rep_start(AdresseSlave_1+SMB_READ);
  Akkuspannung_Wert1 = smb_readAck();
  Akkuspannung_Wert2 = smb_readNak();
  smb_stop();

  Akkuspannung = Akkuspannung_Wert1+Akkuspannung_Wert2;


  if(Akkuspannung >= 0x1964 )
  {
    PORTB &= ~ (1 << PB2);

  }

}
>
>> z.B. habe ich folgendes eingelesen LowByte 01010110 HighByte 00011110
>> also
>> 86 & 7680
>
> Bitte gewöhn dich drann, dass man auf Byte-Ebene sinnvollerweise in Hex
> arbeitet
>
> 01010110  ist hexadezimal 0x56
> 00011110  ist hexadezimal 0x1E
>
> die beiden Bytes zusammengesetzt sind daher  0x1E56
> und das ist dann wiederrum die Dezimalzahl 7766

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

>   Akkuspannung_Wert1 = smb_readAck();
>   Akkuspannung_Wert2 = smb_readNak();
>   smb_stop();
>
>   Akkuspannung = Akkuspannung_Wert1+Akkuspannung_Wert2;

wo sind die 256, von denen die Rede war?

>   if(Akkuspannung >= 0x1964 )

Wenn dir 0x1964 als Zahlenwert was sagt - dann spricht nichts dagegen.
Da man aber wohl Spannungen eher nicht als Hex-Zahlen angibt sondern als 
Dezimalzahlen, die sich möglicherweise aus Grenzwerten ergeben, die ein 
Benutzer vorgibt, würde es wohl mehr Sinn machen, hier in diesem 
konkreten Fall eine Dezimalschreibweise zu benutzen

    if(Akkuspannung >= 6500 )


Dieser Vergleich besagt exakt genau das gleiche, wie die Hex-Zahl. Der 
einzige Unterschied dürfte eher darin liegen, dass dir als Entwickler 
6500 etwas mehr sagt (zb das das 6.500 Volt sind) als dir 0x1964 sagen 
würde.

Aber abgesehen davon, dass du dir selber die Interpretation eines 
Zahlenwertes durch Wahl eines ungeschickten Zahlensystems schwer machen 
kannst, gibt es keinen Unterschied. Denn wie gesagt: Es sind nur 
unterschiedliche Schreibweisen. Das ändert nichts an der Zahl an sich.

von starter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> starter schrieb:
>
>>   Akkuspannung_Wert1 = smb_readAck();
>>   Akkuspannung_Wert2 = smb_readNak();
>>   smb_stop();
>>
>>   Akkuspannung = Akkuspannung_Wert1+Akkuspannung_Wert2;
>
> wo sind die 256, von denen die Rede war?
>
>>   if(Akkuspannung >= 0x1964 )

okay dann haben wir uns missverstanden ich hatte ja vorher auch als 
dezimal zahl den Wert da stehen.
>
> Wenn dir 0x1964 als Zahlenwert was sagt - dann spricht nichts dagegen.
> Da man aber wohl Spannungen eher nicht als Hex-Zahlen angibt sondern als
> Dezimalzahlen, die sich möglicherweise aus Grenzwerten ergeben, die ein
> Benutzer vorgibt, würde es wohl mehr Sinn machen, hier in diesem
> konkreten Fall eine Dezimalschreibweise zu benutzen
>
>     if(Akkuspannung >= 6500 )
>
> Dieser Vergleich besagt exakt genau das gleiche, wie die Hex-Zahl. Der
> einzige UNterschied dürfte eher darin liegen, dass die als Entwickler
> 6500 etwas mehr sagt (zb das das 6.500 Volt sind) als 0x1964.


hier ist die Funktion. Wäre das korrekt?
1
void ReadPackCurrent (void)
2
{
3
4
  unsigned int Akkuspannung ,Akkuspannung_Wert1,Akkuspannung_Wert2;
5
6
7
  smb_start_wait(AdresseSlave_1+SMB_WRITE);
8
  smb_write (0x09);
9
  smb_rep_start(AdresseSlave_1+SMB_READ);
10
  Akkuspannung_Wert1 = smb_readAck();
11
  Akkuspannung_Wert2 = smb_readNak();
12
  smb_stop();
13
14
  Akkuspannung = (Akkuspannung_Wert1+Akkuspannung_Wert2)*256;
15
16
17
  if(Akkuspannung >= 6500)
18
  {
19
    PORTB &= ~ (1 << PB2);
20
    
21
  }
22
23
}

Vllt. noch mal ganz kurz was ich mit der Funktion vorhabe. Diese soll 
einen Spannungswert über den I2C-Bus einlesen dann wollte ich die 2 
Bytes die eingelesen wurden zusammensetzen und mit der if-Bedingung 
Vergleichen wenn wahr dann soll die LED ausgehen.

Hast du dan vllt eine einfachere Alternative?


Vielen Dank für dein Bemühen!

von Peter II (Gast)


Lesenswert?

starter schrieb:
> Akkuspannung = (Akkuspannung_Wert1+Akkuspannung_Wert2)*256;

auch nicht besser - du hast also nicht nicht verstanden was es damit 
aufsich hat.

Wie machst du denn aus einen 2 und einer 3 eine 23? Wie würdest du das 
rechnen?

von Karl H. (kbuchegg)


Lesenswert?

starter schrieb:

>   Akkuspannung = (Akkuspannung_Wert1+Akkuspannung_Wert2)*256;

Du ratest jetzt nur noch rum.

Wie war das:
Um aus den 'Ziffern' 3 und 5 die Zahl 35 zusammenzusetzen 
(Dezimalsystem), musstest du rechnen
1
   3 * 10   +    5      ----> 35

du hast nicht gerechnet
1
   3 + 5
denn das ergibt 8
Und du hast auch nicht gerechnet
1
  ( 3 + 5 ) * 10
denn das ergibt 80.

Alles nicht richtig. Die Ziffern 3 und 5 setzen sich zur Zahl 35 
zusammen, indem man rechnet 3*10 + 5. 3 ist sozusagen die höherwertige 
Stelle und 5 die niederwertige.

Bei dir ist der Faktor nicht 10 sondern 256. Und deine beiden 'Stellen' 
stehen in 2 Variablen, wobei jeder der 'Stellen' Werte von 0 bis 255 
annehmen kann.

Also muss es wie heißen?

von Bronco (Gast)


Lesenswert?

starter schrieb:
>   Akkuspannung = (Akkuspannung_Wert1+Akkuspannung_Wert2)*256;

Gegenfrage:
35 = (3 + 5) * 10
Stimmt das?

von Heinz (Gast)


Lesenswert?

Nein, das stimmt leider nicht, denn
(3 + 5) = 8
und wenn man das ganze dann multiplizert also,
8*10 = 80
und somit nicht 35.

mfg, Heinz

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Offtopic: Karl Heinz, du musst mir irgendwann verraten, wo du deine 
Geduld her hast. ich bräuchte davon so 1%...

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.