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


von Bernhard N. (bernieserver)


Angehängte Dateien:

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_information/CRC_Calculation_Humidity_Sensor_E.pdf

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:
1
void MessungAusfuehren(Messwerte *myMesswerte){
2
3
  uint8_t Fehler = 0;
4
  uint8_t *pChecksumme = 0;
5
  uint8_t CRC = 0;
6
  uint8_t CRC_IV = 0b00000000;  // Hinweis: Dieser Initialisierungsvektor (IV) muss dem
7
                  // Statusregisterinhalt mit umgedrehter Bitfolge entsprechen! 
8
                  // Also beim Registerinhalt 00000001 muss der IV 10000000 sein.
9
                  // Standartwert des Registers ist 00000000.
10
11
12
  // Wiederhole die Messung bis keine Fehler aufgetreten sind
13
  do { 
14
    Fehler = 0;      
15
    Verbindungsreset();    
16
    Fehler += Messung(&myMesswerte->TTicks,pChecksumme,0);    
17
    // Hier erfolgt die Validierung des Ergebnisse mittels einer CRC Prüfung.
18
    if (Fehler == 0){
19
      SwitchOnRelais(0);
20
      CRC = CalcCRC(MESSE_TEMP,CRC_IV);              // Erstes Bit,  der gesendete Befehl
21
      CRC = CalcCRC((uint8_t)(myMesswerte->TTicks >> 8 ),CRC);   // Zweites Bit, das MSB vom Messergebnis
22
      CRC = CalcCRC((uint8_t)(myMesswerte->TTicks / 256),CRC);  // Drittes Bit, das LSB vom Messergebnis
23
        char text[8];
24
        char text2[8];
25
        itoa((int)CRC,text,10);
26
        itoa((int)*pChecksumme,text2,10);
27
28
        _delay_ms(10);
29
        SendeTextUART(text,sizeof(text));
30
        _delay_ms(10);
31
        SendeTextUART("xx",sizeof("xx"));
32
        _delay_ms(10);
33
        SendeTextUART(text2,sizeof(text2));
34
        _delay_ms(10);
35
        SendeTextUART("xx",sizeof("xx"));
36
37
      if (CRC == gInvBitOrder_LUT[*pChecksumme]){ // Nutzung der LUT zum Invertieren der Bitreihenfolge der empfangenen Checksumme
38
        SwitchOnRelais(1);
39
      }
40
        
41
    }
42
    
43
44
    Fehler += Messung(&myMesswerte->RFTicks,pChecksumme,1);      
45
    if (Fehler != 0){
46
      SoftwareReset();
47
    }
48
  }
49
  while (Fehler != 0);
50
51
  // Berechnung, Linearisierung und Temperaturkompensation
52
53
  BerechneT_RF(myMesswerte);
54
55
}


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

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

1
uint8_t SchreibeByte(uint8_t Wert){
2
3
  uint8_t i; 
4
  uint8_t Fehlerwert = 0;  
5
6
  cli();
7
8
  // Es wird eine Bitmaske (Shifted Bit) erzeugt, mittels der das einzelne Bit auf den Bus geschrieben wird 
9
  // Es wird das MSB am Anfang geschrieben
10
  for (i = 0b10000000; i > 0; i /= 2){
11
12
    if (i & Wert){    // realisiert bitweise UND - Verknüpfung
13
      SHT75_DATA_1;  // Wenn 1, dann eine 1 auf den Bus schreiben
14
    }else{
15
      SHT75_DATA_0;  // Ansonsten eine 0
16
    }
17
18
    _delay_us(20); // Zeitdauer, in der das gültige Signal vor der Taktflanke anliegen muss
19
    // Takterzeugung
20
    SHT75_CLK_1;
21
    _delay_us(80);
22
    SHT75_CLK_0;
23
    _delay_us(60); // Halbe Periodendauer - Setupzeit
24
25
  }
26
  // Jetzt wird die Datenleitung auf Hochohmig geschaltet, damit am Bus gelauscht werden kann.
27
  SHT75_DATA_1;
28
  _delay_us(20);
29
  SHT75_CLK_1;
30
  _delay_us(20);
31
32
  // Jetzt wird das Acknowledge Signal vom Sensor abgeprüft. Bei 0 ist kein Fehler aufgetreten. 
33
  // Wenn es High blieb war ein Übertragungsfehler aufgetreten.
34
  Fehlerwert = PINC & (1 << PC6);
35
36
  _delay_us(60);
37
  SHT75_CLK_0;
38
39
  sei();  
40
41
  _delay_ms(100);
42
43
  return Fehlerwert;
44
45
}


Empfangsroutine:
1
uint8_t LeseByte(uint8_t SetAcknowledge){
2
3
  cli();
4
5
  uint8_t i; 
6
  uint8_t Eingangsdaten = 0;
7
8
  // Setze die Datenleitung auf Hochohmig, damit "gelauscht" werden kann. 
9
  SHT75_DATA_1; 
10
11
  _delay_us(80);
12
13
  // Es wird eine Bitmaske (Shifted Bit) erzeugt, mittels der das gelesene Bit in das Byte platziert wird
14
  // Dabei wird zuerst das MSB gelesen
15
  for (i = 0b10000000; i > 0; i /= 2){
16
      
17
    SHT75_CLK_1;
18
    // Eine gewisse Zeit nach der steigenden Taktflanke kann das Signal ausgelesen werden.
19
    // Wenn eine 1 vorliegt wird das Bit der aktuellen Bitmaske mit dem vorherigen Wert ODER - Verknüpft
20
    _delay_us(16);
21
    
22
    if (PINC & (1 << PC6)){
23
      Eingangsdaten = (Eingangsdaten | i);      
24
    }
25
    
26
    _delay_us(64);
27
    SHT75_CLK_0;
28
    _delay_us(80);
29
        
30
  }
31
  
32
  _delay_us(16);
33
34
  // Das Acknowledgesignal wird hier gesetzt (d.h. die Datenleitung auf 0 gezogen ), wenn verlangt
35
  
36
  if (SetAcknowledge == 1){ 
37
    SHT75_DATA_0;
38
  }
39
40
  _delay_us(16);
41
   SHT75_CLK_1;
42
  _delay_us(80);
43
  SHT75_CLK_0;
44
  _delay_us(16);
45
  SHT75_DATA_1;// Nach den Acknowledge wird der Datenpin wieder auf hochohmig gesetzt
46
  _delay_us(144); 
47
48
  sei();
49
50
  return Eingangsdaten;
51
}

von Stefan B. (Gast)


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.

von (prx) A. K. (prx)


Lesenswert?


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.