Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum

Re: CRC Berechnung von Temp.Sensor DS18B20 Kategorie: Programmierung C (von Ernst H. - 27.02.2011 19:10)
Als Antwort auf Re: CRC Berechnung von Temp.Sensor DS18B20 von Joerg - 27.02.2011 17:56
Ich nutze:
C-Control Pro Mega128, CC-Pro 128 Application Board, Pro-Bot128
> > > > // Beispielprogramm um den DS18S20 Temperatur Sensor von Dallas Maxim zu lesen
> > > > // mit Berechnung der  CRC Prüfsumme  -  bei Fehler extra Zeile
> > > > char Text[40];
> > > > int ret,Heiz,i,Secure;
> > > > int temp, Heiztemp;
> > > > byte rom_code[8];
> > > > byte scratch_pad[9];      //'9ehemals
> > > > byte Serienschutz[8];
> > > > char Fehler;
> > > > byte CRC_Wert;
> > > > #define One_Wire_Port  35   //'e3,   hier das Port für den Sensor
> > > >
> > > >
> > > >
> > > >
> > > > void main(void)
> > > > {
> > > >  do
> > > >    {
> > > >     ret = OneWire_Reset(One_Wire_Port);
> > > >     if (ret == 0)
> > > >         {
> > > >         Text= "Kein Sensor gefunden";
> > > >         Msg_WriteText(Text);
> > > >         goto Ende;
> > > >         }
> > > >     // Ã?ndern der Konfiguration (Default 12 Bit) nun 9 Bit
> > > >     // OneWire_Write(0xcc)   ' ROM überspringen Kommando
> > > >     OneWire_Write(0x4e);   // Master issues Write Scratchpad command
> > > >     OneWire_Write(0x7F);   // Master sends three data bytes to scratchpad ..TH
> > > >     OneWire_Write(0xFF);   // sicherheitshalber niedrigste Temp in Tl  .....TL
> > > >     // OneWire_Write(0b00011111) // für 9 Bit     und config Bitanzahl ..9-12
> > > >     // OneWire_Write(0b00111111) // für 10 Bit
> > > >     // OneWire_Write(0b01011111) // für 11 Bit
> > > >     OneWire_Write(0b01111111); // für 12 Bit
> > > >     ret = OneWire_Reset(One_Wire_Port); // #define One_Wire_Po
> > > >     if (ret == 0)
> > > >         {
> > > >         Text= "Kein Sensor gefunden";
> > > >         Msg_WriteText(Text);
> > > >         goto Ende;
> > > >         }
> > > >     OneWire_Write(0xcc);   //' ROM überspringen Kommando
> > > >     OneWire_Write(0x44);   //' starte Temperatur Messung Kommando
> > > >
> > > >     AbsDelay(1000);
> > > >
> > > >     OneWire_Reset(One_Wire_Port);   //   ' PortA.7
> > > >     OneWire_Write(0xcc);   //' ROM überspringen Kommando
> > > >     OneWire_Write(0xbe);   //' lese scratch_pad Kommando
> > > >     for (i=0; i<9; i++)        //' komplettes scratchpad lesen
> > > >         {
> > > >         scratch_pad[i]= OneWire_Read();
> > > >         Msg_WriteText(" " );
> > > >         Msg_WriteWord(i );
> > > >         Msg_WriteText(":=" );
> > > >         Msg_WriteHex(scratch_pad[i]);
> > > >         }
> > > >         //'SCRATCHPAD (Power-up State)
> > > >         //'byte 0 Temperature LSB (50h)
> > > >         //'byte 1 Temperature MSB (05h) EEPROM
> > > >         //'byte 2 TH Register or User Byte 1* TH Register or User Byte 1
> > > >         //'byte 3 TL Register or User Byte 2* TL Register or User Byte 2
> > > >         //'byte 4 Configuration Register* Configuration Register
> > > >         //'byte 5 Reserved (FFh)
> > > >         //'byte 6 Reserved (0Ch)
> > > >         //'byte 7 Reserved (10h)
> > > >         //'byte 8 CRC*
> > > >     Msg_WriteText(" crc=" );
> > > >     CRC_Wert=CRC_8();
> > > >     Msg_WriteHex(CRC_Wert);     //Berechnete CRC ausgeben
> > > >     Fehler = CRC_Wert - scratch_pad[8];
> > > >     if (Fehler == 0) Msg_WriteText(" ok" );
> > > >     else
> > > >       {
> > > >         Msg_WriteChar(13);
> > > >         Msg_WriteText(" Fehler=" );
> > > >         Msg_WriteInt(Fehler);
> > > >       }
> > > >     Msg_WriteChar(13);
> > > >     Text = "Temperatur: ";
> > > >     Msg_WriteText(Text);
> > > >     temp = scratch_pad[1] * 256 + scratch_pad[0];
> > > >     Msg_WriteFloat(temp /16.0);       //'hier das Komma wichtig .. für 12Bit
> > > >                                      //'mit DS1822
> > > >     Msg_WriteChar(99);
> > > >     Msg_WriteText(" Dez=" );
> > > >     Msg_WriteWord(scratch_pad[0] );
> > > >     Msg_WriteChar(13);
> > > >
> > > >   }
> > > >   while(1);
> > > >
> > > >     Ende:   // Label Ende
> > > >
> > > > }
> > > >
> > > >
> > > >
> > > > byte CRC_8(void)
> > > > {
> > > >     int Schleifen_count;
> > > >     byte Pruf_Byte, CRC, Bit_Count, Wert_Bit;
> > > >     CRC = 0;
> > > >     for (Schleifen_count = 0; Schleifen_count < 8; Schleifen_count++)
> > > >     {                      // die 8 Byte werden berechnet (0-7)
> > > >         Bit_Count = 8;
> > > >         Pruf_Byte = scratch_pad[Schleifen_count];
> > > >         do
> > > >         {                 // jedes Bit wird extra hinzuberechnet
> > > >             Wert_Bit = (CRC ^ Pruf_Byte) & 0x01;
> > > >             if ( Wert_Bit == 0x01 ) CRC = CRC ^ 0X18; // 0X18= X^8+X^5+X^4+X^0
> > > >             CRC = 0x7F & (CRC >> 1);
> > > >             if ( Wert_Bit == 0x01 ) CRC = CRC | 0x80;
> > > >             Bit_Count--;
> > > >             Pruf_Byte = Pruf_Byte >> 1;
> > > >         } while (Bit_Count > 0);
> > > >     }
> > > >     return CRC;
> > > > }

