139-c-sharp-crc-code-for-modbus-rtu

Modbus is serial communication protocol. It is widely spread in industry and mainly is used to connect master communication device (usually PC) to remote terminal unit (RTU). Information package from master to slave device in MODBUS protocol has following format in RTU mode:

  • ID of the slave device is the first byte in the message
  • Code of the instruction is the second byte
  • Next two bytes are for 16 bits register address
  • Starting from fifth byte data bytes starts
  • Last two bytes contains CRC checksum bytes

RTU mode has good character density for the same baud rate (better then ASCII mode). Modbus defines information package structure and it is independent from physical layer such as RS232 or RS485. Example of Modbus implementation in C# is now following. For handling serial port, namespaces System.IO and System.IO.Ports are necessary. Now, serial port object has to be created and opened.

SerialPort spSerial = new SerialPort();
spSerial.PortName = “COM1”;
spSerial.BaudRate = 9600;
spSerial.DataBits = 8;
spSerial.StopBits = System.IO.Ports.StopBits.One;
spSerial.Parity = System.IO.Ports.Parity.None;

spSerial.Open(); // Open port

There comes a tricky part. We need to have byte array as data to send via Modbus RTU protocol, but to calculate CRC checksum bytes we need integers. So we will use integers for C# crc checksum modbus rtu calculus, and then data will be cast to bytes.

int[] intSend = new int[8];
intSend[0] = 0x01; // ID of slave device
intSend[1] = 0x03; // code of the command
intSend[2] = 0x1D; // Register address 0x1D63
intSend[3] = 0x63; // Register address 0x1D63
intSend[4] = 0x00; // First 8 bits of the data
intSend[5] = 0x02; // Second 8 bits of the data

int int_crc = 0xFFFF;
int int_lsb;
int int_crc_byte_a, int_crc_byte_b;

for (int int_i = 0; int_i < intSend.Length – 2; int_i++)
{

int_crc = int_crc ^ intSend[int_i];
for (int int_j = 0; int_j < 8; int_j++)
{

int_lsb = int_crc & 0x0001; // Mask of LSB
int_crc = int_crc >> 1;
int_crc = int_crc & 0x7FFF;
if (int_lsb == 1) int_crc = int_crc ^ 0xA001;

}

}

int_crc_byte_a = int_crc & 0x00FF;
int_crc_byte_b = (int_crc >> 8) & 0x00FF;

After CRC checksum is calculated as integer, byte array for sending data has to be created and data has to be cast.

byte[] bytSend = new byte[8];
byte bytTransfer;

for (int i = 0; i <= intSend.Length – 2; i++)
{

bytSend[i] = (byte)intSend[i];

}

CRC bytes are now added:

bytTransfer = (byte)int_crc_byte_a;
bytSend[intSend.Length – 2] = bytTransfer;

bytTransfer = (byte)int_crc_byte_b;
bytSend[intSend.Length – 1] = bytTransfer;

After cast, bytes has to be written into serial port and port can be closed:

spSerial.Write(bytSend, 0, bytSend.Length);
spSerial.Close(); // close port

Whole code is:

private void cmdModbus_Click(object sender, EventArgs e)
{

SerialPort spSerial = new SerialPort();
spSerial.PortName = “COM1”;
spSerial.BaudRate = 9600;
spSerial.DataBits = 8;
spSerial.StopBits = System.IO.Ports.StopBits.One;
spSerial.Parity = System.IO.Ports.Parity.None;

spSerial.Open(); // open port

int[] intSend = new int[8];
intSend[0] = 0x01; // ID of slave device
intSend[1] = 0x03; // code of the command
intSend[2] = 0x1D; // Register address 0x1D63
itSend[3] = 0x63; // Register address 0x1D63
intSend[4] = 0x00; // First 16 bits of the data
intSend[5] = 0x02;

int int_crc = 0xFFFF;
int int_lsb;
int int_crc_byte_a, int_crc_byte_b;

for (int int_i = 0; int_i < intSend.Length – 2; int_i++)
{

int_crc = int_crc ^ intSend[int_i];
for (int int_j = 0; int_j < 8; int_j++)
{

int_lsb = int_crc & 0x0001; // Mask of LSB
int_crc = int_crc >> 1;
int_crc = int_crc & 0x7FFF;
if (int_lsb == 1) int_crc = int_crc ^ 0xA001;

}

}

int_crc_byte_a = int_crc & 0x00FF;
int_crc_byte_b = (int_crc >> 8) & 0x00FF;

byte[] bytSend = new byte[8];
byte bytTransfer;

for (int i = 0; i <= intSend.Length – 2; i++)
{

bytSend[i] = (byte)intSend[i];

}

bytTransfer = (byte)int_crc_byte_a;
bytSend[intSend.Length – 2] = bytTransfer;

bytTransfer = (byte)int_crc_byte_b;
bytSend[intSend.Length – 1] = bytTransfer;

spSerial.Write(bytSend, 0, bytSend.Length);
spSerial.Close(); // close port

}

External links:

C# CRC Checksum Code for Modbus RTU on Codeproject
C# CRC Checksum Code for Modbus RTU on Ccontrolsys
C# CRC Checksum Code for Modbus RTU on Modbustools

Posted in c-sharp-code-examples

Leave a Reply

Your email address will not be published. Required fields are marked *

*