Tom Estes
- 7th November 2007, 16:52
Three different routines to calculate the Sensirion CRC as used in their temperature/humidity sensors.
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,10 6,253,204,159,174,128,_
177,226,211,68,117,38,23,252,205,158,175,56,9,90,1 07,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,2 40,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
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,10 6,253,204,159,174,128,_
177,226,211,68,117,38,23,252,205,158,175,56,9,90,1 07,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,2 40,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