www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SHT75 - CRC Check: Ich finde den Fehler nicht


Autor: Bernhard N. (bernieserver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


ich möchte gerne die vom Sensor bereitgestellten Prüfsummen zum 
Validieren der Daten nutzen. Dazu implementierte ich den CRC 
Algorithmus, der in dieser PDF erklärt wird:

http://www.sensirion.com/en/pdf/product_informatio...

Hier ein Ausschnitt der PDF, der die Vorgehensweise der byteweisen 
Berechnung mittels einer LUT beschreibt:

============

2.4 Bytewise

With this implementation the CRC data is stored in a 256 byte lookup 
table.

Perform the following operations:

1. Initialize the CRC register with the value of the lower nibble of the 
value of the status register (reversed (s0s1s2s3‘0000)). (default 
‘00000000’ = 0)

2. XOR each (transmitted and received) byte with the previous CRC value.
The result is the new byte that you need to calculate the CRC value 
from.

3. Use this value as the index to the table to obtain the new CRC value.

4. Repeat from 2.) until you have passed all bytes through the process.

5. The last byte retrieved from the table is the final CRC value.

6. The CRC value retrieved from the SHTxx must be reversed (bit 0 = bit 
7, bit 1=bit 6 … bit 7 = bit 0) and can then be compared to the final 
CRC value.

=============


Zum Umdrehen der Bitreihenfolge nutze ich ebenso eine LUT.

Nur leider funktioniert das ganze nicht. Es wird seltsamerweise immer 
der Wert 160 ausgelesen. Dies kann aber normal nicht sein, da die 
gleiche Leseroutine wie beim Auslesen der Temperatur genutzt wird. Diese 
liest aber die Temperatur und Feuchte korrekt aus.

Vielleicht habe ich prinzipiell etas nicht verstanden oder übersehe 
dauernd etwas.

Hier mal ein paar Codeausschnitte, der Rest ist in der angehängten 
Datei.
Die Funktion SendeTextUART sendet Statusmeldungen über die serielle 
Schnittstelle.

Dane schonmal im Voraus für die Hilfe.

Gruß

Bernhard N.

====================


Messung und Berechnung des CRC:
void MessungAusfuehren(Messwerte *myMesswerte){

  uint8_t Fehler = 0;
  uint8_t *pChecksumme = 0;
  uint8_t CRC = 0;
  uint8_t CRC_IV = 0b00000000;  // Hinweis: Dieser Initialisierungsvektor (IV) muss dem
                  // Statusregisterinhalt mit umgedrehter Bitfolge entsprechen! 
                  // Also beim Registerinhalt 00000001 muss der IV 10000000 sein.
                  // Standartwert des Registers ist 00000000.


  // Wiederhole die Messung bis keine Fehler aufgetreten sind
  do { 
    Fehler = 0;      
    Verbindungsreset();    
    Fehler += Messung(&myMesswerte->TTicks,pChecksumme,0);    
    // Hier erfolgt die Validierung des Ergebnisse mittels einer CRC Prüfung.
    if (Fehler == 0){
      SwitchOnRelais(0);
      CRC = CalcCRC(MESSE_TEMP,CRC_IV);              // Erstes Bit,  der gesendete Befehl
      CRC = CalcCRC((uint8_t)(myMesswerte->TTicks >> 8 ),CRC);   // Zweites Bit, das MSB vom Messergebnis
      CRC = CalcCRC((uint8_t)(myMesswerte->TTicks / 256),CRC);  // Drittes Bit, das LSB vom Messergebnis
        char text[8];
        char text2[8];
        itoa((int)CRC,text,10);
        itoa((int)*pChecksumme,text2,10);

        _delay_ms(10);
        SendeTextUART(text,sizeof(text));
        _delay_ms(10);
        SendeTextUART("xx",sizeof("xx"));
        _delay_ms(10);
        SendeTextUART(text2,sizeof(text2));
        _delay_ms(10);
        SendeTextUART("xx",sizeof("xx"));

      if (CRC == gInvBitOrder_LUT[*pChecksumme]){ // Nutzung der LUT zum Invertieren der Bitreihenfolge der empfangenen Checksumme
        SwitchOnRelais(1);
      }
        
    }
    

    Fehler += Messung(&myMesswerte->RFTicks,pChecksumme,1);      
    if (Fehler != 0){
      SoftwareReset();
    }
  }
  while (Fehler != 0);

  // Berechnung, Linearisierung und Temperaturkompensation

  BerechneT_RF(myMesswerte);

}



