|Lynn's Industrial Automation Protocol Tips|
|Home > Modbus > Modbus/RTU Tips >|
The information on this web page is either Lynn's opinion or something Lynn agrees with. He has complete control over its contents. Nothing contained within this pages is approved by or represents the opinion of Digi International, The Modbus Organization, the Modbus-IDA Group, ODVA, or any other organization Lynn is associated with.
Question? How to calculate the CRC in "C"?
Here is code I've used. It uses the faster 'table lookup' made popular by XMODEM. Mine fills the static table of 256 words dynamically upon start-up - other examples you'll find initialize the data directly.
Question? How to calculate the CRC in VisualBasic?
Here is code I've used. It uses the faster 'table lookup' made popular by XMODEM. The key to VB is the correct masking of 32-bit longs to simulate 16-bit unsigned operation. My is not optimized, but it works.
Question? How to handle the 3.5 character timeout?
Answer: There are really 2 sides to this question: Transmit and Receive:
When transmitting, make sure your device can send data with less than 1.5 character gap between bytes. This may mean you have the serial transmit priority very high - perhaps even higher than Ethernet etc. This is generally not hard to do.
When receiving, generally you should NOT enforce a strict 3.5 character timeout - you'll find it causes more support problems than 'the better way'. Many wireless/radio modems and wide-area-network solutions will NOT work if you succeed in doing a perfect 3.5 character (or 3.5 millisecond at 9600 baud) end-of-message detection. This is because they 'packetize' data into fixed blocks of perhaps 32 or 128 bytes and send these with error correction information, retries, and token rotation between blocks. This means you may see a 5 or 25 msec gaps within your Modbus message. With wide-area-network (like satellite) this can be even more extreme with gaps up to 1-second! Plus it is nearly impossible to measure on a modern system with UART FIFOs, heavy OS overhead and stock serial drivers. Trying to do a 4 msec gap detect on a stock Windows serial driver will lead to long delays after every message.
The better way is to add some Modbus protocol knowledge into your driver. For example if you are a slave seeing a function code 3 request, then after the second byte (the func 3) you'll know you should receive a total of 8 bytes with the CRC. If after seeing 8 bytes the CRC is valid, then you know that you have a complete message and no 3.5 character pause or gap is required. If you are a masters seeing a function code 3 response, then after the third byte (the data length) you'll know you should receive a total of 5 bytes plus the data length value. If after seeing this number of bytes the CRC is valid, then you know that you have a complete message and no 3.5 character pause or gap is required.
Why is this smarter? Because it allows you to have more tolerant, customer-friendly end-of-message timeout of 50 msec. This will NOT slow down your Modbus - in fact it will be faster than trying to use a 3.5 char gap! With the combination of message-length estimation and a 50 millisecond timeout, once you see the expected number of bytes and a valid CRC you are done without the need for the 50 msec delay. You'll get by with NO added delay. The 50 msec delay only is used when a CRC error is being detected or you are seeing a Modbus function you do not support. Compare this to the situation with the 3.5 character (4-msec at 9600 baud). You will always add about 5msec of dead time to every message - and if you find yourself talking over a wireless or wide-area-network system that adds gaps and pauses you'll have either a large error rate or no communications at all.
Yes, this violates the SACRED ISO/OSI 7-layer model by making your "Link-Layer" application aware. Whoppity-do I say. In the real world - solve your problems as you must. This estimation method gives you the best throughput and performance, with the least support head-aches. It will work with hardware that demands a 3.5 character timeout, as well as hardware and media that cannot deliver such tight timing.
Just make sure you allow your users to adjust this time delay. The 50 msec I mention is a good default, but for wide-area-network systems delays up in the 1-2 second range are possible. I prefer a range of about 5 to 5000 msec.
Here is a some simple psuedo-C code showing how to estimate the 8 most common Modbus function codes. Hopefully I haven't goofed creating this example.
Answer: No, this is a common goof beginners make
I've heard from a few embedded programmers over the years who've tried that and learned the hard way it doesn't work. Nothing stops the CRC from being zero several times during a continuing message. With only 65,535 possible values, the partial CRC can be zero after any number of bytes are received.
|Feedback - Contact||Lynn's Industrial Automation Protocol Tips||Copyright 2004|