PDA

View Full Version : Dallas CRC16 Routines



Tom Estes
- 16th May 2005, 16:29
Three separate Dallas CRC16 routines.

Note: for some reason spaces are being added to some of the table entries. I tried to edit them out but they returned. They need to be removed before the table version is used.


' PIC16F628
' This program contains three subroutines for calculating the Dallas 1Wire 16Bit CRC.
' The computationally intensive short version is called CRC16. Use this one when
' you don't have enough PIC memory to store the table version (approx 550 words).
' and/or can afford the processing time.
' The table version CRC16LU is computationally fast since it works on byte at a
' time rather than bit at a time as CRC16 does.
' The assembly language version of the computationally intensive version is CRC16AL
' Times per 16 bit CRCWord consisting of CRCHI and CRCLO:
' CRC16LU - 62usec
' CRC16AL - 130usec
' CRC16 - 330usec


DEFINE OSC 4

@ DEVICE XT_OSC
@ DEVICE MCLR_OFF
@ DEVICE LVP_OFF
CMCON = 7

CRCData var Byte ' CRC16 & CRC16LU & CRC16AL
CRCLo var Byte ' CRC16 & CRC16LU & CRC16AL
CRCHi var Byte ' CRC16 & CRC16LU & CRC16AL
I var Byte ' CRC16 & CRC16AL
TestByte var Byte ' CRC16AL
TestBit var Bit ' CRC16
LUIndex var Byte ' CRC16LU
OldCRCHi var Byte ' CRC16LU

' Test Data
CRCHi = $90
CRCLo = $F1
CRCData = $75
' New CRCLo = $63, CRCHi = $90
GoSub CRC16LU
'GoSub CRC16
'Call CRC16AL
END

' ********** Subroutine CRC16 **********
' Subroutine expects CRCLo and CRCHi to be initialized to zero or some starting value
' and expects data to be CRC'd in CRCData
' CRCLo and CRCHi will contain new CRC Values. CRCData is destroyed.
' Need variables I-Byte, TestBit-Bit, CRCHi-Byte, CRCLo-Byte, CRCData-Byte
CRC16:
For I = 0 to 7 ' Do for all 8 bits in Data Byte
TestBit = CRCData.0 ^ CRCLo.0 ' XOR bit0 of Data Byte and Low CRC
CRCData = CRCData >> 1 ' Position Data Byte for next bit test
If TestBit = 0 then Shift ' If Test Bit not set, just shift CRC's
CRCHi.6 = CRCHi.6 ^ 1 ' If Test Bit set, compliment bit 14 of CRC
CRCLo.1 = CRCLo.1 ^ 1 ' And compliment bit 1 of CRC as well
Shift: ' Shift right whole CRC word.
CRCLo = CRCLo >> 1 ' Low CRC bit 0 is to bit bucket
CrcLo.7 = CRCHi.0 ' Make sure High CRC bit 0 shifts to Low CRC bit 7
CRCHi = CRCHi >> 1 ' High CRC bit 0 can now go to bit bucket
CRCHi.7 = TestBit ' Replace bit 15 of CRC with TestBit.
Next I
Return


' ********** Subroutine CRC16AL **********
' Subroutine expects CRCLo and CRCHi to be initialized to zero or some starting value
' and expects data to be CRC'd in CRCData
' CRCLo and CRCHi will contain new CRC Values. CRCData will be destroyed.
' Need variables I-Byte, TestByte-Byte, CRCHi-Byte, CRCLo-Byte, CRCData-Byte
ASM
_CRC16AL ; Dallas CRC16 Assembly Language PIC16F628
MOVLW 8
MOVWF _I ; Do this for all 8 bits of CRCByte
CRCLOOP
MOVF _CRCLo,0 ; Put CRCLo into W
XORWF _CRCData,0 ; XOR CRCLo with CRCData
MOVWF _TestByte ; Put results in TestByte
RRF _TestByte,1 ; Shift TestByte.0 into Carry bit
BTFSS STATUS,C ; If Carry = 1, account for EXOR feedback gates
GOTO CRCSHIFT ; Otherwise just shift CRC's and CRCByte
MOVF _CRCHi,0 ; Get latest copy of CRCHi
XORLW 0x40 ; Compliment CRCHi.6
MOVWF _CRCHi ; Keep a copy of results
MOVF _CRCLo,0 ; Get latest copy of CRCL0
XORLW 0x02 ; Compliment CRCLo.1
MOVWF _CRCLo ; Keep a copy of results
CRCSHIFT
RRF _CRCHi,1 ; Rotate both CRCs as a word, incorporate
RRF _CRCLo,1 ; c flag into CRCHi.7
RRF _CRCData,1 ; Shift remaining data bits right once
DECFSZ _I,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