Berechnung der CRC mittels der LUT:
uint8_t CalcCRC(uint8_t x, uint8_t crc){  
  return gCRC_LUT[x ^ crc]; // bitweises XOR
}

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

Senderoutine:



uint8_t SchreibeByte(uint8_t Wert){

  uint8_t i; 
  uint8_t Fehlerwert = 0;  

  cli();

  // Es wird eine Bitmaske (Shifted Bit) erzeugt, mittels der das einzelne Bit auf den Bus geschrieben wird 
  // Es wird das MSB am Anfang geschrieben
  for (i = 0b10000000; i > 0; i /= 2){

    if (i & Wert){    // realisiert bitweise UND - Verknüpfung
      SHT75_DATA_1;  // Wenn 1, dann eine 1 auf den Bus schreiben
    }else{
      SHT75_DATA_0;  // Ansonsten eine 0
    }

    _delay_us(20); // Zeitdauer, in der das gültige Signal vor der Taktflanke anliegen muss
    // Takterzeugung
    SHT75_CLK_1;
    _delay_us(80);
    SHT75_CLK_0;
    _delay_us(60); // Halbe Periodendauer - Setupzeit

  }
  // Jetzt wird die Datenleitung auf Hochohmig geschaltet, damit am Bus gelauscht werden kann.
  SHT75_DATA_1;
  _delay_us(20);
  SHT75_CLK_1;
  _delay_us(20);

  // Jetzt wird das Acknowledge Signal vom Sensor abgeprüft. Bei 0 ist kein Fehler aufgetreten. 
  // Wenn es High blieb war ein Übertragungsfehler aufgetreten.
  Fehlerwert = PINC & (1 << PC6);

  _delay_us(60);
  SHT75_CLK_0;

  sei();  

  _delay_ms(100);

  return Fehlerwert;

}



Empfangsroutine:

uint8_t LeseByte(uint8_t SetAcknowledge){

  cli();

  uint8_t i; 
  uint8_t Eingangsdaten = 0;

  // Setze die Datenleitung auf Hochohmig, damit "gelauscht" werden kann. 
  SHT75_DATA_1; 

  _delay_us(80);

  // Es wird eine Bitmaske (Shifted Bit) erzeugt, mittels der das gelesene Bit in das Byte platziert wird
  // Dabei wird zuerst das MSB gelesen
  for (i = 0b10000000; i > 0; i /= 2){
      
    SHT75_CLK_1;
    // Eine gewisse Zeit nach der steigenden Taktflanke kann das Signal ausgelesen werden.
    // Wenn eine 1 vorliegt wird das Bit der aktuellen Bitmaske mit dem vorherigen Wert ODER - Verknüpft
    _delay_us(16);
    
    if (PINC & (1 << PC6)){
      Eingangsdaten = (Eingangsdaten | i);      
    }
    
    _delay_us(64);
    SHT75_CLK_0;
    _delay_us(80);
        
  }
  
  _delay_us(16);

  // Das Acknowledgesignal wird hier gesetzt (d.h. die Datenleitung auf 0 gezogen ), wenn verlangt
  
  if (SetAcknowledge == 1){ 
    SHT75_DATA_0;
  }

  _delay_us(16);
   SHT75_CLK_1;
  _delay_us(80);
  SHT75_CLK_0;
  _delay_us(16);
  SHT75_DATA_1;// Nach den Acknowledge wird der Datenpin wieder auf hochohmig gesetzt
  _delay_us(144); 

  sei();

  return Eingangsdaten;
}

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du genug Datentelegramme mitschneiden, um einen Software-SHT75 zu 
implementieren? Das würde IMHO die Anzahl der Leute erhöhen, die das 
Problem angehen können, ohne dass sie einen SHT75 haben müssen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.