Shop OBEX P1 Docs P2 Docs Learn Events
CRC 16 generation and confusion — Parallax Forums

CRC 16 generation and confusion

Philip GamblinPhilip Gamblin Posts: 202
edited 2005-12-07 16:59 in BASIC Stamp
This subject has come up a couple times, and was recently on the Javelin
Stamp list as well. Here's a bit of code I used in a Stamp-to-PC
program:

Calc_CRC:
crc = (crc & $FF00) | (aByte ^ (crc & $FF))
FOR idx = 0 TO 7
IF (crc.BIT0 = 0) THEN
crc = crc >> 1
ELSE
crc = (crc >> 1) ^ $A001
ENDIF
NEXT
RETURN


The crc value is initialized to $0000 before looping through the bytes
in the package, sending them one at a time to the Calc_CRC routine.

I'll post the other demo in the file section as that algorithm was
described and provided with a small packet and expected CRC (and yes,
the PBASIC implementation works).

-- Jon Williams
-- Applications Engineer, Parallax
-- Dallas Office
·Philip Gamblin's Program

' {$STAMP BS2}
' {$PBASIC 2.5}
' {$PORT COM4}
'SERIN Rpin {\Fpin}, Baudmode, {Plabel,} {Timeout, Tlabel,} [noparse][[/noparse]InputData]
'SEROUT Tpin {\Fpin}, Baudmode, {Pace,} {Timeout, Tlabel,} [noparse][[/noparse]OutputData]

start:
······· cntr············ VAR··········· Byte
······· x··············· VAR··········· Byte
······· IO·············· VAR··········· Byte
······· IO1············· VAR··········· Byte
······· IO2············· VAR··········· Byte
······· addr············ VAR··········· Byte
······· funct··········· VAR··········· Byte
······· bytecnt········· VAR··········· Byte
······· RecDat·········· VAR··········· Byte(10)
······· Tx_CRC·········· VAR··········· Word
······· CRC_Reg········· VAR··········· Word
······· crclo··········· VAR··········· Byte
······· crchi··········· VAR··········· Byte
······· 'LSB············· VAR··········· Tx_CRC.LOWBIT''
' initialize VARs
······ IO = $AA
······ IO1 = $FF
······ IO2 =$AA
Chirp:
······· FREQOUT 0,500,3500
······· PAUSE 500
DatIn:
······· SERIN 2\10,396,[noparse][[/noparse]WAIT(":"),RecDat(0),RecDat(1),RecDat(2),RecDat(3),· 'Receive data to array
··················· RecDat(4),RecDat(5),RecDat(6),RecDat(7)]
······· Tx_Crc.LOWBYTE =· RecDat(7)········································ 'capture the Master CRC
······· Tx_CRC.HIGHBYTE = RecDat(6)
······· CRC_Reg=$FFFF························································· ·· 'Reset CRC_Reg
······· 'GOSUB CRC_Gen······················································· ··· 'Skipped the routine
··························································································· · 'because it doesn't work
······· PAUSE 200
········ IF RecDat(0)<$7e OR RecDat(0)>$7e THEN Chirp··················' Chirp is address is wrong
······· SEROUT 16,396,[noparse][[/noparse]":",$7e,funct,bytecnt,IO2,IO1,IO,crclo,crchi]

'DEBUG"*****************************************",CR
'DEBUG HEX2 ? addr,CR
'DEBUG HEX2 ? dataddrhi,CR
'DEBUG HEX2 ? dataddrlo,CR
'DEBUG HEX2 ? ptshi,CR
'DEBUG HEX2 ? ptslo,CR
'DEBUG HEX2 ? crchi,CR
'DEBUG HEX2 ? crclo,CR
' DEBUG HEX2?IO

CRC_Gen:
···········
········· FOR x= 0 TO 5······························ ···· 'this counter is for the 5 bytes in the Master Message
············ ·CRC_Reg.LOWBYTE=(CRC_Reg.LOWBYTE ^ RecDat(x)) '
·············· FOR Cntr = 1 TO 8

·············· CRC_Reg=CRC_Reg>>1
·············· CRC_Reg.BIT15=0

········································
·············· ·SELECT CRC_Reg.BIT0
··················· CASE = 0
······················· CRC_Reg=CRC_Reg/2
······················· CRC_Reg.BIT15=0
··················· CASE =1
······················· CRC_Reg= CRC_Reg ^ $A001
··············· ENDSELECT

············ · NEXT
······· ··· NEXT
········ '· DEBUG HEX4? CRC_Reg
········ '· DEBUG HEX2? RecDat(0)
········ '· DEBUG HEX2? RecDat(1)
········ '· DEBUG HEX2? RecDat(2)
········ '· DEBUG HEX2? RecDat(3)
········ '· DEBUG HEX2? RecDat(4)
········ '· DEBUG HEX2? RecDat(5)
········· ' DEBUG HEX2? RecDat(6)
········· ' DEBUG HEX2? RecDat(7)
········· ' DEBUG HEX4? Tx_CRC
·········· 'DEBUG HEX2? RecDat(8)
······ ' GOTO DatIn

·

Comments

  • Philip GamblinPhilip Gamblin Posts: 202
    edited 2005-12-07 16:59
    Well the short version is that Jon's code woks and mine doesn't. I had an extra shift ( >> ) command which hosed things up. My primary problem is, after reading the spec, it still reads to me like another shift is required. My program did what I told it to do ( as all programs will ) I just can't read english, I guess. My program is attached which serves to simulate·a Modbus Slave and simply forms a Modbus formated slave reply to a Modbus Master Interrogation .·It is a developemental step towards a larger project of·creating a Small I/O count Remote Terminal·Unit. I can·possibly save as much as·2,500 per installation.·What could be better than getting my employer to pay for my hobby?·Thanks again to Parallax. The archve provided the information I needed. Proving once again that Parallax helps those who help theselves. ·smile.gif

    Post Edited (Philip Gamblin) : 12/7/2005 5:14:55 PM GMT
Sign In or Register to comment.