' ********** Subroutine CRC16LU **********
' Subroutine expects CRCLo and CRCHi to be initialized to zero or some starting value
' expects data to be CRC'd in CRCData
' CRCLo and CRCHi will contain the new CRC values
' Needs variables LUIndex-Byte, CRCLo-Byte, CRCHi-Byte, OldCRCHi-Byte, CRCData-Byte
CRC16LU:
OldCRCHi = CRCHi
LUIndex = CRCLo ^ CRCData
LookUp LUIndex, [$00,$C0,$C1,$01,$C3,$03,$02,$C2,$C6,$06,$07,$C7,$0 5,$C5,$C4,$04,_
$CC,$0C,$0D,$CD,$0F,$CF,$CE,$0E,$0A,$CA,$CB,$0B,$C 9,$09,$08,$C8,_
$D8,$18,$19,$D9,$1B,$DB,$DA,$1A,$1E,$DE,$DF,$1F,$D D,$1D,$1C,$DC,_
$14,$D4,$D5,$15,$D7,$17,$16,$D6,$D2,$12,$13,$D3,$1 1,$D1,$D0,$10,_
$F0,$30,$31,$F1,$33,$F3,$F2,$32,$36,$F6,$F7,$37,$F 5,$35,$34,$F4,_
$3C,$FC,$FD,$3D,$FF,$3F,$3E,$FE,$FA,$3A,$3B,$FB,$3 9,$F9,$F8,$38,_
$28,$E8,$E9,$29,$EB,$2B,$2A,$EA,$EE,$2E,$2F,$EF,$2 D,$ED,$EC,$2C,_
$E4,$24,$25,$E5,$27,$E7,$E6,$26,$22,$E2,$E3,$23,$E 1,$21,$20,$E0,_
$A0,$60,$61,$A1,$63,$A3,$A2,$62,$66,$A6,$A7,$67,$A 5,$65,$64,$A4,_
$6C,$AC,$AD,$6D,$AF,$6F,$6E,$AE,$AA,$6A,$6B,$AB,$6 9,$A9,$A8,$68,_
$78,$B8,$B9,$79,$BB,$7B,$7A,$BA,$BE,$7E,$7F,$BF,$7 D,$BD,$BC,$7C,_
$B4,$74,$75,$B5,$77,$B7,$B6,$76,$72,$B2,$B3,$73,$B 1,$71,$70,$B0,_
$50,$90,$91,$51,$93,$53,$52,$92,$96,$56,$57,$97,$5 5,$95,$94,$54,_
$9C,$5C,$5D,$9D,$5F,$9F,$9E,$5E,$5A,$9A,$9B,$5B,$9 9,$59,$58,$98,_
$88,$48,$49,$89,$4B,$8B,$8A,$4A,$4E,$8E,$8F,$4F,$8 D,$4D,$4C,$8C,_
$44,$84,$85,$45,$87,$47,$46,$86,$82,$42,$43,$83,$4 1,$81,$80], CRCHi
' PBP only handles 255 constants in the list (256 for 18Cxxx) so special case for $FF
If LUIndex = $FF then
CRCHi = $40
EndIF
LookUp LUIndex, [$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81,$40,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$0 1,$C0,$80,$41,_
$00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$0 0,$C1,$81], CRCLo
If LUIndex = $FF then
CRCLo = $40
EndIF
CRCLo = CRCLo ^ OldCRCHi
Return