> > >
> > > Hallo,
> > >
> > > ich hatte auch erst diese Variante realisiert. Sie braucht nur sehr viel Rechenzeit.
> > > Ich habe mich dann für die Tabellenversion entschieden.
> > > Da ich die Tabelle mit 'flash'  abgelegt habe, benötigt sie auch kein Ram.
> > >
> > > Grü�e Joerg
> > Hallo Joerg!
> > Die Rechenzeit stört mich auch, habe 13ms gemessen das ist enorm.
> >
> > Ich habe auch Tests wegen Leitungslänge gemacht - mit einen erstaunlichen Ergebnis:
> > bei ca 10m 4pol Kabel (für RJ12 Telefonstecker) kein crc Felher entdeckt.
> > bei ca 90m (ganze Spule dazwischengeschalten) nur jedes ca 20x ein Fehler.
> > Systembedingt habe ich die 5V direkt am Sensor mit 100 Ohm belastet, nach den 90m ist
> > dann die Versorgungsspannung nur mehr 3,8V  trotzdem nur geringe Probleme!.
> > Zu bemerken ist aber das das Kabel aufgespult und nicht verlegt ist. Angeschlossen ist der
> > Sensor nicht parisitär, also mit 5V Versorgung - aber ohne Pull Up Widerstände.
> > Am Oszi verbessert sich das Impulsverhalten mit 2x   2k2 Pull Up bringt aber nicht viel.
> > (die Pull up Wid. gerhören meiner Ansicht auf beiden Seiten - da einmal der Prozessor auf
> > Low zieht, dann der Sensor)
> > Bei ca 40m Cat 5 verlegten Netzwerkkabel sind die Fehler dann schon häufiger.
> >
> >
> > Ich wäre sehr dankbar wenn Du die Tabellenversion hier Posten würdest - diese 13ms Rechenzeit
> > passt mir nämlich nicht ins Konzept.
> >
> > Vielen Dank!
> > Ernst H.
> >
>
> /*********************************************************************************
>  * Table for CRC calculation
>  ********************************************************************************/
> flash byte crc8_table[256] = {
>     0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
>     157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
>     35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
>     190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
>     70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
>     219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
>     101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
>     248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
>     140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
>     17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
>     175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
>     50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
>     202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
>     87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
>     233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
>     116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
>
>
> byte calculate_table_crc8(byte data[], byte n)
> {
>    byte temp, crc, i, tmp;
>
>    crc = 0;
>    for (i=0; i < n; i++) // loop over all data
>    {
>      tmp = crc^data[i];
> crc = crc8_table[tmp];
>    }
>    return(crc);
> }
>
>
>
> Grü�e Joerg

Hallo Joerg!
Vielen Dank - funktioniert Perfekt!  statt 13ms nur mehr ca 0,9ms - super!.

Fertiges Programm zum Testen und vergleichen:
//' Beispielprogramm um den DS18S20 Temperatur Sensor von Dallas Maxim zu lesen
//' mit Berechnung der  CRC Prüfsumme  -  bei Fehler extra Zeile
//'
//'  Fertiges Programm - einfach kopieren und starten
//'  Sensor an E.3 anschlieÃ?en,  zum messen: C.2 zuerst crc berechnet..ca 13ms,
//'  dann crc mit Tabellenberechnung (von Joerg)  ca 0,9ms !!!
char Text[40];
int ret,Heiz,i,Secure;
int temp, Heiztemp;
byte rom_code[8];
byte scratch_pad[9];      //'9ehemals

char Fehler;
byte CRC_Wert;

#define One_Wire_Port  35   //'e3,   hier das Port für den Sensor


void main(void)
{
  Port_DataDirBit(18,1 );    //'C.2   zum Zeitmessen  als Ausgang
  Port_DataDirBit(19,1 );    //'C.3   zum Zeitmessen  als Ausgang


 do
   {
    ret = OneWire_Reset(One_Wire_Port);
    if (ret == 0)
        {
        Text= "Kein Sensor gefunden";
        Msg_WriteText(Text);
        goto Ende;
        }
    //' Ã?ndern der Konfiguration (Default 12 Bit) nun 9 Bit
    //' OneWire_Write(0xcc)   ' ROM überspringen Kommando
    OneWire_Write(0x4e);   // Master issues Write Scratchpad command
    OneWire_Write(0x7F);   // Master sends three data bytes to scratchpad ..TH
    OneWire_Write(0xFF);   // sicherheitshalber niedrigste Temp in Tl  .....TL
    //' OneWire_Write(0b00011111) // für 9 Bit     und config Bitanzahl ..9-12
    //' OneWire_Write(0b00111111) // für 10 Bit
    //' OneWire_Write(0b01011111) // für 11 Bit
    OneWire_Write(0b01111111); // für 12 Bit
    ret = OneWire_Reset(One_Wire_Port); //' #define One_Wire_Po
    if (ret == 0)
        {
        Text= "Kein Sensor gefunden";
        Msg_WriteText(Text);
        goto Ende;
        }
    OneWire_Write(0xcc);   //' ROM überspringen Kommando
    OneWire_Write(0x44);   //' starte Temperatur Messung Kommando

    AbsDelay(1000);

    OneWire_Reset(One_Wire_Port);   //   ' PortA.7
    OneWire_Write(0xcc);   //' ROM überspringen Kommando
    OneWire_Write(0xbe);   //' lese scratch_pad Kommando
    for (i=0; i<9; i++)        //' komplettes scratchpad lesen
        {
        scratch_pad[i]= OneWire_Read();
        Msg_WriteText(" " );
        Msg_WriteWord(i );
        Msg_WriteText(":=" );
        Msg_WriteHex(scratch_pad[i]);
        }
        //'SCRATCHPAD (Power-up State)
        //'byte 0 Temperature LSB (50h)
        //'byte 1 Temperature MSB (05h) EEPROM
        //'byte 2 TH Register or User Byte 1* TH Register or User Byte 1
        //'byte 3 TL Register or User Byte 2* TL Register or User Byte 2
        //'byte 4 Configuration Register* Configuration Register
        //'byte 5 Reserved (FFh)
        //'byte 6 Reserved (0Ch)
        //'byte 7 Reserved (10h)
        //'byte 8 CRC*
    Msg_WriteText(" crc=" );
    Port_WriteBit(18,1 );       //'C.2   zum Zeitmessen auf High
    CRC_Wert=CRC_8();
    Port_WriteBit(18,0 );       //'C.2   zum Zeitmessen auf Low
    Msg_WriteHex(CRC_Wert);     //'Berechnete CRC ausgeben

    Msg_WriteText(" Tab=" );
    Port_WriteBit(18,1 );      //'C.2   zum Zeitmessen auf High
    CRC_Wert = calculate_table_crc8(scratch_pad,8);
    Port_WriteBit(18,0 );      //'C.2   zum Zeitmessen auf Low
    Msg_WriteHex(CRC_Wert);    //'Berechnete CRC nach Tabelle ausgeben

    Fehler = CRC_Wert - scratch_pad[8];
    if (Fehler == 0) Msg_WriteText(" ok" );
    else
      {
        Msg_WriteChar(13);
        Msg_WriteText(" Fehler=" );
        Msg_WriteInt(Fehler);
      }
    Msg_WriteChar(13);
    Text = "Temperatur: ";
    Msg_WriteText(Text);
    temp = scratch_pad[1] * 256 + scratch_pad[0];
    Msg_WriteFloat(temp /16.0);       //'hier das Komma wichtig .. für 12Bit
                                     //'mit DS1822
    Msg_WriteChar(99);
    Msg_WriteText(" Dez=" );
    Msg_WriteWord(scratch_pad[0] );
    Msg_WriteChar(13);

  }
  while(1);

    Ende:   //' Label Ende

}



byte CRC_8(void)
{
    int Schleifen_count;
    byte Pruf_Byte, CRC, Bit_Count, Wert_Bit;
    CRC = 0;
    for (Schleifen_count = 0; Schleifen_count < 8; Schleifen_count++)
    {                      //' die 8 Byte werden berechnet (0-7)
        Bit_Count = 8;
        Pruf_Byte = scratch_pad[Schleifen_count];
        do
        {                 //' jedes Bit wird extra hinzuberechnet
            Wert_Bit = (CRC ^ Pruf_Byte) & 0x01;
            if ( Wert_Bit == 0x01 ) CRC = CRC ^ 0X18; //' 0X18= X^8+X^5+X^4+X^0
            CRC = 0x7F & (CRC >> 1);
            if ( Wert_Bit == 0x01 ) CRC = CRC | 0x80;
            Bit_Count--;
            Pruf_Byte = Pruf_Byte >> 1;
        } while (Bit_Count > 0);
    }
    return CRC;
}

//'************************************************************************
//' * Table for CRC calculation
//'************************************************************************
flash byte crc8_table[256] = {
    0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
    157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
    35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
    190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
    70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
    219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
    101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
    248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
    140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
    17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
    175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
    50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
    202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
    87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
    233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
    116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};


byte calculate_table_crc8(byte data[], byte n)
{
   byte temp, crc, i, tmp;
   crc = 0;
   for (i=0; i < n; i++) //' loop over all data
   {
     tmp = crc^data[i];
     crc = crc8_table[tmp];
   }
   return(crc);
}





Gruss
Ernst H.


    Antwort schreiben


Antworten: