Sensirion CRC


Closed Thread
Results 1 to 4 of 4

Thread: Sensirion CRC

  1. #1
    Join Date
    Jan 2004
    Location
    Grand Lake O' Cherokees USA
    Posts
    15

    Default Sensirion CRC

    Three different routines to calculate the Sensirion CRC as used in their temperature/humidity sensors.

    Code:
    Sensirion CRC
    'Choose one of the following CRC routines.  The table based one is the fastest
    'but requires a large table in memory.  The assembly language one is slower but
    'doesn't require much memory.  The PBP one is the slowest.  
    'The assembly language one was written with the PIC18 instruction set.  If used
    'on earlier PICs the rotate instruction will need to be changed accordingly.
    
    'Make sure to initialize SHTCRC before calling the routine for the first time.
    'Place the data to be crc'd in SHTRxCRC and call the routine.  CRC will be
    'accumulated in SHTCRC unless reset externally from the routine.
    
    'PIC18F252
    
    SHTCRC          var byte    'accumulative CRC, usually initialize to zero before
                                'calling CRC routine for first time - used by
                                'all routines
    SHTRxCRC        var byte    'data to be added to CRC total - used by all
                                'routines
    SHTCRCBitNo     var byte    'internal to Sht_CRC_Basic, Sht_CRC_AL
    SHTTestByte     var byte    'internal to Sht_CRC_AL
    SHTCRCTestBit   var bit     'internal to Sht_CRC_Basic, Sht_CRC_AL 
    
    Sht_CRC_Basic:
    ' This code confirmed operational 12/30/03
    ' PBP version should work with all PIC series
        For shtCRCbitno = 0 to 7        'Do for all 8 bits
            Shtcrctestbit = shtcrc.7 ^ shtrxcrc.7 'XOR msb
            shtrxcrc = shtrxcrc << 1    'Position received byte for next test
            IF shtcrctestbit = 0 Then Sht_No_XOR 'If tested bits same, skip 
            shtcrc = shtcrc ^ $18       'Else, invert bits 4,5 
    Sht_No_XOR:
            ShtCRC = shtcrc << 1        'Shift the CRC byte
            ShtCrc.0 = shtcrctestbit    'And set its bit 0 to the xor'd value
                                        'after shift this would be bit 8 position
            Next shtCRCbitno
        Return
    
    
    Sht_CRC_Table:
    ' This code confirmed operational 12/29/03
    ' For PIC18 series, table may be too long for previous PIC series
        Shtrxcrc = shtrxcrc ^ shtcrc
        Lookup shtrxcrc, [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,253,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], shtcrc
        Return
        
    ' ********** Subroutine Sht_CRC_AL **********
    ' This code confirmed operational 12/31/03
    ' Uses PIC18 Instruction Set
    ASM
    _Sht_CRC_AL                 ; SHTxx CRC (a reflected CRC from Dallas 1wire)
        MOVLW   8
        MOVWF   _ShtCRCBitNo    ; Do this for all 8 bits of CRCByte
    CRCLOOP
        MOVF    _ShtCRC,0       ; Put CRC into W
        XORWF   _ShtRxCRC,0     ; XOR CRC with CRCData
        MOVWF   _ShtTestByte    ; Put results in TestByte
        RLCF    _ShtTestByte,1  ; Shift TestByte.7 into Carry bit
        BTFSS   STATUS,C        ; If Carry = 1, do polynomial math
        GOTO    CRCSHIFT        ; Otherwise just shift CRC and CRCByte
        MOVF    _ShtCRC,0       ; Get latest copy of CRC
        XORLW   0x18            ; Polynomial math
        MOVWF   _ShtCRC         ; Keep a copy of results
    CRCSHIFT
        RLCF    _ShtCRC,1       ; Rotate CRC into carry
        RLCF    _ShtRxCRC,1     ; Rotate CRCData, carry shifts in but not important
        DECFSZ  _ShtCRCBitNo,1  ; Keep track of #times through loop
        GOTO    CRCLOOP         ; Go to start if not looped through the 8 bits
        RETURN                  ; Return if all 8 bits analyzed
    ENDASM
    Tom

  2. #2


    Did you find this post helpful? Yes | No

    Default

    This is the code I use for calculating the CRC from the Dallas 18B20 temperature sensor. The only difference I can notice is the locations of the << and >> in the two code. Can you give me an example of how your code is used cause I'm still a little fuzzy on what data does where. I know the CRC value byte is the third byte but not sure what bytes are used to calculate the CRC to compare to this value.

    Code:
    ------------------------ Calculate the CRC from Byte 9 ------------------------
    
    GetCRC:
        for x = 0 to 7
        databyte = dq[x]
        gosub CalcCRC
        next x
        if dq[8] <> crccalc then
            sensorerror = 1
            else
            sensorerror = 0
        endif
        crccalc = 0                
        return
    
    '--------------------- CRC Bit Calcuation Method -------------------------------
    
    CalcCRC:
        for i = 0 to 7
        databit = crccalc.0 ^ databyte.0
        databyte = databyte >> 1
        if databit = 0 then Shift
        crccalc = crccalc ^ $18
    
    shift:
        crccalc = crccalc >> 1
        crccalc.7 = databit
        next i
        return
    Code:
    '------------------ Read SHT71 Temperature / Humidity Sensor -------------------
    
    ReadSHT71:
        gosub Initialize
        Sensorcmd = ReadTemp
        gosub readsensor
        if result => 4000 then
            tempC = result - 4000
            SignC = 160
            else
            tempC = 4000 - result
            SignC = "-"
        endif
        gosub ConvertToKelvin    
        gosub ConvertToFahrenheit
        gosub Initialize
        Sensorcmd = ReadHumidity
        gosub readsensor
    
    '--------------------- Calculate Relative Humidity -----------------------------
    
        w = result * 405
        w = div32 100
        x = result * result
        x = div32 1000
        x = x * 28
        x = div32 100
        RHLinear = w - x - 400
    
    '---------- Calculate Relative Humidity with Temperature Compensation ----------
    
        w = (8 * result + 1000) / 10
        if SignC = 160 then
            if tempC > 2500 then
                x = (tempC - 2500) * w
                x = div32 100
                RHTempComp = RHLinear + x / 100
                else
                x = (2500 - temp) * w
                x = div32 100
                RHTempComp = RHLinear - x / 100
            endif
            else
            x = (2500 + tempC) * w
            x = div32 10000
            RHTempComp = RHLinear - x
        endif
        sleep 1
        return
    
    '---------------------------- Initialize the Sensor ----------------------------
    
    Initialize:
        high DataPin
        low clk
        for i = 1 to 10
            high clk
            pause 1
            low clk
            pause 1
        next i
        call TransferStart
        return
    
    '---------------------------- Get Data from Sensor -----------------------------
    
    ReadSensor:
        gosub TransferStart
        gosub WaitSensor
        shiftout DataPin,clk,1,[Sensorcmd\8]        ' Send command byte
        input DataPin                               ' Wait for acknowledge
        low clk
        while DataPin = 1
        wend
        pulsout clk,10                              ' Send acknowledge
        while DataPin = 0
        wend
        while DataPin = 1                           ' Wait for conversion to complete
        wend
        low clk
        shiftin DataPin,clk,0,[result.byte1\8]      ' Get the first byte, 8 bits
        low DataPin
        pulsout clk,10                              ' Send acknowledge
        shiftin DataPin,clk,0,[result.byte0\8]      ' Get the second byte, 8 bits
        low DataPin
        pulsout clk,10                              ' Send acknowledge
        shiftin DataPin,clk,0,[crc\8]               ' Get third byte, 8 bits, CRC
        high DataPin
        pulsout clk,10                              ' Send acknowledge
        input DataPin                               ' End of Transmission
        input clk
        return
    
    '---------------------------- Start Transfer -----------------------------------
    
    TransferStart:
        high clk
        pause 1
        low DataPin
        pause 1
        low clk
        pause 1
        high clk
        pause 1
        high DataPin
        pause 1
        low clk
        return
    
    '---------------------------- Wait for Sensor ----------------------------------
    
    WaitSensor:
        result = 4096
    
    Loop:
        result = result - 1
        if DataPin && result.bit11 then Loop
        return
        
    '-------------------------- Convert to Kelvin ----------------------------------
    
    ConvertToKelvin:
    	if signC = "-" then
        	tempk = 27315 - temp
            else
        	tempk = temp + 27315
      	endif
      	return
      	
    ConvertToFahrenheit:
        if SignC = 160 then
            SignF = 160
            dummy = TempC * 18
            TempF = div32 10
            TempF = TempF + 3200
            else
            TempF = (tempc + 5000) * 900
            TempF = DIV32 500
            if TempC => 1778 and SignC = "-" then
                TempF = TempF - 12200
                SignF = "-"
                else				
                TempF = 12200 - TempF
                SignF = 160
        	endif    
        endif
    	return

  3. #3
    Join Date
    Jan 2004
    Location
    Grand Lake O' Cherokees USA
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    There isn't much difference between the Sensirion and 1wire CRC calculations. The Sensirion tests Bit 7 of the data and does a left shift for the next test bit whereas the 1wire version tests Bit 0 and does a right shift. They both use the same polynomial.

    If you haven't downloaded Sensirion's CRC application note, you need to do that. In there it states the CRC covers the whole transmission (command and response bytes) without the acknowledge bits.

    The CRC is initialized to the low 4 bits of the STATUS register. If you have not changed the STATUS register it defaults to zero meaning you should initialize SHTCRC to zero. If you have changed the status register then you need to read the application note carefully to see how to initialize SHTCRC (it has to be reversed).

    Then send your command byte and the two received bytes to the CRC routine via variable SHTRxCRC. After receiving the CRC byte from the device it must be reversed. In PBP you can do this: Reversed_CRC = Received_CRC REV 8. Now compare Reversed_CRC and SHTCRC. They should be equal if the transmission was OK.

    That's it....
    Tom

  4. #4


    Did you find this post helpful? Yes | No

    Default

    Thank you very much for all your help Tom. Without your assistance I would still be out in the dark. Getting more familiar with this CRC checking thing as I go. This is my final code to do the CRC check. I simply compare CRC to CRCCalc and look for the match.

    Code:
    '--------- Calculate the CRC from Command Byte and Received Bytes --------------
    
    GetSHTCRC:
        CRCCalc = 0                
        DataByte = SensorCmd
        gosub CalcSHTCRC
        DataByte = SensorData.byte1
        gosub CalcSHTCRC
        databyte = SensorData.Byte0
        gosub CalcSHTCRC
        CRC = CRC REV 8
        return
    
    '--------------------- CRC Bit Calcuation Method -------------------------------
    
    CalcSHTCRC:
        for i = 0 to 7
        DataBit = CRCCcalc.7 ^ DataByte.7
        DataByte = DataByte << 1
        if DataBit = 0 then ShiftSHT
        CRCCcalc = CRCCcalc ^ $18
    
    ShiftSHT:
        CRCCcalc = CRCCcalc << 1
        CRCCcalc.0 = DataBit
        next i
        return

Similar Threads

  1. Dallas CRC8 Routines
    By Tom Estes in forum Code Examples
    Replies: 23
    Last Post: - 8th May 2018, 19:07
  2. Calculating CRC for Modbus RTU
    By tekart in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 20th January 2010, 23:42
  3. CRC Calculations
    By timmers in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 16th June 2009, 18:10
  4. Problems with CRC8 Calc in 1Wire
    By JohnB in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 16th March 2007, 23:01
  5. crc16 help
    By beto in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 4th January 2006, 22:21

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts