Home AMX User Forum AMX General Discussion

CRC16 Modbus Problem

I'am having problems with the checksum of this piece of kit any help well much appreciated.


It's been a bit of a *****.

I have tried this.

DEFINE_FUNCTION CalculateCRC (CHAR cData[255])
{
STACK_VAR LONG nCRC_Hi LONG nCRC_Lo INTEGER nIndex
nCRC_Hi = ($FF)
nCRC_Lo = ($FF)
SEND_STRING 0:0:70,"'CRC Hi, ',ITOA(nCRC_Hi),' CRC Lo, ',ITOA(nCRC_Lo)"
FOR(nIndex = 1 ; nIndex < LENGTH_STRING(cData) ; nIndex ++)
{
nCRC_Hi = nCRC_Lo ^ cCRCHiArray[cData[nIndex]]
nCRC_Lo = cCRCLoArray[cData[nIndex]]
SEND_STRING 0:0:70,"'For Loop ',ITOA(nIndex),' CRC Hi, ',ITOA(nCRC_Hi)"
SEND_STRING 0:0:70,"'For Loop ',ITOA(nIndex),' CRC Lo, ',ITOA(nCRC_Lo)"
}

nCRC_Data_Lo = nCRC_Lo
nCRC_Data_Hi = (nCRC_Hi << 8)

SEND_STRING 0:0:70,"'End CRC Lo, ',ITOA(nCRC_Data_Lo)"
SEND_STRING 0:0:70,"'End CRC Hi, ',ITOA(nCRC_Data_Hi)"
}

cScaler_Command_Buffer = "$BE,$EF,$1A,$0C,$00,$00,$00,$3F,$00,$00,$00,$02,$00,$00,$00,$00,$00,$00,$00"

CalculateCRC (cScaler_Command_Buffer)

I Should get $19,$d7 back.

Any Help Please.

Cameron.

Comments

  • GregGGregG Posts: 251
    The main issue I think was you were probably throwing index 0 errors in netlinx a lot, I'd do it like this:
    PROGRAM_NAME='test'
    DEFINE_DEVICE
    dvMaster = 0:1:0
    DEFINE_CONSTANT
    Char cCRCHiArray[] = {
      $00, $C1, $81, $40, $01, $C0, $80, $41,
    // removed many lines of constant data for brevity
      $01, $C0, $80, $41, $00, $C1, $81, $40
    }
    Char cCRCLoArray[] = {
      $00, $C0, $C1, $01, $C3, $03, $02, $C2,
    // Removed many more lines of constants here too...
      $82, $42, $43, $83, $41, $81, $80, $40
    }
    
    DEFINE_VARIABLE
    
    Volatile Char cTestString[255]
    Volatile Char cCRC_Return[2]
    
    Define_Function Char[2] CalcCRC(Char cDataIn[])
    {
    Stack_Var Char cData[15000] // Whatever the longest possible message will be
    Stack_Var Char cCRCHi,cCRCLo,cDatum,cIndex
    
      cData = cDataIn // So we can be destructive without changing cDataIn
      cCRCHi = $FF
      cCRCLo = $FF
      
      While(Length_String(cData))
      {
        // Pull off the first data byte
        cDatum = Get_Buffer_Char(cData)
    
        cIndex = cCRCHi BXOR cDatum
    
        // We add 1 to all our array indexes, since unlike C, 0 is not our first array element.
        cCRCHi = cCRCLo BXOR cCRCHiArray[cIndex+1]
        cCRCLo = cCRCLoArray[cIndex+1]
      }
      
      Return "cCRCLo,cCRCHi"
    }
    
    DEFINE_PROGRAM
    
    Wait 100
    {
      cTestString = "$BE,$EF,$1A,$0C,$00,$00,$00,$3F,$00,$00,$00,$02,$00,$00,$00,$00,$00,$00,$00"
      
      cCRC_Return = CalcCRC(cTestString)
      
      SEND_STRING dvMaster,"'End CRC Hi, $',ItoHex(cCRC_Return[2])"
      SEND_STRING dvMaster,"'End CRC Lo, $',ItoHex(cCRC_Return[1])"
    }
    

    This function returns the CRC bytes all ready to be concatenated into your send packet like:
    cData=$BE,$EF,$1A,$0C,$00,$00,$00,$3F,$00,$00,$00,$02,$00,$00,$00,$00,$00,$00,$00
    Send_String dvDevice,"$BE,$EF,$1A,$0C,$00,CalcCRC(cData),$3F,$00,$00,$00,$02,$00,$00,$00,$00,$00,$00,$00"
    

    Apparently this is one weirdo protocol trying to CRC it's own header and CRC byte positions.
  • Many Thanks

    Thanks Greg

    That is fantastic i will try this on Monday.
    Its a very strange way indeed. thats why i was a bit confussed.

    Thanks Again

    Cameron
Sign In or Register to comment.