Sto utilizzando C# per comunicare tramite modbus rs485 rs232
a 2 misuratori di fase che tra gli altri registrano la tensione di alimentazione.Comunicazione Modbus
Devo inviare i dati sul bus in modo da poter ricevere le letture.
Ho collegato un filo normale e ho messo in corto l'invio e la ricezione.
I dati è ricevuto e questo evento viene generato:
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
}
}
Poi questo buffer viene inviato ad un'altra funzione, che è questo:
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);
}
}
Penso che il problema sta alla dati controllo di integrità:
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;
}
C'è un controllo CRC e ciò che è strano è che non è mai bec è vero. Il calcolo 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);
}
Esistono risorse online con una trascrizione di una tipica sessione di comunicazione, completa di CRC? Quindi potresti almeno applicare il tuo algoritmo a quei messaggi di esempio e vedere se ti viene in mente lo stesso CRC. –
Qual è la variabile "buffer"? È una lista? Sei sicuro che la tua variabile "msg" sia mai più grande di 6? Perché non utilizzare il buffer solo dalla porta seriale invece di scomporlo in un ciclo per byte, ricostruendolo in un elenco, quindi riconvertendolo in un array di byte globale? Chiamate anche ReadExisting sulla porta seriale subito dopo aver letto il contenuto del buffer, perché? –
Il CRC sembra essere corretto @AndyzSmith. cosa intendi con la chiamata a leggere esattamente dove posso chiamarlo?e sì il buffer è una lista – Combinu