Modbus CRC
Posted: Sun Jan 02, 2011 8:45 pm
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)
------------------------------------------------------------------------------------------------------------------------
;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)