LB Booster
« MODBUS CRC16 calculation »

Welcome Guest. Please Login or Register.
Apr 1st, 2018, 04:26am



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
We apologize Conforums does not have any export functions to migrate data.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

Thank you Conforums members.
Speed up Liberty BASIC programs by up to ten times!
Compile Liberty BASIC programs to compact, standalone executables!
Overcome many of Liberty BASIC's bugs and limitations!
LB Booster Resources
LB Booster documentation
LB Booster Home Page
LB Booster technical Wiki
Just BASIC forum
BBC BASIC Home Page
Liberty BASIC forum (the original)

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: MODBUS CRC16 calculation  (Read 1843 times)
flotulopex
Junior Member
ImageImage


member is offline

Avatar




Homepage PM

Gender: Male
Posts: 94
xx MODBUS CRC16 calculation
« Thread started on: Feb 13th, 2014, 4:12pm »

Hello,

I'm working on a small MODBUS project and have a need for a CRC16 calculator. For a start, I found following explanation on the web and aslo a PIC Basic code to start with.

For now, I would like to convert this PIC Basic code to LBB so I get a nice tool to work with.

I know, I know: google. Pffff.....

But I don't want a "ready made" thing; I prefer to MAKE MY OWN tool!

Hereunder is the explanation of how to calculate a CRC16.

The 16-bits Cyclical Redundancy Check (CRC) field is two bytes, containing a 16-bit binary value.
The CRC value is calculated by the transmitting device, which appends the CRC to the message.
The receiving device recalculates a CRC during receipt of the message, and compares the calculated value to the actual value it received in the CRC field. If the two values are not equal, an error results.
The CRC is started by first preloading a 16-bit register to all 1's. Then a process begins of applying successive 8-bit bytes of the message to the current contents of the register.
Only the eight bits of data in each character are used for generating the CRC; start and stop bits, and the parity bit do not apply to the CRC.
During generation of the CRC, each 8-bit character is XORed with the register contents. Then the result is shifted in the direction of the least significant bit (LSB) and filled with a zero into the most significant bit (MSB) position. The LSB is extracted and examined. If the LSB was a 1, the register is then XORed with a preset fixed value. If the LSB was a 0, no XOR takes place. This process is repeated until eight shifts have been performed. After the last (eighth) shift, the next 8-bit character is XORed with the register's current value, and the process repeats for eight more shifts as described above.
The final content of the register, after all the characters of the message have been applied, is the CRC value.


Here's the PIC Basic code I started with:
Code:
'CRC=$FFFF ' initialize value
For X = 0 to 10 ' number of bytes to process
    CRC = CRC ^ dataCRC[X] ' read through data array
        For Z = 1 to 8
            IF CRC.Bit0 = 1 Then ' check bits
               CRC = $A001 ^ (CRC >> 1)
            Else
               CRC = CRC >> 1
            EndIF
        Next Z
Next X 


And here is what I came to with LBB:
Code:
'This example is ment to be correct: 0F 03 08 13 24 13 88 13 5B 00 01 = CRC16: 0x0FD2

DataCRC$(0)  = "0F"
DataCRC$(1)  = "03"
DataCRC$(2)  = "08"
DataCRC$(3)  = "13"
DataCRC$(4)  = "24"
DataCRC$(5)  = "13"
DataCRC$(6)  = "88"
DataCRC$(7)  = "13"
DataCRC$(8)  = "5B"
DataCRC$(9)  = "00"
DataCRC$(10) = "01"

[start]
    PRINT "MODBUS CRC-16 calculator"
    PRINT "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ"
[calculate]
   CRCRegister = 65535 '&hFFFF
   FOR X = 0 to 10
      CRCRegister = CRCRegister XOR HEXDEC(DataCRC$(0))
      FOR Z = 0 TO 7
         IF (CRCRegister MOD 2) = 1 THEN        'chek if the LSB is a "1"
            CRCRegister = INT(CRCRegister / 2)  'shift CRCRegister one bit to the right
            CRCRegister = CRCRegister XOR 40961 '&hA001
         ELSE
            CRCRegister = INT(CRCRegister / 2)  'shift CRCRegister one bit to the right
         END IF
      NEXT Z
   NEXT X
   PRINT "CRC16 (0x0FD2) : "; CRCRegister, DECHEX$(CRCRegister)
END 

I just can't get the correct result that should be 0x0FD2.

What am I doing (or not doing) wrong?

BTW, is there a way to close the "***.lbb.tmp" window by a command instead of Alt+F4? Something like:
Code:
INPUT "Close this window?"; Y/N 


Roger
User IP Logged

Roger
Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: MODBUS CRC16 calculation
« Reply #1 on: Feb 13th, 2014, 10:14pm »

on Feb 13th, 2014, 4:12pm, flotulopex wrote:
What am I doing (or not doing) wrong?

There's a typo. Change DataCRC$(0) to DataCRC$(X) as follows:

Code:
      CRCRegister = CRCRegister XOR HEXDEC(DataCRC$(X)) 

Quote:
BTW, is there a way to close the "***.lbb.tmp" window by a command instead of Alt+F4?

If you don't mind it being LBB-specific you can close the mainwin as follows:

Code:
    !QUIT 

(note the initial exclamation mark).

Richard.
User IP Logged

flotulopex
Junior Member
ImageImage


member is offline

Avatar




Homepage PM

Gender: Male
Posts: 94
xx Re: MODBUS CRC16 calculation
« Reply #2 on: Feb 14th, 2014, 05:59am »

Thank you Richard; it works fine now.

Having my nose too close to the screen, I couldn't see that simple mistake that costed me more than 12 hours!!

Thanks again for that and also for the windows closing tip smiley
User IP Logged

Roger
Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls