Modbus Communication

I use C # to communicate via modbus rs485 rs232 with two phase counters, which, among others, register the supply voltage.

I need to send data on the bus so that I can receive readings.
I connected a regular wire and shorted the transmission and reception.

The data is received and this event is fired:

 private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; byte[] buff = new byte[sp.BytesToRead]; //Read the Serial Buffer sp.Read(buff, 0, buff.Length); string data= sp.ReadExisting(); foreach (byte b in buff) { AddBuffer(b); //Add byte to buffer } } 

Then this buffer is sent to another function, which is the following:

 private void AddBuffer(byte b) { buffer.Add(b); byte[] msg = buffer.ToArray(); //Make sure that the message integrity is correct if (this.CheckDataIntegrity(msg)) { if (DataReceived != null) { ModbusEventArgs args = new ModbusEventArgs(); GetValue(msg, args); DataReceived(this, args); } buffer.RemoveRange(0, buffer.Count); } } 

I think the problem is data integrity checking:

 public bool CheckDataIntegrity(byte[] data) { if (data.Length < 6) return false; //Perform a basic CRC check: byte[] CRC = new byte[2]; GetCRC(data, ref CRC); if (CRC[0] == data[data.Length - 2] && CRC[1] == data[data.Length - 1]) return true; else return false; } 

There is a CRC check, and it is strange that it never becomes true. Calculation of CRC:

 private void GetCRC(byte[] message, ref byte[] CRC) { ushort CRCFull = 0xFFFF; byte CRCHigh = 0xFF, CRCLow = 0xFF; char CRCLSB; for (int i = 0; i < (message.Length) - 2; i++) { CRCFull = (ushort)(CRCFull ^ message[i]); for (int j = 0; j < 8; j++) { CRCLSB = (char)(CRCFull & 0x0001); CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); if (CRCLSB == 1) CRCFull = (ushort)(CRCFull ^ 0xA001); } } CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF); CRC[0] = CRCLow = (byte)(CRCFull & 0xFF); } 
+6
source share
2 answers

The problem is using ReadExisting (). It could not be used in this way, since the buffer was filled with useless data from the serial port. This issue was identified by @glace in the comments!

+2
source

First you need to establish a connection with your meters through some existing MODBUS main application, for example MODPOLL . Then, as soon as you have work with the data and the availability of the correct answers from your device, then and only then start testing your code. This way you will see that the problem can only be in your code and nothing else.

For example, for simultaneous connection to two slaves, instead of RS232, it is necessary to use RS485, and this requires different wiring and a RS485 to RS232 converter on the PC side.

Having RX and TX connected to RS232 for simulation purposes is not a good idea, since each MODBUS message from the master (except for broadcast messages) needs a response that is different from a simple message echo. In addition, each MODBUS message from the master has a MODBUS client address built into it, and only one client should respond to it (MODBUS is a protocol with one master with several subordinates).

As for CRC calculation, this can help for the MODBUS RTU protocol (ASCII is different):

 function mb_CalcCRC16(ptr: pointer to byte; ByteCount: byte): word; var crc: word; b, i, n: byte; begin crc := $FFFF; for i := 0 to ByteCount do if i = 0 then // device id is 1st byte in message, and it is not in the buffer b := mb_GetMessageID; // so we have to calculate it and put it as 1st crc byte else b := ptr^; Inc(ptr); endif; crc := crc xor word(b); for n := 1 to 8 do if (crc and 1) = 1 then crc := (crc shr 1) xor $A001; else crc := crc shr 1; endif; endfor; endfor; Return(crc); end; function mb_CalcCRC: word; // Calculate CRC for message in mb_pdu begin // this message can be one that is just received, or in a reply we have just composed Return(mb_CalcCRC16(@mb_pdu[1], mb_GetEndOfData)); end; 

This is a quote from a working embedded AVR device with the MODBUS RTU slave protocol implemented.

+1
source

Source: https://habr.com/ru/post/952656/


All Articles