
namespace PressureMonitor
{
class NP70C
{
Modbus mModbus;
public NP70C(SerialPort _SerialPort)
{
mModbus = new Modbus(_SerialPort);
}
[StructLayout(LayoutKind.Explicit)]
public struct Union
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(0)]
public Int16 Value;
}
public int Pv = 0x00;
public string ErrorMag = string.Empty;
public void ReadPv()
{
byte Address = 0x01;
UInt16 RegisterNumber = 0x02;
UInt16 RegisterCount = 0x01;
byte[] Data = null;
Modbus.Error err;
if ((err = mModbus.ReadHoldingRegister(Address, RegisterNumber, RegisterCount, ref Data)) != Modbus.Error.Success)
{
ErrorMag = err.ToString();
return;
}
Union Temp = new Union();
Temp.byte1 = Data[0];
Temp.byte2 = Data[1];
Pv = Temp.Value;
}
}
}
class Modbus
{
private SerialPort mSerialPort;
public enum Error
{
Success,
SerialPortNotOpenYet,
SerialPortWriteFailure,
SerialPortReadFailure,
}
public Modbus(SerialPort _SerialPort)
{
mSerialPort = _SerialPort;
}
public Error ReadHoldingRegister(byte Address, UInt16 RegisterNumber, UInt16 RegisterCount, ref byte[] Data)
{
byte[] Cmd = new byte[8];
Cmd[0] = Address;
Cmd[1] = 0x03;
Cmd[2] = (byte)((RegisterNumber & 0xF0) >> 8);
Cmd[3] = (byte)((RegisterNumber & 0x0F));
Cmd[4] = (byte)((RegisterCount & 0xF0) >> 8);
Cmd[5] = (byte)((RegisterCount & 0x0F));
byte[] Crc = CalculateCRC(Cmd, 6);
Cmd[6] = Crc[0];
Cmd[7] = Crc[1];
Error Err = Error.Success;
if ((Err = SendCmd(Cmd)) != Error.Success) return Err;
//Address(1) + FunctionCode(1) + RegisterNumber(2) + RegisterCount *2 + CRC(2)
int MsgLen = 1 + 1 + 2 + 2 * RegisterCount + 2;
byte[] Response = new byte[MsgLen];
if ((Err = ReceiveMsg(MsgLen, ref Response)) != Error.Success) return Err;
int DataLen = 2 * RegisterCount;
Data = new byte[DataLen];
for (int idx = 0; idx < DataLen; idx++)
{
Data[idx] = Response[5 + idx];
}
return Error.Success;
}
public Error SendCmd(byte[] Cmd)
{
if (mSerialPort.IsOpen == false) return Error.SerialPortNotOpenYet;
try
{
mSerialPort.Write(Cmd, 0, Cmd.Length);
}
catch
{
return Error.SerialPortWriteFailure;
}
return Error.Success;
}
public Error ReceiveMsg(int MsgLen, ref byte[] Response)
{
if (mSerialPort.IsOpen == false) return Error.SerialPortNotOpenYet;
byte[] REV = new byte[MsgLen];
try
{
mSerialPort.Read(REV, 0, MsgLen);
Response = REV;
}
catch
{
return Error.SerialPortReadFailure;
}
return Error.Success;
}
byte[] CalculateCRC(byte[] Mag, int len)
{
UInt16 Temp = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
Temp ^= (UInt16)Mag[pos]; // 取出第一個byte與crc XOR
for (int i = 8; i != 0; i--)
{ // 巡檢每個bit
if ((Temp & 0x0001) != 0)
{ // 如果 LSB = 1
Temp >>= 1; // 右移1bit 並且 XOR 0xA001
Temp ^= 0xA001;
}
else // 如果 LSB != 1
Temp >>= 1; // 右移1bit
}
}
byte[] Crc = new byte[2];
Crc[0] = (byte)(Temp & 0xFF);
Crc[1] = (byte)(Temp >> 8 & 0xFF);
return Crc;
}
}
沒有留言:
張貼留言