Files
DT_BR_GUI/LFP_Manager/Function/CsRs485CommFunction124050.cs
2025-12-17 12:40:51 +09:00

997 lines
46 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using LFP_Manager.DataStructure;
using LFP_Manager.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LFP_Manager.Function
{
internal class CsRs485CommFunction124050
{
public const byte READ_COIL_STATUS = 0x01;
public const byte READ_HOLDING_REG = 0x03;
public const byte READ_INPUT_REG = 0x04; //Byul 구문 추가 필요
public const byte FORCE_SINGLE_COIL = 0x05;
public const byte PRESET_SINGLE_REG = 0x06;
public const byte PRESET_MULTI_REG = 0x10;
public const byte WRITE_COIL_REG = 0x0F;
public const byte ERROR_REG = 0x90;
public const byte READ_WRITE_REG = 0x17;
public const byte SPECIAL_REG_02 = 0x19;
public const byte READ_DEV_ID = 0x2B;
public const byte FW_FLASH_ERASE_CMD = 0x43;
public const byte FW_FLASH_WRITE_CMD = 0x31;
public const byte NO_CMD = 0xFF;
public static byte[] GetCRC(byte[] pby, int nSize)
{
ushort uIndex, i;
ushort crc;
byte uchCRCHi = 0xff;
byte uchCRCLo = 0xff;
byte[] result = new byte[2];
for (i = 0; i < nSize; i++)
{
uIndex = (ushort)((int)uchCRCLo ^ (int)pby[i]);
uchCRCLo = (byte)(uchCRCHi ^ csConstData.CRC_Data.auchCRCHi[uIndex]);
uchCRCHi = csConstData.CRC_Data.auchCRCLo[uIndex];
}
crc = (ushort)((uchCRCHi << 8) | uchCRCLo);
result[0] = (byte)(crc >> 8);
result[1] = (byte)(crc >> 0);
return result;
}
static public byte[] MakeReadRegisterData(ushort DevID, ushort cmd, ushort ReadAddr, ushort Size)
{
byte[] result = new byte[8];
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)cmd; // Command
result[2] = (byte)(ReadAddr >> 8); // Register Address MSB
result[3] = (byte)(ReadAddr >> 0); // Register Address LSB
result[4] = (byte)(Size >> 8); // Count of Register MSB
result[5] = (byte)(Size >> 0); // Count of Register LSB
crc = GetCRC(result, 6);
result[6] = crc[1]; // CRCH
result[7] = crc[0]; // CRCL
return result;
}
static public byte[] MakeWriteCoilData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[7 + (1 * 1) + 2];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)WRITE_COIL_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB
result[i++] = (byte)(1 >> 8); // Count of Register MSB
result[i++] = (byte)(1 >> 0); // Count of Register LSB
result[i++] = (byte)(1 * 1); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[1]; // CRCH
result[i++] = crc[0]; // CRCL
return result;
}
static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[9 + (1 * 2)];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)PRESET_MULTI_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB
result[i++] = (byte)(1 >> 8); // Count of Register MSB
result[i++] = (byte)(1 >> 0); // Count of Register LSB
result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 8);
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[1]; // CRCH
result[i++] = crc[0]; // CRCL
return result;
}
static public byte[] MakeReadDevIdRegReqData(ushort DevID, ushort cmd, ushort ReadAddr)
{
byte[] result = new byte[7];
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)cmd; // Command
result[2] = (byte)0x0E; // MEI Type
result[3] = (byte)0x02; // Read Dev Id code
result[4] = (byte)ReadAddr; // Object Id
crc = GetCRC(result, 5);
result[5] = crc[1]; // CRCH
result[6] = crc[0]; // CRCL
return result;
}
static short GetRegister(ushort reg_addr, ref DeviceParamData aParam)
{
short result = 0;
switch (reg_addr)
{
//case 19: result = (short)(0 >> 16); break; // 0021 : UTC TimeStamp MSB
//case 20: result = (short)(58 >> 0); break; // 0022 : UTC TimeStamp LSB
//case 21: result = (short)0x1000; break; // 0023 : Cell Balancing Flag
//case 22: result = (short)0x0000; break; // 0024 : Cell Balancing Voltage
//case 23: result = (short)15; break; // 0024 : Cell Balancing Time
case 0x4002: result = (short)aParam.CellUnderVoltageWarning; break; // 0061 : Low cell voltage warning data
//case 33: result = (short)param.sf1.voltage.CUV_Threshold; break; // 0062 : Low cell voltage protection data
//case 34: result = (short)param.sf1.voltage.CUV_Recovery; break; // 0063 : Low cell voltage recovery data
//case 35: result = (short)param.sf1.voltage.SUV_Warning; break; // 0064 : Low voltage warning data
//case 36: result = (short)param.sf1.voltage.SUV_Threshold; break; // 0065 : Low voltage protection data
//case 37: result = (short)param.sf1.voltage.SUV_Recovery; break; // 0066 : Low voltage recovery data
//case 38: result = (short)param.sf1.voltage.COV_Warning; break; // 0067 : Over cell voltage warning data
//case 39: result = (short)param.sf1.voltage.COV_Threshold; break; // 0068 : Over cell voltage protection data
//case 40: result = (short)param.sf1.voltage.COV_Recovery; break; // 0069 : Over cell voltage recovery data
//case 41: result = (short)param.sf1.voltage.SOV_Warning; break; // 0070 : Over voltage warning data
//case 42: result = (short)param.sf1.voltage.SOV_Threshold; break; // 0071 : Over voltage protection data
//case 43: result = (short)param.sf1.voltage.SOV_Recovery; break; // 0072 : Over voltage recovery data
//case 44: result = (short)param.sf1.temperature.OT_Chg_Warning; break; // 0044 : Charge over temperature warning data
//case 45: result = (short)param.sf1.temperature.OT_Chg_Threshold; break; // 0045 : Charge over temperature protection data
//case 46: result = (short)param.sf1.temperature.OT_Chg_Recovery; break; // 0046 : Charge over temperature recovery data
//case 47: result = (short)param.sf1.temperature.OT_Chg_Time; break; // 0047 : Charge over temperature time
//case 48: result = (short)param.sf1.temperature.OT_Dsg_Warning; break; // 0048 : Discharge over temperature warning data
//case 49: result = (short)param.sf1.temperature.OT_Dsg_Threshold; break; // 0049 : Discharge over temperature protection data
//case 50: result = (short)param.sf1.temperature.OT_Dsg_Recovery; break; // 0050 : Discharge over temperature recovery data
//case 51: result = (short)param.sf1.temperature.OT_Dsg_Time; break; // 0051 : Discharge over temperature time
}
return result;
}
static byte[] ModBusGetRegWordToBytes(ushort addr, ref DeviceParamData aParam)
{
short data;
byte[] result = new byte[2];
data = GetRegister(addr, ref aParam);
result[0] = (byte)(data >> 8);
result[1] = (byte)(data >> 0);
return result;
}
static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, ushort reg_len, ref DeviceParamData aParam)
{
int tlen = (reg_len * 2) + 7 + 2;
byte[] result = new byte[tlen];
byte[] tmp;
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)PRESET_MULTI_REG; // Command
result[2] = (byte)(WriteAddr >> 8); // Register Address MSB
result[3] = (byte)(WriteAddr >> 0); // Register Address LSB
result[4] = (byte)(reg_len >> 8); // Count of Register MSB
result[5] = (byte)(reg_len >> 0); // Count of Register LSB
result[6] = (byte)(reg_len * 2); ; // Current Value MSB
for (int i = 0; i < reg_len; i++)
{
tmp = ModBusGetRegWordToBytes((ushort)(WriteAddr + i), ref aParam);
result[7 + (i * 2) + 0] = tmp[0];
result[7 + (i * 2) + 1] = tmp[1];
}
crc = GetCRC(result, 8);
result[tlen - 2] = crc[0]; // CRCH
result[tlen - 1] = crc[1]; // CRCL
return result;
}
static public byte[] MakeReadWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[15];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)READ_WRITE_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Read Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Read Register Address LSB
result[i++] = (byte)(0 >> 8); // Read Count of Register MSB
result[i++] = (byte)(0 >> 0); // Read Count of Register LSB
result[i++] = (byte)(WriteAddr >> 8); // Write Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Write Register Address LSB
result[i++] = (byte)(1 >> 8); // Write Count of Register MSB
result[i++] = (byte)(1 >> 0); // Write Count of Register LSB
result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 8);
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[0]; // CRCH
result[i++] = crc[1]; // CRCL
return result;
}
public static byte[] MakeCheckSum(byte[] sData, int offset, int len, bool flag)
{
byte[] result = new byte[2];
int checksum = 0;
for (int i = 0; i < len; i++)
{
checksum += sData[i + offset];
}
checksum = ~checksum + 1;
result[0] = (byte)(checksum >> 8);
result[1] = (byte)checksum;
return result;
}
private static byte[] MakeTxPacket(byte[] sData, int len)
{
string str = "";
byte[] result;
char[] chrArray;
int checksum = 0;
string checksumStr = "";
char[] checksumChr;
str = "~";
for (int i = 0; i < len; i++)
{
str += sData[i].ToString("X2");
}
str += "\r";
chrArray = str.ToCharArray();
for (int i = 0; i < (chrArray.Length - 6); i++)
{
checksum += chrArray[i + 1];
}
checksum = ~checksum + 1;
checksumStr = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum);
checksumChr = checksumStr.ToCharArray();
for (int i = 0; i < 4; i++)
{
chrArray[chrArray.Length - 5 + i] = checksumChr[i];
}
result = new byte[chrArray.Length];
for (int i = 0; i < chrArray.Length; i++)
{
result[i] = (byte)chrArray[i];
}
return result;
}
public static byte[] LengthLchk(int sLen)
{
byte[] result = new byte[2];
int lchksum = 0;
lchksum = (~(((sLen >> 8) & 0xF) +
((sLen >> 4) & 0xF) +
((sLen >> 0) & 0xF)) + 1) % 16;
lchksum = ((lchksum << 12) | sLen);
result[0] = (byte)(lchksum >> 8);
result[1] = (byte)(lchksum >> 0);
return result;
}
public static byte[] MakeTxData(byte addr, byte cmd, int sLen)
{
int buffCh = 0;
byte[] sData;
byte[] lenId;
byte[] checksum;
sData = new byte[((sLen > 0) ? 11 : 10)];
sData[buffCh] = 0x7E; buffCh++; // SOI
sData[buffCh] = 0x25; buffCh++; // VER
sData[buffCh] = addr; buffCh++; // ADDR
sData[buffCh] = 0x46; buffCh++; // CID1
sData[buffCh] = cmd; buffCh++; // CID2 (CMD)
lenId = LengthLchk(sLen); // LENID
sData[buffCh] = lenId[0]; buffCh++; // LENID MSB
sData[buffCh] = lenId[1]; buffCh++; // LENID LSB
if (sLen > 0)
{
sData[buffCh] = (byte)(sLen / 2); buffCh++; // INFO
}
checksum = csSerialCommFunction.MakeCheckSum(sData, 1, sData.Length - 4, false);
sData[buffCh] = checksum[1]; buffCh++;
sData[buffCh] = checksum[0]; buffCh++;
sData[buffCh] = 0x0D; buffCh++; // EOI
return MakeTxPacket(sData, sData.Length);
}
public static int TbPacketCheck(byte[] rdata, int rlen)
{
int result = 0;
byte[] cdata;
byte[] checksum;
byte[] checksum1;
checksum = MakeCheckSum(rdata, 1, rlen - 6, false);
checksum1 = new byte[2];
checksum1[0] = csUtils.StrByte2toByte(rdata[rlen - 4], rdata[rlen - 5]);
checksum1[1] = csUtils.StrByte2toByte(rdata[rlen - 2], rdata[rlen - 3]);
if ((checksum[0] == checksum1[0]) && (checksum[1] == checksum1[1]))
{
cdata = csUtils.StrToByteArray(rdata, 0, rlen);
result = 1;
}
return result;
}
static public int ModbusPacketFromSlaveCheck(byte[] rdata, ushort rlen)
{
int result = 0;
byte[] cdata, crc;
ushort clen, bytecount;
if (rlen > 2)
{
cdata = rdata;
switch (cdata[1])
{
case READ_DEV_ID:
if (rlen < 10) break;
if (rdata[7] == 0) break;
int tmp = 0;
int cPos = 7;
int alen = 0;
for (int i = 0; i < cdata[7]; i++)
{
alen = cdata[cPos + 2];
cPos += alen + 2;
if (rlen < (cPos + 3))
{
tmp = 1;
break;
}
}
if (tmp == 1) break;
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1;
else result = -1;
break;
case READ_COIL_STATUS:
case READ_HOLDING_REG:
case READ_INPUT_REG:
case READ_WRITE_REG:
bytecount = cdata[2];
clen = (ushort)(bytecount + 5); // header 3, tail 2
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1;
else result = -1;
}
break;
case PRESET_MULTI_REG:
case FORCE_SINGLE_COIL:
case PRESET_SINGLE_REG:
clen = 8;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1;
else result = -1;
}
break;
case ERROR_REG:
clen = 6;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1;
else result = -1;
}
break;
case FW_FLASH_ERASE_CMD:
clen = 5;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2;
else result = -1;
}
break;
case FW_FLASH_WRITE_CMD:
clen = 5;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2;
else result = -1;
}
break;
default:
result = -1;
break;
}
}
return result;
}
public static short[] SerialRxProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
short[] result = new short[2];
switch (rData[1])
{
case READ_HOLDING_REG: // 0x03
ReadHoldingRegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case READ_INPUT_REG: // 0x04
ReadInputRegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case READ_WRITE_REG: // 0x17
//ReadSP1RegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case SPECIAL_REG_02: // 0x19
//ReadInputRegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case READ_DEV_ID: // 0x2B
ReadDevIdRegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case PRESET_MULTI_REG:
// read_holding_reg_process(reverse16(rsp->start_addr, true), reverse16(rsp->qty_reg, true));
//result[0] = 1;
//result[1] = 1;
break;
case ERROR_REG:
result[0] = 2;
result[1] = (short)((rData[0] << 8) | rData[1]);
break;
}
return result;
}
private static void ReadCoilRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = rData[i];
i++;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i + j]);
SetCoilRegister((short)(rRegAddr + j), reg_value, ref rSystemData);
i++;
}
}
private static void ReadHoldingRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetHoldingRegister((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static void ReadInputRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetInputRegister((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static void ReadDevIdRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int cPos = 7;
int alen = 0;
int regCount = rData[7];
int oID = 0;
for (int i = 0; i < regCount; i++)
{
oID = rData[cPos + 1];
alen = rData[cPos + 2];
byte[] tmp = new byte[alen];
for (int j = 0; j < alen; j++) { tmp[j] = rData[cPos + 3 + j]; }
switch (oID)
{
case 0x00: rSystemData.Information.VendorName = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x01: rSystemData.Information.ProductCode = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x02: rSystemData.Information.MajorMinorRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x05: rSystemData.Information.ModelName = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x82: rSystemData.Information.HwSerialNumber = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x83: rSystemData.Information.HwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x84: rSystemData.Information.ManufacturingDate = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x86: rSystemData.Information.SwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
}
cPos += alen + 2;
if (rLen < (cPos + 3))
{
break;
}
}
}
private static void ReadSP2RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetSP2Register((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static void ReadSP1RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetSP1Register((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static readonly int CURRENT_OFFSET = 10000;
private static readonly int TEMP_OFFSET = 400;
private static short MakeWarningData_AMG(short reg_value)
{
byte[] reg_byte = new byte[2];
ushort result = 0;
reg_byte[1] = (byte)(reg_value >> 8);
reg_byte[0] = (byte)(reg_value >> 0);
if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage
if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage
if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage
if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage
if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Charge Over Current
if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Discharge Over Current
if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 14); // ENV Over Temperature
if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 15); // ENV Under Temperature
if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature
if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature
if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature
if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature
if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 11); // SOC Low Alarm
if (((reg_byte[1] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 9); // Diff Voltage Alarm
if (((reg_byte[1] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 13); // CB On/OFF (1: OFF, 0: ON)
if (((reg_byte[1] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 12); // reserved
return (short)result;
}
private static short MakeProtectData_AMG(short reg_value)
{
byte[] reg_byte = new byte[2];
ushort result = 0;
reg_byte[1] = (byte)(reg_value >> 8);
reg_byte[0] = (byte)(reg_value >> 0);
if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage
if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage
if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage
if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage
if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 1
if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 2
if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 1
if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 2
if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 8); // SC Protect / CB off
if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature
if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature
if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature
if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature
return (short)result;
}
private static void MakeAlarm(ref DeviceSystemData rSystemData)
{
if (((rSystemData.StatusData.faultstatus >> 14) & 0x0001) == 0x0001)
{
rSystemData.StatusData.batteryStatus = 4; // Anti-theft Gyroscope
}
else if (((rSystemData.StatusData.faultstatus >> 15) & 0x0001) == 0x0001)
{
rSystemData.StatusData.batteryStatus = 5; // Anti-theft Comm.
}
else if (rSystemData.StatusData.protection != 0x0000)
{
rSystemData.StatusData.batteryStatus = 2;
}
else if (rSystemData.StatusData.warning != 0x0000)
{
rSystemData.StatusData.batteryStatus = 1;
}
else
{
rSystemData.StatusData.batteryStatus = 0;
}
}
private static void SetHoldingRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
//100 ~111 : Model_Product Name
case 100:
case 101:
case 102:
case 103:
case 104:
case 105:
case 106:
case 107:
case 108:
case 109:
case 110:
case 111:
int mReg = reg_addr - 100;
rSystemData.Information.Model_Byte[(mReg * 2) + 0] = (byte)(reg_value >> 8);
rSystemData.Information.Model_Byte[(mReg * 2) + 1] = (byte)(reg_value >> 0);
if (reg_addr == 111)
{
rSystemData.Information.ModelName = Encoding.Default.GetString(rSystemData.Information.Model_Byte).Trim('\0');
}
break;
//112 ~114 : FW Version
case 112:
case 113:
case 114:
int fReg = reg_addr - 112;
rSystemData.Information.FwVer_Byte[(fReg * 2) + 0] = (byte)(reg_value >> 8);
rSystemData.Information.FwVer_Byte[(fReg * 2) + 1] = (byte)(reg_value >> 0);
if (reg_addr == 114)
{
rSystemData.Information.SwProductRev = Encoding.Default.GetString(rSystemData.Information.FwVer_Byte).Trim('\0');
}
break;
//115 ~ 122 : BMS Serial number
case 115:
case 116:
case 117:
case 118:
case 119:
case 120:
case 121:
case 122:
int snReg = reg_addr - 115;
rSystemData.Information.BMS_SN[(snReg * 2) + 0] = (byte)(reg_value >> 8);
rSystemData.Information.BMS_SN[(snReg * 2) + 1] = (byte)(reg_value >> 0);
if (reg_addr == 122)
{
rSystemData.Information.HwSerialNumber = Encoding.Default.GetString(rSystemData.Information.BMS_SN).Trim('\0');
}
break;
//123 ~ 127 : Manufacturer
case 123:
case 124:
case 125:
case 126:
case 127:
int mnReg = reg_addr - 123;
rSystemData.Information.Vendor_Byte[(mnReg * 2) + 0] = (byte)(reg_value >> 8);
rSystemData.Information.Vendor_Byte[(mnReg * 2) + 1] = (byte)(reg_value >> 0);
if (reg_addr == 127)
{
rSystemData.Information.VendorName = Encoding.Default.GetString(rSystemData.Information.Vendor_Byte).Trim('\0');
}
break;
default:
break;
}
}
private static void SetInputRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x0FFF:
rSystemData.ValueData.voltageOfPack = (short)(reg_value / 10);
rSystemData.active = true;
break; // 48.00V = 4800
case 0x1000: rSystemData.ValueData.current = (short)(reg_value - CURRENT_OFFSET); break; // 100.0A = 1000 -10000 = 0;
case 0x1001: rSystemData.ValueData.remainingCapacity = (short)(reg_value / 1); break; // 100.0Ah = 1000
case 0x1002: rSystemData.ValueData.Ext1Temperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100
case 0x1003: rSystemData.ValueData.Ext2Temperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100
case 0x1004: rSystemData.StatusData.warning = MakeWarningData_AMG(reg_value); break; // Warning Status
case 0x1005: rSystemData.StatusData.protection = MakeProtectData_AMG(reg_value); break; // Protection Status
case 0x1006: // Fault Status
rSystemData.StatusData.faultstatus = (short)(reg_value / 1);
rSystemData.StatusData.status = (short)((reg_value >> 8) & 0x0003);
MakeAlarm(ref rSystemData);
break;
case 0x1007: rSystemData.ValueData.rSOC = (short)(reg_value / 10); break; // 100.00% = 10000
case 0x1008: rSystemData.ValueData.stateOfHealth = (short)(reg_value / 10); break; // 100.00% = 10000
case 0x1009: rSystemData.ValueData.fullChargeCapacity = (short)(reg_value / 1); break; // 100.0Ah = 1000
case 0x100A: rSystemData.ValueData.cycleCount = (short)(reg_value / 1); break; // 100 cycles = 100
case 0x100B: rSystemData.ValueData.NumOfCells = (short)(reg_value / 1); break; // 15 cells = 15
case 0x100C: // Cell Voltage #1
case 0x100D: // Cell Voltage #2
case 0x100E: // Cell Voltage #3
case 0x100F: // Cell Voltage #4
case 0x1010: // Cell Voltage #5
case 0x1011: // Cell Voltage #6
case 0x1012: // Cell Voltage #7
case 0x1013: // Cell Voltage #8
case 0x1014: // Cell Voltage #9
case 0x1015: // Cell Voltage #10
case 0x1016: // Cell Voltage #11
case 0x1017: // Cell Voltage #12
case 0x1018: // Cell Voltage #13
case 0x1019: // Cell Voltage #14
case 0x101A: // Cell Voltage #15
case 0x101B: // Cell Voltage #16
case 0x101C: // Cell Voltage #17
case 0x101D: // Cell Voltage #18
case 0x101E: // Cell Voltage #19
case 0x101F: // Cell Voltage #20
case 0x1020: // Cell Voltage #21
case 0x1021: // Cell Voltage #22
case 0x1022: // Cell Voltage #23
case 0x1023: // Cell Voltage #24
case 0x1024: // Cell Voltage #25
case 0x1025: // Cell Voltage #26
case 0x1026: // Cell Voltage #27
case 0x1027: // Cell Voltage #28
case 0x1028: // Cell Voltage #29
case 0x1029: // Cell Voltage #30
case 0x102A: // Cell Voltage #31
case 0x102B: // Cell Voltage #32
case 0x102C: // Cell Voltage #33
case 0x102D: // Cell Voltage #34
case 0x102E: // Cell Voltage #35
case 0x102F: // Cell Voltage #36
case 0x1030: // Cell Voltage #37
case 0x1031: // Cell Voltage #38
case 0x1032: // Cell Voltage #39 - 3.256V = 3256
int cNo = reg_addr - 0x100C;
if (cNo < rSystemData.ValueData.CellVoltage.Length)
{
rSystemData.ValueData.CellVoltage[cNo] = (ushort)(reg_value / 1);
}
csUtils.MakeMaxAvgMinCellVoltage(ref rSystemData, 39);
break;
case 0x1033: rSystemData.ValueData.NumOfTemps = (short)(reg_value / 1); break; // 5 temps = 5
case 0x1034: rSystemData.ValueData.CellTemperature[0] = (short)(reg_value - TEMP_OFFSET); break;
case 0x1035: rSystemData.ValueData.CellTemperature[1] = (short)(reg_value - TEMP_OFFSET); break;
case 0x1036: rSystemData.ValueData.CellTemperature[2] = (short)(reg_value - TEMP_OFFSET); break;
case 0x1037: rSystemData.ValueData.CellTemperature[3] = (short)(reg_value - TEMP_OFFSET); break;
case 0x1038: rSystemData.ValueData.CellTemperature[4] = (short)(reg_value - TEMP_OFFSET); break;
case 0x1039: rSystemData.ValueData.CellTemperature[5] = (short)(reg_value - TEMP_OFFSET); break;
case 0x103A: rSystemData.ValueData.CellTemperature[6] = (short)(reg_value - TEMP_OFFSET); break;
case 0x103B: // 25.3C = 253 - 400 = -147 (Offset -400)
rSystemData.ValueData.CellTemperature[7] = (short)(reg_value - TEMP_OFFSET);
csUtils.MakeMaxAvgMinTemperature(ref rSystemData, 8);
break;
case 0x103C: rSystemData.MaxValue.MaxChgCurrent = (short)(reg_value); break; // Max. Charge Current
case 0x103D: rSystemData.MaxValue.MaxChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Max. Charge Temperature
case 0x103E: rSystemData.MaxValue.MinChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Min. Charge Temperature
case 0x103F: rSystemData.MaxValue.FloatChgVolt = (short)(reg_value / 10); break; // Float Charge Current
case 0x1040: rSystemData.MaxValue.BoostChgVolt = (short)(reg_value / 10); break; // Boost Charge Current
case 0x3000: rSystemData.CalibrationData.AntiTheftComm.TimeOut = (short)(reg_value / 1); break;
case 0x3002: rSystemData.CalibrationData.AntiTheftComm.FuncSwitch = (short)(reg_value / 1); break;
case 0x4000: rSystemData.CalibrationData.AntiTheftGyro.XAxis = (short)(reg_value / 1); break;
case 0x4001: rSystemData.CalibrationData.AntiTheftGyro.YAxis = (short)(reg_value / 1); break;
case 0x4002: rSystemData.CalibrationData.AntiTheftGyro.ZAxis = (short)(reg_value / 1); break;
case 0x4003: rSystemData.CalibrationData.AntiTheftGyro.GyroPolicySel = (short)(reg_value / 1); break;
case 0x4004: rSystemData.CalibrationData.AntiTheftGyro.GyroFuncSwitch = (short)(reg_value / 1); break;
case 0x4006: rSystemData.CalibrationData.AntiTheftGyro.GyroState = (short)(reg_value / 1); break;
default:
break;
}
}
private static void SetSP1Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; //
case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; //
case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; //
case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; //
default:
break;
}
}
private static void SetSP2Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x3000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x3002: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
default:
break;
}
}
private static void SetReadIdRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; //
case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; //
case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; //
case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; //
default:
break;
}
}
private static void SetCoilRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x3078:
rSystemData.StatusData.relayStatus = reg_value;
rSystemData.CalibrationData.FetCalib.FetStatus = reg_value;
break;
case 0x502E:
rSystemData.CalibrationData.Current.ChargeOption = reg_value;
break;
}
}
private static short MakeUartWarningData(short rdata)
{
short result = 0;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001Pack OV
if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002Cell OV
if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004Pack UV
if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008Cell UV
if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010Charging OC
if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020Discharging OC
if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Tempratuer
if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Tempratuer
if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Tempratuer
if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Tempratuer
if (bAlarm[12] == true) result |= (short)(1 << 11); // 0x0200SOC Low
return result;
}
private static short MakeUartTripData(short rdata)
{
short result = 0;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001Pack OV
if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002Cell OV
if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004Pack UV
if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008Cell UV
if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010Charging OC
if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020Discharging OC
if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Temprature
if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Temprature
if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Temprature
if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Temprature
if (bAlarm[13] == true) result |= (short)(1 << 9); // 0x0200Short Circuit Protection
return result;
}
private static short MakeUartErrorData(short rdata, short cdata)
{
short result = cdata;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 9); // 0x0001Voltage error
if (bAlarm[1] == true) result |= (short)(1 << 9); // 0x0002Temperature error
if (bAlarm[2] == true) result |= (short)(1 << 9); // 0x0004: 电流检测Error
if (bAlarm[3] == true) result |= (short)(1 << 9); // 0x0010Cell unbalance
return result;
}
}
}