Meter Bus in C

Gast #2780544
Lesenswert?

Haha, ich habs schon gemacht und schon sehr oft gesehen... Ich muss aber 
sagen das die meisten Implementationen einfach nur zum spastischem 
stoßweisen hochwürgens des Mageninhalts sind... Einfach nur grausam wenn 
man damit schaffen muss

Die physikalische Umsetzung lief über OptoLink(IR), RS232-TTL und 
natürlich dem MBus Standard selbst.

Lena, hättest Du Deine Frage hier schon offengelegt hätte ich mich gerne 
direkt daran versucht sie zu beantworten.
#2832846
Lesenswert?

lena schrieb:

>
1
long long long_long_decode(u8 *data, int length){
2
>   int i;
3
>   long long result;
4
>   result = 0;
5
> 
6
>   for(i = length; i > 0; i--){
7
>     result = (result << 8) + data[i-1];
8
>   }
9
>   return result;
10
> }


Wenn man die mal analysiert, dann stellt sich raus, dass sie so 
arbeitet.

Da hat man also zb die ominösen 8 Byte im Array

   aa bb cc dd ee ff gg hh       (jeder Buchstabe ist eine Hex-Ziffer)

Was macht die Funtkion damit?
Nun, zentrales Element ist die for Schleife. DIe würde in diesem Fall 8 
mal durchlaufen werden, wobei i von oben herunter in RIchtung 0 zählt. 
Also. i nimmt nacheinander die Zahlen 8, 7, 6, 5, 4, 3, 2, 1 an (und 
natürlich 0, aber dann bricht die Schleife ab)

Was macht der Schleifenkörper mit dem i.

    data[i-1]

Aha. Er nimmt also das i-1 te Byte aus dem Array. Warum -1? Logisch, 
weil i ja bei 8 anfängt und der letzte INdex in einem Array mit 8 
Elementen ist nun mal 7. Bei den vorgegebenen 8 Bytes wäre data[i-1] 
also das hier

   aa bb cc dd ee ff gg hh
                        **

so weit so gut. Was passiert damit?

  (result << 8) + data[i-1]

zu diesem Byte wird noch was dazugezählt. Da result im Moment noch 0 ist

   result = 0;

und man eine 0 nach links verschieben kann sooft man will, da kommt 
trotzdem 0 raus, bleibt es also bei diesem Byte. Was passiert weite?

   result = (result << 8) + data[i-1];

das wird also result zugewiesen. die 8 Bytes von result sehen also so 
aus

   00 00 00 00 00 00 00 hh

Damit ist dieser Schleifendurchlauf fertig und die Schleife beginnt von 
vorne, diesmal mit einem Wert von 7 für i.

Was passiert

  data[i-1]

da i den Wert 7 hat, ist das also das Byte mit dem Index 6 aus dem 
Array. Also das hier

   aa bb cc dd ee ff gg hh
                     **

Was pssiert in

  (result << 8) + data[i-1]

Nun, zunächst mal  result << 8.
der Inhalt von result wird also um 8 Bits nach links geschoben, was 
effektiv einer Verschiebung aller Bytes von result um 1 Byte nach links 
entspricht. result verändert sich also zu

   00 00 00 00 00 00 hh 00

und dazu wird dann noch

  (result << 8) + data[i-1]

data[i-1] dazugezählt, von dem wir schon wissen, dass es das Byte gg aus 
dem Array war. Das Endergebnis ist also

   00 00 00 00 00 00 hh gg

und das wird dann wieder an result

   result = (result << 8) + data[i-1];

zugewiesen.

Das wars für diesen Schleifendurchlauf, der nächste Durchlauf beginnt, 
diesmal hat i den Wert 6.

data[i-1] ist daher                            aa bb cc dd ee ff gg hh
                                                              **
result um 8 Bits nach links geschoben ergibt   00 00 00 00 00 hh gg 00
und da dann die ff von data[i-1] addiert       00 00 00 00 00 hh gg ff
was wiederrum in result abgelegt wird.

Nächster Durchlauf: i ist jetzt 5

data[i-1] ist daher                            aa bb cc dd ee ff gg hh
                                                           **
result um 8 Bits nach links geschoben ergibt   00 00 00 00 hh gg ff 00
und da dann die ee von data[i-1] addiert       00 00 00 00 hh gg ff ee
was wiederrum in result abgelegt wird.

Nächster Durchlauf: i ist jetzt 4


Und ich glaub den Rest kann ich mir sparen. Man sieht schon, nach 
welchem Muster sich der long long aus den Bytes das Arrays 
zusammensetzt. Im Endergebnis stehen die 8 Bytes aus dem Array so im 
long long

das war das Array                       aa bb cc dd ee ff gg hh
und so sehen die Bytes in result aus    hh gg ff ee dd cc bb aa


Damit ist klargestellt, WIE denn die Dekodierung arbeitet.
Und damit kommst du ins Spiel. Du brauchst jetzt die Umkehrung. Also: 
Was hast du zu tun, damit sich die 8 Bytes eines long long so in das 
Array einpassen, damit nach der Dekodierung wieder alles richtig 
rauskommt?
Gast #2832901
Lesenswert?

lena schrieb:
> wäre diese Codierung dann in Ordnung?unsigned long long long_long_encode(u8 
*data, int length, unsigned long long value){
>
>   int i;
>
>   for(i = 0; i < length; i++){
>
>     data[i] = (value >> (i*8)) & 0xFF;
>
>   }
>
>   return 0;
>
> }

Ist dein Debugger kaputt?

Wenn du implemntiert hast, musst du ja offensichtlich deine 
Anforderungen kennen. Wenn du diese kennst kann es doch kein Problem 
sein, einen möglichen Test zu schreiben.
#2832975
Lesenswert?

lena schrieb:
> wäre diese Codierung dann in Ordnung?

Warum probierst du es nicht einfach aus? Da das eine die Umkehrung vom 
anderen ist, drängt es sich doch geradezu auf, da ein Testprogramm zu 
machen, welches das ausnutzt. Einmal Codeieren, das Ergebnis Decodieren 
und dann muss am Ende wieder dasselbe rauskommen:

int main()
{
  u8 tmp[8];
  long long val1;
  long long val2;

  for( val1 = 0; val1 < 5000000; val1++ ) {
    long_long_encode( tmp, 8, val1 );
    val2 = long_long_decode(tmp, 8 );

    if( val1 != val2 )
      printf( "Fehler" );
  }
}

setz dein Funktionen ein, ergänze sonst noch was du brauchst um das 
compilierbar zu bekommen, teste vielleicht auch noch andere 
Zahlenbereiche und wenn das Testprogramm "Fehler" meldet, dann weißt du 
dass auf jeden Fall erst mal ein Fehler enthalten ist. Vergiss auch 
nicht darauf, dass ein long long auch negativ sein kann!

Eine gute Frage ist zb die Frage: Wenn ich tatsächliche alle Zahlen, die 
mit einem long long möglich sind, da druchschleuse, schafft mein PC das, 
wenn er die Nacht durcharbeiten kann?

Wenn das aus Rechenzeitgründen nicht geht, was wären denn gute 
Zahlenbereiche, die man durchtesten kann, so dass man davon ausgehen 
kann dass wenn die funktionieren, das dann auch die nicht getesteten 
Zahlenbereich funktionieren werden?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren