First of all:
- The
MODBUS over Serial Line
standard is available here. This completely specifies low-level interface to MODBUS.
- The
MODBUS Application Protocol Specification
is available here. Higher-level MODBUS commands are specified here.
- Both of these standards are fairly short, easy to read and understand, and contain nice diagrams, so I highly recommend you look at them for answers.
Your data doesn't appear to conform to these standards, which makes it hard to answer your questions!
The serial line standard describes two communication methods, RTU and ASCII, but only the RTU method uses a CRC. So you must be using the RTU communication method since you're asking about CRC.
Assuming the RTU communication method, then the slave address should be the first byte, and the function code should be the second byte. That would mean that the slave address is 01
, and the function code is 37
. But that's not right, because the Application Protocol Specification page 11 lists all the function codes, and 37
is not a valid function code. Also, the slave address 01
doesn't match the slave address 77 that you claim to be using.
But let's ignore that for the moment. Your specific questions are about CRC.
- The RTU communication method is the only one which uses a CRC. The ASCII communication method uses a Longitudinal Redundancy Check (LRC), which is different.
- The RTU communication method uses a CRC-16, meaning the CRC has 16 bits = 2 bytes. The details are contained in the serial line standard, and there is even some sample C code for computing the CRC there. There are also multiple implementations in various languages available if you google, but do be careful because there are several different CRC-16 definitions and you need to make sure that what you use matches the MODBUS standard.
- The CRC position in a MODBUS frame is at the very end of the frame. The last two bytes (16 bits) are the CRC. The low-order byte of the CRC is appended first, followed by the high-order byte.
- The MODBUS queries that you provide do NOT appear to have a CRC appended to them at all. But, as I mentioned earlier, the MODBUS queries that you provide don't even look like they use the RTU communication method, which is the only method that uses a CRC.
Since your data doesn't seem to follow the RTU communication method, perhaps it uses the ASCII communication method, which is described starting on page 16 of the serial line standard. The ASCII communication method always starts with an ASCII :
character, which is 3A
in hex. The ASCII communication method always ends with ASCII cr and lf characters, which are 0D
and 0A
in hex. All other characters between these must be 0-9 or A-F characters, which are 30
through 39
and 41
through 46
in hex. Your message does not obey any of these requirements - it doesn't start with 3A
, it doesn't end with 0D
0A
, and it contains other characters that are not 30
through 39
or 41
through 46
.
If we ignore that and assume that your data follows the ASCII communication method, then:
- The LRC field would be the last two bytes before the
0D
0A
at the end.
- Page 18 of the serial line standard describes how LRC is computed. It is very simple:
The LRC is calculated by adding together successive 8–bit bytes of
the message, discarding any carries, and then two’s complementing the
result. It is performed on the bytes of the message, before the
encoding of each byte in the two ASCII characters corresponding to the
hexadecimal representation of each nibble. The computation does not include
the 'colon' character that begins the message, and does not include the CRLF
pair at the end of the message. The resulting LRC is ASCII encoded into two
bytes and placed at the end of the ASCII mode frame before the CRLF.
- Page 38 of the serial line standard give example C code for generating the LRC. It is only 9 lines of code.
Your data does not follow either of the communication methods. We would need to know more about where your data came from to figure out what went wrong. Perhaps the data is somehow corrupted by multiple devices, or perhaps the sensor that measures the data has incorrect timing or voltage or something, causing it to mis-understand the values being sent. Perhaps there is some kind of parity mis-match, causing some bytes to be thrown away. But we just can't tell without more information.