Funktionsaufruf CRC8 mit Pointern ?



  • Hallo ich habe folgendes Problem
    ich wuerde gerne diese Funktion aufrufen in C leider gibt es immer wieder Probleme.

    Ich habe 15 Byte Hexadezimale Werte die eingelesen werden muessen und aus dem ein CRC8 Wert ermittelt werden muss der 1 Byte gross ist.

    BYTE Crc8 (const void *ptr, int len)
    {
    	BYTE *src = (BYTE*)ptr;
    	BYTE crc = 0xc7;
    	int i;
    
    	for (; len > 0; len--, src++) {
    		crc ^= *src;
    		for (i = 0; i < 8; i++) {
    			if(crc & 0x80) {
    				// x**8 + x**4 + x**3 +x**2 + x**0)
    				crc = (crc << 1) ^ 0x1d;
    			}
    			else crc <<=1;
    		}
    	}
    	return (crc);
    }
    

    //Besten Dank !



  • stochi schrieb:

    ich wuerde gerne diese Funktion aufrufen in C leider gibt es immer wieder Probleme.

    Und welche Probleme??



  • was ist CRC8?





  • Die Probleme liegen darin das ich nicht genau weiss wie ich die 15 Byte an die Funktion uebergebe. Und wie ich die Funktion in der Main aufrufe das ich danach ein Byte als Ergebnis herausbekomme. Die Funktion an sich sollte richtig sein. CRC ist Checksumme die bei Kommunikationsverfahren angewendet wird um zu ueberpruefen ob Datenpakete richtig und vollstaendig angekommen sind.

    #include <stdio.h> 
    
    typedef unsigned char BYTE; 
    
    int main(void) 
    { 
        BYTE Crc8(const void *ptr, int len); 
        BYTE l_speicher[14]; 
    
        l_speicher[0]=0x01;      //HEX     
        l_speicher[1]=0x01;      //BCD 
        l_speicher[2]=0x99;      //BCD 
        l_speicher[3]=0x83;      //BCD 
        l_speicher[4]=0x00;      //BCD 
        l_speicher[5]=0x00;      //BCD 
        l_speicher[6]=0x00;      //BCD 
        l_speicher[7]=0x00;      //BCD 
        l_speicher[8]=0x00;      //BCD 
        l_speicher[9]=0x00;      //BCD 
        l_speicher[10]=0x00;     //BCD 
        l_speicher[11]=0x01;     //BCD 
        l_speicher[12]=0x63;     //BCD 
        l_speicher[13]=0xBA;     //HEX 
        l_speicher[14]=0xA7;     //HEX 
    
        printf("%X", Crc8(l_speicher, 15)); //gibt das errechnete Checkbyte als Hexadezimalzahl aus 
    
        getchar(); 
    } 
    
    BYTE Crc8 (const void *ptr, int len) 
    { 
        BYTE *src = (BYTE*)ptr; 
        BYTE crc = 0xc7; 
        int i; 
    
        for (; len > 0; len--, src++) { 
            crc ^= *src; 
            for (i = 0; i < 8; i++) { 
                if(crc & 0x80) { 
                    // x**8 + x**4 + x**3 +x**2 + x**0) 
                    crc = (crc << 1) ^ 0x1d; 
                } 
                else crc <<=1; 
            } 
        } 
        return (crc); 
    }
    


  • c.rackwitz schrieb:

    http://de.wikipedia.org/wiki/Zyklische_Redundanzprüfung

    danke alles klar!



  • ich wuerde die daten als char* oder BYTE* statt void* uebergeben. dann brauchst du den (BYTE*) cast nicht mehr

    es waere vielleicht auch nicht verkehrt, BYTE als unsigned char zu definieren.

    probier mal [cpp] tags. dann sieht man auch die einrueckung und syntaxhighlighting.



  • @stochi
    Wenn du einen cpp-Tag aufmachst, musst du ihn am Ende deines Codes auch wieder schließen 😉 (bei deinem ersten Beitrag hab ich das korrigiert).

    Zum eigentlichen Problem:
    Mir kommt es so vor als hättest du das mit den Datentypen und betimmten Standardfunktionen noch nicht ganz verstanden.

    Nur weil du deine Variable ptr nennst (schätzungsweise pointer), ist es noch kein Zeiger. Da gehört noch ein * dazu:

    unsigned int * ptr;
    

    Dann ist da noch die Typdefinition von BYTE. Ein unsigned int ist je nachdem für welches System du compilierst unterschiedlich groß. Bei 16bit-Systemen (z. B. DOS) ist er 2 Byte groß, bei 32bit-Systemen (z. B. Windows) ist er 4 Byte groß, usw...

    Wenn du wirklich nur 1 Byte willst, dann verwende am besten unsigned char:

    typedef unsigned char BYTE;
    

    Dann kommen wir zur Zuweisung auf den vermeintlichen Zeiger ptr. Hier verwendest du einfache Anführungszeichen ( ' ' ). Diese werden in C(++) allerdings nur verwendet, wenn man einzelne Zeichen verwenden will. So wie du es hier vor hast, solltest du es eh nicht machen.
    Die auskommentierte Variante mit der Variablen speicher[] ist schon besser geeignet.

    Und nun noch zur Verwendung von printf(). Die auskommentierten Varianten hast du richtig angewendet, aber da wo du deine Funktion aufrufst fehlt der Formatstring!

    printf("%X", Crc8(speicher, 14)); //gibt das errechnete Checkbyte als Hexadezimalzahl aus
    

    Ich hoffe jetzt ist es etwas klarer 🙂



  • Besten dank erstmal, aber ich glaube das die 15 Byte nicht richtig eingelesen werden da gibt es wohl noch einen Fehler in der Deklaration oder so ? Ich weiss auch nicht wie ich 15 Byte in die Funktion einlesen kann damit nur 1 Byte als Checksumme heraus kommt



  • stochi schrieb:

    Besten dank erstmal, aber ich glaube das die 15 Byte nicht richtig eingelesen werden da gibt es wohl noch einen Fehler in der Deklaration oder so ? Ich weiss auch nicht wie ich 15 Byte in die Funktion einlesen kann damit nur 1 Byte als Checksumme heraus kommt

    Geh es hald mal mit dem Debugger durch, vielleicht kommst du dann dahinter (ob Fehler oder Verständnisproblem).



  • Danke es war doch ein verstaendnis Problem. Es funktioniert jetzt. Gibt es denn auch eine elegantere moeglichkeit die Bytes in den Speicher zu schreiben ?



  • char *arr[] = {0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d};
    


  • stochi schrieb:

    Gibt es denn auch eine elegantere moeglichkeit die Bytes in den Speicher zu schreiben ?

    Jaein. Kommt drauf an, ob dir diese Variante besser gefällt:

    BYTE speicher[15] = { 0x01, 0x01, 0x99, ..., 0xA7 }; //... steht für die anderen ganzen Zahlen ;)
    

    Du hast übrigens in deinem Code für speicher ein Element zu wenig definiert. Du schreibst 15 Zahlen rein, hast aber eigentlich nur Platz für 14! Zum Glück hast du gleich danach *ptr definiert (und zum Glück hat das Programm den Speicher direkt hintereinander reserviert; aber soviel Glück hat man nicht immer ⚠ ).
    Außerdem sind deine Variablen global. Du solltest sie besser innerhalb von main() definieren und die Definition von *ptr kannst du dir eigentlich ganz sparen, da du es ja nicht verwendest - zumindest nicht die globale Variante -, aber in deiner Funktion Crc8() hast du auch eine Variable (Parameter), die so heißt und so was ist immer gefährlich! Wenn du globale Variablen verwendest, dann achte darauf, dass die Namen eindeutig sind. Vielleicht würde auch eine kleine eigene Namenskonvention weiterhelfen: z. B. globale Variablen immer mit g_ beginnen, lokale mit l_ und Parameter mit p_.



  • Das merkwuerdige ist jetzt nur, das als Ergebnis 4D rauskommen sollte, wie es bei der 1. Source der Fall ist

    wenn ich aber schreibe

    #include <stdio.h> 
    
    typedef unsigned char BYTE; 
    
    int main(void) 
    { 
        BYTE Crc8(const void *ptr, int len); 
        BYTE l_speicher[15]; 
    
        l_speicher[1]=0x01;      //HEX     
        l_speicher[2]=0x01;      //BCD 
        l_speicher[3]=0x99;      //BCD 
        l_speicher[4]=0x83;      //BCD 
        l_speicher[5]=0x00;      //BCD 
        l_speicher[6]=0x00;      //BCD 
        l_speicher[7]=0x00;      //BCD 
        l_speicher[8]=0x00;      //BCD 
        l_speicher[9]=0x00;      //BCD 
        l_speicher[10]=0x00;      //BCD 
        l_speicher[11]=0x00;     //BCD 
        l_speicher[12]=0x01;     //BCD 
        l_speicher[13]=0x63;     //BCD 
        l_speicher[14]=0xBA;     //HEX 
        l_speicher[15]=0xA7;     //HEX 
    
        printf("%X", Crc8(l_speicher, 15)); //gibt das errechnete Checkbyte als Hexadezimalzahl aus 
    
        getchar(); 
    } 
    
    BYTE Crc8 (const void *ptr, int len) 
    { 
        BYTE *src = (BYTE*)ptr; 
        BYTE crc = 0xc7; 
        int i; 
    
        for (; len > 0; len--, src++) { 
            crc ^= *src; 
            for (i = 0; i < 8; i++) { 
                if(crc & 0x80) { 
                    // x**8 + x**4 + x**3 +x**2 + x**0) 
                    crc = (crc << 1) ^ 0x1d; 
                } 
                else crc <<=1; 
            } 
        } 
        return (crc); 
    }
    

    Erhalte ich 30 als Hexadezimales Ergebnis.

    Ich dachte immer die Variablendeklaration faengt immer bei 0 an so das ich bei 15 Werten 14 als Variablen definieren muss.



  • Warum hast du die Array-indizes verkackt? Das 1. Element in einem Array wird immer mit array[0] angesprochen.



  • Das meinte ich naemlich auch das ein Array immer bei 0 anfaengt

    da waere aber noch die frage warum ich den Befehl mit der Laenge 15 aufrufen muss? Das haengt aber mit der Funktion zusammen

    printf("%X", Crc8(l_speicher, 15));
    


  • stochi schrieb:

    da waere aber noch die frage warum ich den Befehl mit der Laenge 15 aufrufen muss?

    Weil dein Array 15 Elemente hat? 🙄



  • @stochi
    Wenn du ein Array definierst, dann musst du die Anzahl angeben (in deinem Fall 15) und wenn du dann auf die einzelnen Elemente zugreifst, dann musst du bei 0 anfangen:

    Index für 1. Element = 0
    Index für letztes (15.) Element = 14


Anmelden zum Antworten