Modbus CRC

Started by electrifiedspam, January 02, 2011, 12:45:03 PM

Previous topic - Next topic

electrifiedspam

I figured out how to do it. I thought I would share. Mind you, this is the gross version so there is much optimization left to do, my goal was to get something that did the trick. Now I need to make it cleaner, but I thought that I would at least share.

------------------------------------------------------------------------------------------------------------------------

;note this spits out the decimal of the crc. It needs converted to hexadecimal.

;0x11 0x05 0x00 0xAC 0xFF 0x00 4E8B (crc appended to the message) Sample message to test against. 0xA001 is the crc constant for modbus.

(context 'CRC)



(constant 'crcConst (bits 0xA001))



(define (crcModbus message)

   (set 'crcReg "1111111111111111")

      (while (> (length message) 0)

         (set 'crcReg (XOR crcReg (bits (pop message))))

         (dotimes (x 8) (set 'crcReg (shiftXOR crcReg)))   

      )

      (println (int crcReg 0 2))

)



(define(lsb_is_1 num)

   (if (= (last num) "1") true)

)



(define (XOR numA numB)

   (if (< (length numA) 16) (dotimes (x (- 16 (length numA))) (push "0" numA)))

   (if (< (length numB) 16) (dotimes (x (- 16 (length numB))) (push "0" numB)))

   (set 'numA (reverse numA) 'numB (reverse numB))

   (join (map string (reverse (map (fn (y z) (^ (int y) (int z))) (explode numA) (explode numB)))))

)



(define (rshift numC)

   (set 'numc (chop numC 1))

   (set 'numc (join (push "0" (explode numc))))

   numc

)



(define (shiftXOR numD)

   (if (lsb_is_1 numD) (set 'res (XOR (rshift numD) (bits 0xA001))) (set 'res (rshift numD)))

   (println res)

   res

)



(context 'MAIN)

electrifiedspam

#1
I chose a string of 1's and 0's simply so I would know what was going on and it was easy to print out all of the shifts and register manipulations so I could debug easier.



granted that (^ 0xFFFF 0x11) turns out the same result as all of the cruft I had to go through but I went for a version that was readable.



I have not done any benchmarking on this so it may in fact BE unusable for higher baud rates.



Thank you all

Chris