0
votes

I'm working on a communication command protocol between a PLC and a 3rd party device.

The manufacturer has provided me with the following information for calculating the CRC values that will change depending on the address of the device I wish to read information from.

A CRC is performed on a block of data, for example the first seven bytes of all transmissions are followed by a two byte CRC for that data. This CRC will be virtually unique for that particular combination of bytes. The process of calculating the CRC follows:

Inputs:
N.BYTES = Number or data bytes to CRC ( maximum 64 bytes )
DATA() = An array of data bytes of quantity N.BYTES
CRC.MASK = 0xC9DA a hexadecimal constant used in the process

Outputs:
CRC = two byte code redundancy check made up of CRC1 (High byte) and CRC2 (Low byte)

Process:
START
CRC = 0xFFFF
FOR N = 1 TO N.BYTES
CRC = CRC XOR ( DATA(N) AND 0xFF )
     FOR I = 1 TO 8
     IF ( CRC AND 0x0001 ) = 0 THEN LSR CRC
     ELSE LSR CRC ; CRC = CRC XOR CRC.MASK
     NEXT I
NEXT N
X = CRC1 ; Change the two bytes in CRC around
CRC1 = CRC2
CRC2 = X
END

They also provided me with a couple of complete command strings for the first few device addresses.

RTU #1
05-64-00-02-10-01-00-6C-4B-53-45-EB-F7
RTU #2
05-64-00-02-10-02-00-1C-AE-53-45-EB-F7
RTU #3
05-64-00-02-10-03-00-CC-F2-53-45-EB-F7

The header CRC bytes in the previous three commands are 6C-4B, 1C-AE, and CC-F2 respectively.

I calculated out a the first few lines by hand to have something to compare against when I wrote out the following code in Python.


    byte1 = 05
    byte2 = 100
    byte3 = 00
    byte4 = 02
    byte5 = 16
    byte6 = 01
    byte7 = 00
    byte8 = 00
    
    mask = 51674
    
    hexarray = [byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8]
    
    #print hexarray
    
    CRCdata = 65535
    
    for n in hexarray:
        CRCdata = CRCdata ^ (n & 255)
        print(n, CRCdata)
    
        for i in range(1,8):
            if (CRCdata & 1) == 0:
                CRCdata = CRCdata >> 1
    #           print 'if'
            else:
                CRCdata = CRCdata >> 1
                CRCdata = CRCdata ^ mask
    #           print 'else'
            print(i, CRCdata)
            
    print CRCdata

I added byte8 due to some research I did mentioning that an extra byte of 0s needs to be added to the end of the CRC array for calculations. I converted the final result and did the byte swap manually. The problem I've been running into, is that my CRC calculations, whether I keep byte8 or not, are not matching up with any of the three examples that have been provided.

I'm not quite sure where I am going wrong on this and any help would be greatly appreciated.

1
Where's your equivalent code for "Change the two bytes in CRC around"? - paxdiablo
Apologies for leaving that information out. I was just doing that part manually. - adlawl
range(1,8) contains seven values - you're completely skipping one bit in each byte. - jasonharper

1 Answers

1
votes

I was able to solve the issue by updating the code to range(0,8) and dropping byte8.