2941 lines
62 KiB
C
2941 lines
62 KiB
C
/**
|
||
******************************************************************************
|
||
* @file InverterSwitch_Page2.c
|
||
* @author -
|
||
* @version -
|
||
* @date 2026.3.26
|
||
* @brief -
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
|
||
/* Includes ------------------------------------------------------------------*/
|
||
#include "stm32f10x.h"
|
||
#include "global.h"
|
||
|
||
|
||
//这里放的是基本款的第2页函数,不根据发货要求变动
|
||
//CAN:
|
||
//13.SMA 14.Sunways 15.Luxpower 16.Schneider
|
||
//17.AlpSolarr
|
||
//Modbus:
|
||
//18.SRNE 19.Voltronic 20.COSUPER
|
||
//21.SMK 22.SAKO 23.SNADI 24.invt
|
||
|
||
|
||
//SMA 艾思玛
|
||
void CAN_Protocol_SMA(void)
|
||
{
|
||
uint8_t data[8];
|
||
uint16_t totalCapacity;
|
||
|
||
int16_t tempVol;
|
||
int16_t tempCur;
|
||
|
||
uint16_t chgVolLimit;
|
||
uint16_t dsgVolLimit;
|
||
int16_t chgCurLimit;
|
||
int16_t dsgCurLimit;
|
||
|
||
uint8_t protectByte1 = 0;
|
||
uint8_t protectByte2 = 0;
|
||
uint8_t protectByte3 = 0;
|
||
uint8_t protectByte4 = 0;
|
||
|
||
uint8_t alarmByte1 = 0;
|
||
uint8_t alarmByte2 = 0;
|
||
uint8_t alarmByte3 = 0;
|
||
uint8_t alarmByte4 = 0;
|
||
|
||
|
||
int16_t T_Average; // 平均温度
|
||
|
||
|
||
//Data0 BIT0.1 General[Cancel] //0000 0010
|
||
protectByte1 |= 0x02;
|
||
|
||
//保护
|
||
//放电高温保护
|
||
//over temp at discharging
|
||
if(((canMem[0].status_byte2 & 0x0008) != 0) || ((canMem[0].status_byte4 & 0x0202) != 0))
|
||
{
|
||
protectByte1 &= 0x7f;
|
||
protectByte1 |= 0x40;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xbf;
|
||
protectByte1 |= 0x80;
|
||
}
|
||
|
||
//欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
protectByte1 &= 0xdf;
|
||
protectByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xef;
|
||
protectByte1 |= 0x20;
|
||
}
|
||
|
||
// //过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte1 & 0x0141) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// protectByte1 &= 0xf7; //去掉leave
|
||
// protectByte1 |= 0x04; //赋值arrive
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfb;
|
||
// protectByte1 |= 0x08;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfb;
|
||
// protectByte1 |= 0x08;
|
||
// }
|
||
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte2 &= 0x7f;
|
||
protectByte2 |= 0x40;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xbf;
|
||
protectByte2 |= 0x80;
|
||
}
|
||
|
||
//充电低温保护
|
||
//Data1 BIT4.5 under temp at charging //0001 0000
|
||
if( ((canMem[0].status_byte2 & 0x0001) != 0) || ((canMem[0].status_byte4 & 0x0404) != 0) )
|
||
{
|
||
protectByte2 &= 0xdf;
|
||
protectByte2 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xef;
|
||
protectByte2 |= 0x20;
|
||
}
|
||
|
||
//充电高温保护
|
||
//Data1 BIT2.3 over temp at charging //0000 0100
|
||
if( ((canMem[0].status_byte2 & 0x0002) != 0) || ((canMem[0].status_byte4 & 0x0101) != 0) )
|
||
{
|
||
protectByte2 &= 0xf7;
|
||
protectByte2 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xfb;
|
||
protectByte2 |= 0x08;
|
||
}
|
||
|
||
//放电低温保护
|
||
//Data1 BIT0.1 under temp at discharging //0000 0001
|
||
if( ((canMem[0].status_byte2 & 0x0004) != 0) || ((canMem[0].status_byte4 & 0x0808) != 0) )
|
||
{
|
||
protectByte2 &= 0xfd;
|
||
protectByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xfe;
|
||
protectByte2 |= 0x02;
|
||
}
|
||
|
||
//短路
|
||
//Data2 BIT4.5 short circuit //0001 0000
|
||
if((canMem[0].status_byte1 & 0x20) != 0)
|
||
{
|
||
protectByte3 &= 0xdf;
|
||
protectByte3 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte3 &= 0xef;
|
||
protectByte3 |= 0x20;
|
||
}
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte3 &= 0xfd;
|
||
protectByte3 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte3 &= 0xfe;
|
||
protectByte3 |= 0x02;
|
||
}
|
||
//Data2 BIT2.3 Contactor[Cancel] //0000 1000
|
||
protectByte3 |= 0x08;
|
||
//Data2 BIT6.7 BMS internal[Cancel] //1000 0000
|
||
protectByte3 |= 0x80;
|
||
// //Data3 BIT0.1 cell imbanlance //0000 0001
|
||
// if((bmsMem.balanceStatus & 0x01) !=0) //0x01表示平衡
|
||
// {
|
||
// protectByte4 &= 0xfe;
|
||
// protectByte4 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte4 &= 0xfd;
|
||
// protectByte4 |= 0x01;
|
||
// }
|
||
|
||
|
||
//告警
|
||
//放电高温告警
|
||
//over temp at discharging
|
||
if(((canMem[0].status_byte2 & 0x2200) != 0) || ((canMem[0].status_byte4 & 0x2000) != 0))
|
||
{
|
||
alarmByte1 &= 0x7f;
|
||
alarmByte1 |= 0x40;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xbf;
|
||
alarmByte1 |= 0x80;
|
||
}
|
||
|
||
//欠压告警
|
||
if((canMem[0].status_byte3 & 0x0A00) != 0)
|
||
{
|
||
alarmByte1 &= 0xdf;
|
||
alarmByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xef;
|
||
alarmByte1 |= 0x20;
|
||
}
|
||
|
||
// //过压告警
|
||
// if((canMem[0].status_byte3 & 0x0500) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte1 &= 0xf7; //去掉leave
|
||
// alarmByte1 |= 0x04; //赋值arrive
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfb;
|
||
// alarmByte1 |= 0x08;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfb;
|
||
// alarmByte1 |= 0x08;
|
||
// }
|
||
|
||
//放电过流告警
|
||
if((canMem[0].status_byte3 & 0x2000) != 0)
|
||
{
|
||
alarmByte2 &= 0x7f;
|
||
alarmByte2 |= 0x40;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xbf;
|
||
alarmByte2 |= 0x80;
|
||
}
|
||
|
||
//充电低温告警
|
||
//Data1 BIT4.5 under temp at charging //0001 0000
|
||
if( ((canMem[0].status_byte2 & 0x4400) != 0) || ((canMem[0].status_byte4 & 0x4000) != 0) )
|
||
{
|
||
alarmByte2 &= 0xdf;
|
||
alarmByte2 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xef;
|
||
alarmByte2 |= 0x20;
|
||
}
|
||
|
||
//充电高温告警
|
||
//Data1 BIT2.3 over temp at charging //0000 0100
|
||
if( ((canMem[0].status_byte2 & 0x1100) != 0) || ((canMem[0].status_byte4 & 0x1000) != 0) )
|
||
{
|
||
alarmByte2 &= 0xf7;
|
||
alarmByte2 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xfb;
|
||
alarmByte2 |= 0x08;
|
||
}
|
||
|
||
//放电低温告警
|
||
//Data1 BIT0.1 under temp at discharging //0000 0001
|
||
if( ((canMem[0].status_byte2 & 0x8800) != 0) || ((canMem[0].status_byte4 & 0x8000) != 0) )
|
||
{
|
||
alarmByte2 &= 0xfd;
|
||
alarmByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xfe;
|
||
alarmByte2 |= 0x02;
|
||
}
|
||
|
||
//短路
|
||
//Data2 BIT4.5 short circuit //0001 0000
|
||
if((canMem[0].status_byte1 & 0x20) != 0)
|
||
{
|
||
alarmByte3 &= 0xdf;
|
||
alarmByte3 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
alarmByte3 &= 0xef;
|
||
alarmByte3 |= 0x20;
|
||
}
|
||
|
||
//充电过流告警
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte3 &= 0xfd;
|
||
alarmByte3 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
alarmByte3 &= 0xfe;
|
||
alarmByte3 |= 0x02;
|
||
}
|
||
|
||
// if((bmsMem.balanceStatus & 0x01) !=0) //0x01表示平衡
|
||
// {
|
||
// alarmByte4 &= 0xfe;
|
||
// alarmByte4 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte4 &= 0xfd;
|
||
// alarmByte4 |= 0x01;
|
||
// }
|
||
|
||
|
||
if(CAN_SendCount ==0) //ID=0x35a - Alarms/Warnings
|
||
{
|
||
data[0] = protectByte1;
|
||
data[1] = protectByte2;
|
||
data[2] = protectByte3;
|
||
data[3] = protectByte4;
|
||
data[4] = alarmByte1; //报警和保护信号相同
|
||
data[5] = alarmByte2;
|
||
data[6] = alarmByte3;
|
||
data[7] = alarmByte4;
|
||
CAN1_SendData(0x35a, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==1) //ID = 0x351 - 电池充电/放电电压,充电/放电限流
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
chgCurLimit = 0; //SMA禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
dsgCurLimit = 0; //SMA禁放
|
||
}
|
||
else
|
||
{
|
||
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
data[0] = chgVolLimit & 0xFF; //充电电压限制低位
|
||
data[1] = (chgVolLimit >> 8) & 0xFF;
|
||
data[2] = chgCurLimit & 0xFF; //充电电流限制低位
|
||
data[3] = (chgCurLimit >> 8) & 0xFF;
|
||
data[4] = dsgCurLimit & 0xFF; //放电电流限制低位
|
||
data[5] = (dsgCurLimit >> 8) & 0xFF;
|
||
data[6] = dsgVolLimit & 0xFF; //放电电压限制低位
|
||
data[7] = (dsgVolLimit >> 8) & 0xFF;
|
||
CAN1_SendData(0x351, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==2) //ID = 0x355 - 电量SOC/SOH
|
||
{
|
||
data[0] = canMem[0].soc & 0xFF; //SOC
|
||
data[1] = 0;
|
||
data[2] = canMem[0].soh & 0xFF; //SOH
|
||
data[3] = 0;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x355, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==3) //ID = 0x356 - 电池电压/电流/温度
|
||
{
|
||
tempVol = (uint16_t)(bmsMem.packVoltage/10); //单位0.01
|
||
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
|
||
T_Average = canMem[0].temp;// 平均温度
|
||
|
||
data[0] = tempVol & 0xFF;
|
||
data[1] = (tempVol >>8) & 0xFF; //电池包电压
|
||
data[2] = tempCur & 0xFF;
|
||
data[3] = (tempCur >>8) & 0xFF; //电池包电流
|
||
data[4] = (T_Average -2731) & 0xFF;;
|
||
data[5] = ((T_Average -2731) >>8) & 0xFF; //温度-暂时取平均温度,具体哪一路需要客户确认
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x356, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==4) //ID = 0x35e - 制造商名称-ASCII
|
||
{
|
||
data[0] = 'B';
|
||
data[1] = 'T';
|
||
data[2] = 'Y';
|
||
data[3] = 'G';
|
||
data[4] = '-';
|
||
data[5] = 'B';
|
||
data[6] = 'M';
|
||
data[7] = 'S';
|
||
CAN1_SendData(0x35e, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==5) //ID = 0x35f - 电池类型,BMS版本,电池容量,保留的制造商ID
|
||
{
|
||
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
|
||
|
||
data[0] = 0X00;
|
||
data[1] = 0X00;
|
||
data[2] = 0X00; //版本号暂无
|
||
data[3] = 0X00;
|
||
data[4] = totalCapacity & 0xFF; //电池容量
|
||
data[5] = (totalCapacity >> 8) & 0xFF;
|
||
data[6] = 0X00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35f, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount>=6)
|
||
{
|
||
CAN_SendCount = 0;
|
||
}
|
||
}
|
||
|
||
//Sunways 尚唯斯
|
||
void CAN_Protocol_Sunways(void)
|
||
{
|
||
uint8_t data[8];
|
||
uint16_t totalCapacity;
|
||
|
||
uint16_t tempVol;
|
||
int16_t tempCur;
|
||
|
||
uint16_t chgVolLimit;
|
||
uint16_t dsgVolLimit;
|
||
int16_t chgCurLimit = bmsMem.inverter_chgCurLimit;
|
||
int16_t dsgCurLimit = bmsMem.inverter_dsgCurLimit;
|
||
|
||
uint8_t protectByte1 = 0;
|
||
uint8_t protectByte2 = 0;
|
||
|
||
int16_t T_Average; // 平均温度
|
||
|
||
uint8_t alarmByte1 = 0;
|
||
uint8_t alarmByte2 = 0;
|
||
|
||
uint8_t alarmByte3 = 0; //0x399传输告警位
|
||
uint8_t status = 0; //0x399传输状态位
|
||
uint8_t protectByte3 = 0; //0x399传输故障位
|
||
|
||
|
||
//保护
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte1 |= 0x80;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0x7f;
|
||
}
|
||
|
||
//低温保护
|
||
//under temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x0005) != 0) || ((canMem[0].status_byte4 & 0x0C0C) != 0))
|
||
{
|
||
protectByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xef;
|
||
}
|
||
|
||
//过温保护
|
||
//over temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x000A) != 0) || ((canMem[0].status_byte4 & 0x0303) != 0))
|
||
{
|
||
protectByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xf7;
|
||
}
|
||
|
||
//欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
protectByte1 |= 0x04;
|
||
alarmByte3 |= 0x02;
|
||
protectByte3 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xfb;
|
||
alarmByte3 &= 0xfd;
|
||
protectByte3 &= 0xfb;
|
||
}
|
||
|
||
// //过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte1 & 0x0141) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// protectByte1 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfd;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfd;
|
||
// }
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xfe;
|
||
}
|
||
|
||
//告警
|
||
//放电过流告警
|
||
if((canMem[0].status_byte3 & 0x2000) != 0)
|
||
{
|
||
alarmByte1 |= 0x80;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0x7f;
|
||
}
|
||
|
||
//低温告警
|
||
if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0))
|
||
{
|
||
alarmByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xef;
|
||
}
|
||
|
||
//过温告警
|
||
if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0))
|
||
{
|
||
alarmByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xf7;
|
||
}
|
||
|
||
//欠压告警
|
||
if((canMem[0].status_byte3 & 0x0A00) != 0)
|
||
{
|
||
alarmByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xfb;
|
||
}
|
||
|
||
// //过压告警
|
||
// if((canMem[0].status_byte3 & 0x0500) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte1 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfd;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfd;
|
||
// }
|
||
|
||
//充电过流告警
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xfe;
|
||
}
|
||
|
||
|
||
if(CAN_SendCount ==0) //ID=0x359
|
||
{
|
||
data[0] = protectByte1;
|
||
data[1] = protectByte2;
|
||
data[2] = alarmByte1;
|
||
data[3] = alarmByte2;
|
||
data[4] = OnlineNum;
|
||
data[5] = 0x50;
|
||
data[6] = 0x4E;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x359, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==1) //ID = 0x351
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
chgCurLimit = 0; //Sol-Ark禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
dsgCurLimit = 0; //Sol-Ark禁放
|
||
}
|
||
else
|
||
{
|
||
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
data[0] = chgVolLimit & 0xFF; //充电电压限制低位
|
||
data[1] = (chgVolLimit >> 8) & 0xFF;
|
||
data[2] = chgCurLimit & 0xFF; //充电电流限制低位
|
||
data[3] = (chgCurLimit >> 8) & 0xFF;
|
||
data[4] = dsgCurLimit & 0xFF; //放电电流限制低位
|
||
data[5] = (dsgCurLimit >> 8) & 0xFF;
|
||
data[6] = dsgVolLimit & 0xFF; //放电电压限制低位
|
||
data[7] = (dsgVolLimit >> 8) & 0xFF;
|
||
CAN1_SendData(0x351, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==2)
|
||
{
|
||
data[0] = canMem[0].soc & 0xFF; //SOC
|
||
data[1] = 0;
|
||
data[2] = canMem[0].soh & 0xFF; //SOH
|
||
data[3] = 0;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x355, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==3)
|
||
{
|
||
tempVol = (uint16_t)(bmsMem.packVoltage/10); //单位0.01
|
||
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
|
||
T_Average = canMem[0].temp;// 平均温度
|
||
|
||
data[0] = tempVol & 0xFF;
|
||
data[1] = (tempVol >>8) & 0xFF; //电池包电压
|
||
data[2] = tempCur & 0xFF;
|
||
data[3] = (tempCur >>8) & 0xFF; //电池包电流
|
||
data[4] = (T_Average -2731) & 0xFF;;
|
||
data[5] = ((T_Average -2731) >>8) & 0xFF; //温度-暂时取平均温度,具体哪一路需要客户确认
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x356, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==4)
|
||
{
|
||
status = 0x03;
|
||
if(chg_forbidFlg == 1)//sunways
|
||
{
|
||
status &= ~0x01; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//sunways
|
||
{
|
||
status &= ~0x02; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//sunways
|
||
{
|
||
status |= ~0x04; //强充
|
||
}
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = alarmByte3;
|
||
data[3] = status;
|
||
data[4] = protectByte3;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x399, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==5)
|
||
{
|
||
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
|
||
|
||
data[0] = 0x00;//电池类型
|
||
data[1] = 0x00;
|
||
data[2] = VersionMem.Software[0] & 0xFF;//BMS版本号,仅传输大版本号及小修改
|
||
data[3] = VersionMem.Software[3] & 0xFF;
|
||
data[4] = totalCapacity & 0xFF; //容量
|
||
data[5] = (totalCapacity >> 8) & 0xFF;
|
||
data[6] = 0x00;//制造商ID
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35F, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==6)
|
||
{
|
||
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
|
||
if(chg_forbidFlg == 1)//sunways
|
||
{
|
||
RequestFlag &= 0x7F; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//sunways
|
||
{
|
||
RequestFlag &= 0xBF; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//sunways
|
||
{
|
||
RequestFlag |= 0x20; //强充
|
||
}
|
||
|
||
data[0] = RequestFlag;
|
||
data[1] = 0x00;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35C, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==7) //0x370
|
||
{
|
||
data[0] = bmsMem.vCell[0] & 0xFF; //电芯N电压
|
||
data[1] = (bmsMem.vCell[0] >> 8) & 0xFF;
|
||
data[2] = bmsMem.vCell[1] & 0xFF; //电芯N+1电压
|
||
data[3] = (bmsMem.vCell[1] >> 8) & 0xFF;
|
||
data[4] = bmsMem.vCell[2] & 0xFF; //电芯N+2电压
|
||
data[5] = (bmsMem.vCell[2] >> 8) & 0xFF;
|
||
data[6] = bmsMem.vCell[3] & 0xFF; //电芯N+3电压
|
||
data[7] = (bmsMem.vCell[3] >> 8) & 0xFF;
|
||
CAN1_SendData(0x370, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==8) //0x371
|
||
{
|
||
data[0] = bmsMem.vCell[4] & 0xFF; //电芯N+4电压
|
||
data[1] = (bmsMem.vCell[4] >> 8) & 0xFF;
|
||
data[2] = bmsMem.vCell[5] & 0xFF; //电芯N+5电压
|
||
data[3] = (bmsMem.vCell[5] >> 8) & 0xFF;
|
||
data[4] = bmsMem.vCell[6] & 0xFF; //电芯N+6电压
|
||
data[5] = (bmsMem.vCell[6] >> 8) & 0xFF;
|
||
data[6] = bmsMem.vCell[7] & 0xFF; //电芯N+7电压
|
||
data[7] = (bmsMem.vCell[7] >> 8) & 0xFF;
|
||
CAN1_SendData(0x371, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==9) //0x372
|
||
{
|
||
data[0] = bmsMem.vCell[8] & 0xFF; //电芯N+8电压
|
||
data[1] = (bmsMem.vCell[8] >> 8) & 0xFF;
|
||
data[2] = bmsMem.vCell[9] & 0xFF; //电芯N+9电压
|
||
data[3] = (bmsMem.vCell[9] >> 8) & 0xFF;
|
||
data[4] = bmsMem.vCell[10] & 0xFF; //电芯N+10电压
|
||
data[5] = (bmsMem.vCell[10] >> 8) & 0xFF;
|
||
data[6] = bmsMem.vCell[11] & 0xFF; //电芯N+11电压
|
||
data[7] = (bmsMem.vCell[11] >> 8) & 0xFF;
|
||
CAN1_SendData(0x372, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==10) //0x373
|
||
{
|
||
data[0] = bmsMem.vCell[12] & 0xFF; //电芯N+12电压
|
||
data[1] = (bmsMem.vCell[12] >> 8) & 0xFF;
|
||
data[2] = bmsMem.vCell[13] & 0xFF; //电芯N+13电压
|
||
data[3] = (bmsMem.vCell[13] >> 8) & 0xFF;
|
||
data[4] = bmsMem.vCell[14] & 0xFF; //电芯N+14电压
|
||
data[5] = (bmsMem.vCell[14] >> 8) & 0xFF;
|
||
data[6] = bmsMem.vCell[15] & 0xFF; //电芯N+15电压
|
||
data[7] = (bmsMem.vCell[15] >> 8) & 0xFF;
|
||
CAN1_SendData(0x373, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==11) //0x3D0
|
||
{
|
||
data[0] = ((bmsMem.mcu_T1 - 2731)/10 + 50) & 0xFF;
|
||
data[1] = ((bmsMem.mcu_T2 - 2731)/10 + 50) & 0xFF;
|
||
data[2] = ((bmsMem.mcu_T3 - 2731)/10 + 50) & 0xFF;
|
||
data[3] = ((bmsMem.mcu_T4 - 2731)/10 + 50) & 0xFF;
|
||
data[4] = ((bmsMem.afe_T1 - 2731)/10 + 50) & 0xFF;
|
||
data[5] = ((bmsMem.afe_T2 - 2731)/10 + 50) & 0xFF;;
|
||
data[6] = ((bmsMem.afe_T3 - 2731)/10 + 50) & 0xFF;;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x3D0, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==12) //0x3DA
|
||
{
|
||
data[0] = bmsMem.can_VolMax & 0xFF;
|
||
data[1] = (bmsMem.can_VolMax >>8) & 0xFF;
|
||
data[2] = bmsMem.can_VolMin & 0xFF;
|
||
data[3] = (bmsMem.can_VolMin >>8) & 0xFF;
|
||
data[4] = (bmsMem.can_VolMaxIndex + 1) & 0xFF;
|
||
data[5] = (bmsMem.can_VolMinIndex + 1) & 0xFF;
|
||
data[6] = 0X00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x3DA, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==13) //0x3DB
|
||
{
|
||
data[0] = ((bmsMem.can_TempMax - 2731)/10 + 50) & 0xFF;
|
||
data[1] = (((bmsMem.can_TempMax - 2731)/10 + 50) >>8) & 0xFF;
|
||
data[2] = ((bmsMem.can_TempMin - 2731)/10 + 50) & 0xFF;
|
||
data[3] = (((bmsMem.can_TempMin - 2731)/10 + 50) >>8) & 0xFF;
|
||
data[4] = (bmsMem.can_TempMaxIndex + 1) & 0xFF;
|
||
data[5] = (bmsMem.can_TempMinIndex + 1) & 0xFF;
|
||
data[6] = 0X00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x3DB, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount ==14) //0x35E
|
||
{
|
||
data[0] = 0x50; //制造商名称
|
||
data[1] = 0x4E;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35E, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount>=15)
|
||
{
|
||
CAN_SendCount = 0;
|
||
}
|
||
|
||
}
|
||
//Lux power 深圳鹏城
|
||
void CAN_Protocol_Luxpower(void)
|
||
{
|
||
uint8_t data[8];
|
||
uint16_t totalCapacity;//总容量
|
||
|
||
uint16_t tempVol;
|
||
int16_t tempCur; //总电流
|
||
|
||
uint16_t chgVolLimit;
|
||
uint16_t dsgVolLimit;
|
||
int16_t chgCurLimit;
|
||
int16_t dsgCurLimit;
|
||
|
||
uint8_t protectByte1 = 0;
|
||
uint8_t protectByte2 = 0;
|
||
|
||
uint8_t alarmByte1 = 0;
|
||
uint8_t alarmByte2 = 0;
|
||
|
||
int16_t T_Max; // 最高温度
|
||
int16_t T_Min; // 最低温度
|
||
uint16_t cellVolMax=0; // 电芯单体最高电压
|
||
uint16_t cellVolMin=0; // 电芯单体最低电压
|
||
|
||
|
||
//保护
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte1 |= 0x80;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0x7f;
|
||
}
|
||
|
||
//低温保护
|
||
//under temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x0005) != 0) || ((canMem[0].status_byte4 & 0x0C0C) != 0))
|
||
{
|
||
protectByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xef;
|
||
}
|
||
|
||
//过温保护
|
||
//over temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x000A) != 0) || ((canMem[0].status_byte4 & 0x0303) != 0))
|
||
{
|
||
protectByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xf7;
|
||
}
|
||
|
||
//欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
protectByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xfb;
|
||
}
|
||
|
||
// //过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte1 & 0x0141) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// protectByte1 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfd;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xfd;
|
||
// }
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xfe;
|
||
}
|
||
|
||
//告警
|
||
//放电过流告警
|
||
if((canMem[0].status_byte3 & 0x2000) != 0)
|
||
{
|
||
alarmByte1 |= 0x80;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0x7f;
|
||
}
|
||
|
||
//低温告警
|
||
if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0))
|
||
{
|
||
alarmByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xef;
|
||
}
|
||
|
||
//过温告警
|
||
if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0))
|
||
{
|
||
alarmByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xf7;
|
||
}
|
||
|
||
//欠压告警
|
||
if((canMem[0].status_byte3 & 0x0A00) != 0)
|
||
{
|
||
alarmByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xfb;
|
||
}
|
||
|
||
// //过压告警
|
||
// if((canMem[0].status_byte3 & 0x0500) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte1 |= 0x02;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfd;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xfd;
|
||
// }
|
||
|
||
//充电过流告警
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
alarmByte2 &= 0xfe;
|
||
}
|
||
|
||
|
||
if(CAN_SendCount ==0) //ID = 0x359 --- 报警/保护、总容量
|
||
{
|
||
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
|
||
|
||
data[0] = protectByte1;
|
||
data[1] = protectByte2;
|
||
data[2] = alarmByte1;
|
||
data[3] = alarmByte2;
|
||
data[4] = OnlineNum;
|
||
data[5] = totalCapacity & 0xFF;
|
||
data[6] = (totalCapacity >> 8) & 0xFF;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x359, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==1) //ID = 0x351 --- 充/放电限压/限流
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
chgCurLimit = 0; //Luxpower禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
dsgCurLimit = 0; //Luxpower禁放
|
||
}
|
||
else
|
||
{
|
||
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
data[0] = chgVolLimit & 0xFF; //充电电压限制低位
|
||
data[1] = (chgVolLimit >> 8) & 0xFF;
|
||
data[2] = chgCurLimit & 0xFF; //充电电流限制低位
|
||
data[3] = (chgCurLimit >> 8) & 0xFF;
|
||
data[4] = dsgCurLimit & 0xFF; //放电电流限制低位
|
||
data[5] = (dsgCurLimit >> 8) & 0xFF;
|
||
data[6] = dsgVolLimit & 0xFF; //放电电压限制低位
|
||
data[7] = (dsgVolLimit >> 8) & 0xFF;
|
||
CAN1_SendData(0x351, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==2) //ID = 0x355 --- SOC/SOH、最大/小电压
|
||
{
|
||
cellVolMax = canMem[0].VolMax;
|
||
cellVolMin = canMem[0].VolMin;
|
||
|
||
data[0] = canMem[0].soc & 0xFF; //SOC
|
||
data[1] = 0;
|
||
data[2] = canMem[0].soh & 0xFF; //SOH
|
||
data[3] = 0;
|
||
data[4] = cellVolMax & 0xFF; //最大单体电压
|
||
data[5] = (cellVolMax >> 8) & 0xFF;
|
||
data[6] = cellVolMin & 0xFF; //最小单体电压
|
||
data[7] = (cellVolMin >> 8) & 0xFF;
|
||
CAN1_SendData(0x355, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==3) //ID = 0x356 --- 总电压/电流、最大/小温度
|
||
{
|
||
tempVol = (uint16_t)(bmsMem.packVoltage/10); //单位0.01
|
||
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
|
||
T_Max = canMem[0].TempMax; // 最高温度 单位0.1
|
||
T_Min = canMem[0].TempMin; // 最低温度 单位0.1
|
||
|
||
data[0] = tempVol & 0xFF;
|
||
data[1] = (tempVol >>8) & 0xFF; //电池包电压
|
||
data[2] = tempCur & 0xFF;
|
||
data[3] = (tempCur >>8) & 0xFF; //电池包电流
|
||
data[4] = (T_Max -2731) & 0xFF; //最高单体温度
|
||
data[5] = ((T_Max -2731) >> 8) & 0xFF;
|
||
data[6] = (T_Min -2731) & 0xFF; //最低单体温度
|
||
data[7] = ((T_Min -2731) >> 8) & 0xFF;
|
||
CAN1_SendData(0x356, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==4) //ID = 0x35C --- 总电压/电流、最大/小温度
|
||
{
|
||
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
|
||
if(chg_forbidFlg == 1)//Lux power
|
||
{
|
||
RequestFlag &= 0x7F; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//Lux power
|
||
{
|
||
RequestFlag &= 0xBF; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//Lux power
|
||
{
|
||
RequestFlag |= 0x20; //强充
|
||
}
|
||
|
||
data[0] = RequestFlag; //充电允许,放电允许
|
||
data[1] = 0x00;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35C, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount>=5)
|
||
{
|
||
CAN_SendCount = 0;
|
||
}
|
||
}
|
||
|
||
//Schneider 施耐德
|
||
void CAN_Protocol_Schneider(void)
|
||
{
|
||
uint8_t data[8];
|
||
uint16_t totalCapacity; //总容量
|
||
|
||
uint32_t tempVol; //总电压
|
||
int32_t tempCur; //总电流
|
||
|
||
uint32_t chgVolLimit; //充电限压
|
||
uint32_t dsgVolLimit; //放电限压
|
||
int32_t chgCurLimit; //充电限流
|
||
int32_t dsgCurLimit; //放电限流
|
||
|
||
uint8_t protectByte1 = 0; //保护位1,与告警位1值相同
|
||
|
||
uint8_t alarmByte1 = 0;
|
||
|
||
|
||
int16_t T_Average; // 平均温度
|
||
int16_t T_Max; // 最高温度
|
||
int16_t T_Min; // 最低温度
|
||
|
||
uint16_t cellVolMax=0; // 电芯单体最高电压
|
||
uint16_t cellVolMin=0; // 电芯单体最低电压
|
||
|
||
|
||
// //Data2 BIT6 cell imbalance
|
||
// if((bmsMem.balanceStatus & 0x01) !=0) //表示开启了均衡
|
||
// {
|
||
// protectByte1 |= 0xBF;
|
||
// alarmByte1 |= 0xBF;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0x40;
|
||
// alarmByte1 &= 0x40;
|
||
// }
|
||
|
||
//保护
|
||
//欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
protectByte1 |= 0x20;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xDF;
|
||
}
|
||
|
||
// //过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte1 & 0x0141) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// protectByte1 |= 0x10;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xEF;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte1 &= 0xEF;
|
||
// }
|
||
|
||
//低温保护
|
||
//under temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x0005) != 0) || ((canMem[0].status_byte4 & 0x0C0C) != 0))
|
||
{
|
||
protectByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xF7;
|
||
}
|
||
|
||
//过温保护
|
||
//over temp at charging or discharging
|
||
if(((canMem[0].status_byte2 & 0x000A) != 0) || ((canMem[0].status_byte4 & 0x0303) != 0))
|
||
{
|
||
protectByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xFB;
|
||
}
|
||
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte1 |= 0x02;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xFD;
|
||
}
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte1 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xFE;
|
||
}
|
||
|
||
//告警
|
||
//欠压告警
|
||
if((canMem[0].status_byte3 & 0x0A00) != 0)
|
||
{
|
||
alarmByte1 |= 0x20;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xDF;
|
||
}
|
||
|
||
// //过压告警
|
||
// if((canMem[0].status_byte3 & 0x0500) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte1 |= 0x10;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xEF;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte1 &= 0xEF;
|
||
// }
|
||
|
||
//低温告警
|
||
if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0))
|
||
{
|
||
alarmByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xF7;
|
||
}
|
||
|
||
//过温告警
|
||
if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0))
|
||
{
|
||
alarmByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xFB;
|
||
}
|
||
|
||
//放电过流告警
|
||
if((canMem[0].status_byte3 & 0x2000) != 0)
|
||
{
|
||
alarmByte1 |= 0x02;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xFD;
|
||
}
|
||
|
||
//充电过流告警
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte1 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
alarmByte1 &= 0xFE;
|
||
}
|
||
|
||
|
||
if(CAN_SendCount ==0) //ID = 0x321 - 最大充电电压、最小放电电压
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = (chgVolLimit >> 8) & 0xFF;
|
||
data[3] = chgVolLimit & 0xFF; //最大充电电压
|
||
data[4] = 0x00;
|
||
data[5] = 0x00;
|
||
data[6] = (dsgVolLimit >> 8) & 0xFF;
|
||
data[7] = dsgVolLimit & 0xFF; //最小放电电压
|
||
CAN1_SendData(0x321, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==1) //ID = 0x322 - 最大充电电流、最大放电电流
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
chgCurLimit = 0; //Schneider禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
dsgCurLimit = 0; //Schneider禁放
|
||
}
|
||
else
|
||
{
|
||
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = (chgCurLimit >> 8) & 0xFF;
|
||
data[3] = chgCurLimit & 0xFF; //最大充电电流
|
||
data[4] = 0x00;
|
||
data[5] = 0x00;
|
||
data[6] = (dsgCurLimit >> 8) & 0xFF;
|
||
data[7] = dsgCurLimit & 0xFF; //最大放电电流
|
||
CAN1_SendData(0x322, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==2) //ID = 0x323 - 电池电压、电流
|
||
{
|
||
tempVol = (int16_t)(bmsMem.packVoltage/10); //单位0.01
|
||
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = (tempVol >>8) & 0xFF; //电池组电压 0.01
|
||
data[3] = tempVol & 0xFF;
|
||
data[4] = 0x00;
|
||
data[5] = 0x00;
|
||
data[6] = (tempCur >>8) & 0xFF; //电池组电流 0.1
|
||
data[7] = tempCur & 0xFF;
|
||
CAN1_SendData(0x323, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==3) //ID = 0x324 - 温度、SOC
|
||
{
|
||
totalCapacity = 100 * ncc_Ah * OnlineNum; //单位0.01Ah
|
||
T_Average = canMem[0].temp;// 平均温度
|
||
|
||
data[0] = ((T_Average-2731) >>8) & 0xFF;
|
||
data[1] = (T_Average-2731) & 0xFF; //平均温度 0.1
|
||
data[2] = 0x00;
|
||
data[3] = canMem[0].soc & 0xFF; //SOC
|
||
data[4] = 0x00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0x00;
|
||
CAN1_SendData(0x324, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==4) //ID = 0x325 - 允许位、报警/保护
|
||
{
|
||
RequestFlag = 0xC0; //充电允许0x02,放电允许0x04,不强充~0x01
|
||
if(chg_forbidFlg == 1)//Schneider
|
||
{
|
||
RequestFlag &= 0xFD; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//Schneider
|
||
{
|
||
RequestFlag &= 0xFB; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//Schneider
|
||
{
|
||
RequestFlag |= 0x01; //强充
|
||
}
|
||
|
||
data[0] = RequestFlag; //充电允许放电允许
|
||
data[1] = 0x00;
|
||
data[2] = protectByte1;
|
||
data[3] = 0x00;
|
||
data[4] = alarmByte1;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0x00;
|
||
CAN1_SendData(0x325, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==5) //ID = 0x326 - SOH、满充容量
|
||
{
|
||
totalCapacity = 100 * ncc_Ah * OnlineNum; //单位0.01Ah
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0;
|
||
data[5] = canMem[0].soh & 0xFF; //SOH
|
||
data[6] = (totalCapacity >> 8) & 0xFF;
|
||
data[7] = totalCapacity & 0xFF; //电池满充容量 10mAh
|
||
CAN1_SendData(0x326, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==6) //ID = 0x327 - 电池最高/低温度、电池最高/低电压
|
||
{
|
||
T_Max = canMem[0].TempMax; // 最高温度
|
||
T_Min = canMem[0].TempMin; // 最低温度
|
||
cellVolMax = canMem[0].VolMax;
|
||
cellVolMin = canMem[0].VolMin;
|
||
|
||
data[0] = ((T_Max -2731) >> 8) & 0xFF;
|
||
data[1] = (T_Max -2731) & 0xFF; //最大电池温度
|
||
data[2] = ((T_Min -2731) >> 8) & 0xFF;
|
||
data[3] = (T_Min -2731) & 0xFF; //最小电池温度
|
||
data[4] = (cellVolMax >> 8) & 0xFF;
|
||
data[5] = cellVolMax & 0xFF; //最大电池电压
|
||
data[6] = (cellVolMin >> 8) & 0xFF;
|
||
data[7] = cellVolMin & 0xFF; //最小电池电压
|
||
CAN1_SendData(0x327, &data[0]);
|
||
}
|
||
|
||
if(CAN_SendCount>=7)
|
||
{
|
||
CAN_SendCount = 0;
|
||
}
|
||
}
|
||
|
||
//AlpSolarr 力高
|
||
void CAN_Protocol_AlpSolarr(void)
|
||
{
|
||
uint8_t data[8];
|
||
uint16_t totalCapacity;
|
||
|
||
uint16_t tempVol;
|
||
int16_t tempCur;
|
||
|
||
uint16_t chgVolLimit;
|
||
uint16_t dsgVolLimit;
|
||
int16_t chgCurLimit;
|
||
int16_t dsgCurLimit;
|
||
|
||
uint8_t protectByte1 = 0;
|
||
uint8_t protectByte2 = 0;
|
||
|
||
int16_t T_Average; // 平均温度
|
||
int16_t T_Max; // 最高温度
|
||
int16_t T_Min; // 最低温度
|
||
uint16_t cellVolMax=0; // 电芯单体最高电压
|
||
int16_t cellVolMin=0; // 电芯单体最低电压
|
||
|
||
//BIT7 discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x2c) !=0) || ((canMem[0].status_byte4 & 0x20) !=0) )
|
||
{
|
||
protectByte1 |= 0x80;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0x7f;
|
||
}
|
||
|
||
//BIT4 cell under temp at charging or discharging
|
||
//add mcu temp protect status
|
||
if( ((canMem[0].status_byte2 & 0x05) !=0) || ((canMem[0].status_byte4 & 0x0C) !=0) )
|
||
{
|
||
protectByte1 |= 0x10;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xEF;
|
||
}
|
||
|
||
//BIT3 cell over temp at charging or discharging
|
||
//add mcu temp protect status
|
||
if( ((canMem[0].status_byte2 & 0x0A) !=0) || ((canMem[0].status_byte4 & 0x03) !=0) )
|
||
{
|
||
protectByte1 |= 0x08;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xF7;
|
||
}
|
||
|
||
//BIT2 cell uv
|
||
if((canMem[0].status_byte1 & 0x02) !=0)
|
||
{
|
||
protectByte1 |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xfb;
|
||
}
|
||
|
||
//BIT1 cell ov
|
||
if((canMem[0].status_byte1 & 0x01) !=0)
|
||
{
|
||
if(canMem[0].soc < 99)
|
||
{
|
||
protectByte1 |= 0x02;
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xfd;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
protectByte1 &= 0xfd;
|
||
}
|
||
|
||
//BIT0 charge over current
|
||
if( ((canMem[0].status_byte1 & 0x10) !=0) || ((canMem[0].status_byte4 & 0x10) !=0) )
|
||
{
|
||
protectByte2 |= 0x01;
|
||
}
|
||
else
|
||
{
|
||
protectByte2 &= 0xfe;
|
||
}
|
||
|
||
// //Data1 BIT4 cell balance
|
||
// if((bmsMem.balanceStatus & 0x01) !=0)
|
||
// {
|
||
// protectByte2 |= 0x10;
|
||
// }
|
||
// else
|
||
// {
|
||
// protectByte2 &= 0xef;
|
||
// }
|
||
|
||
|
||
if(CAN_SendCount ==0) //ID=0x359
|
||
{
|
||
data[0] = protectByte1;
|
||
data[1] = protectByte2;
|
||
data[2] = protectByte1;
|
||
data[3] = protectByte2;
|
||
data[4] = 0X00;
|
||
data[5] = 0X00;
|
||
data[6] = 0X00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x359, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==1) //ID = 0x351
|
||
{
|
||
//充放电电流限制需要有符号区别吗?
|
||
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 0)
|
||
{
|
||
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
else
|
||
{
|
||
chgCurLimit = 0; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 0)
|
||
{
|
||
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
else
|
||
{
|
||
dsgCurLimit = 0; //禁放
|
||
}
|
||
|
||
data[0] = chgVolLimit & 0xFF; //充电电压限制低位
|
||
data[1] = (chgVolLimit >> 8) & 0xFF;
|
||
data[2] = chgCurLimit & 0xFF; //充电电流限制低位
|
||
data[3] = (chgCurLimit >> 8) & 0xFF;
|
||
data[4] = dsgCurLimit & 0xFF; //放电电流限制低位
|
||
data[5] = (dsgCurLimit >> 8) & 0xFF;
|
||
data[6] = dsgVolLimit & 0xFF; //放电电压限制低位
|
||
data[7] = (dsgVolLimit >> 8) & 0xFF;
|
||
CAN1_SendData(0x351, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==2)
|
||
{
|
||
data[0] = canMem[0].soc & 0xFF; //SOC
|
||
data[1] = 0;
|
||
data[2] = canMem[0].soh & 0xFF; //SOH
|
||
data[3] = 0;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x355, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==3)
|
||
{
|
||
tempVol = (uint16_t)(bmsMem.packVoltage/10); //单位0.01
|
||
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
|
||
T_Average = canMem[0].temp;// 平均温度
|
||
|
||
data[0] = tempVol & 0xFF;
|
||
data[1] = (tempVol >>8) & 0xFF; //电池包电压
|
||
data[2] = tempCur & 0xFF;
|
||
data[3] = (tempCur >>8) & 0xFF; //电池包电流
|
||
data[4] = (T_Average -2731) & 0xFF;;
|
||
data[5] = ((T_Average -2731) >>8) & 0xFF; //温度-暂时取平均温度,具体哪一路需要客户确认
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x356, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==4) //ID = 0x370 - 最大/最小单体温度,最大/最小单体电压(新加入)
|
||
{
|
||
T_Max = canMem[0].TempMax; // 最高温度
|
||
T_Min = canMem[0].TempMin; // 最低温度
|
||
cellVolMax = canMem[0].VolMax;
|
||
cellVolMin = canMem[0].VolMin;
|
||
|
||
data[0] = (T_Max -2731) & 0xFF; //最大单体温度
|
||
data[1] = ((T_Max -2731) >> 8) & 0xFF;
|
||
data[2] = (T_Min -2731) & 0xFF; //最小单体温度
|
||
data[3] = ((T_Min -2731) >> 8) & 0xFF;
|
||
data[4] = cellVolMax & 0xFF; //最大单体电压
|
||
data[5] = (cellVolMax >> 8) & 0xFF;
|
||
data[6] = cellVolMin & 0xFF; //最小单体电压
|
||
data[7] = (cellVolMin >> 8) & 0xFF;
|
||
CAN1_SendData(0x370, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==5)
|
||
{
|
||
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
RequestFlag &= 0x7F; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
RequestFlag &= 0xBF; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)
|
||
{
|
||
RequestFlag |= 0x20; //强充
|
||
}
|
||
|
||
data[0] = RequestFlag;
|
||
data[1] = 0x00;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0X00;
|
||
data[5] = 0x00;
|
||
data[6] = 0x00;
|
||
data[7] = 0X00;
|
||
CAN1_SendData(0x35C, &data[0]);
|
||
}
|
||
if(CAN_SendCount ==6) //0x35E
|
||
{
|
||
totalCapacity = fcc_Ah * OnlineNum; //单位1Ah
|
||
|
||
data[0] = 0x00;
|
||
data[1] = 0x00;
|
||
data[2] = 0x00;
|
||
data[3] = 0x00;
|
||
data[4] = 0x00;
|
||
data[5] = 0x00;
|
||
data[6] = totalCapacity & 0xFF;
|
||
data[7] = (totalCapacity >> 8) & 0xFF;
|
||
CAN1_SendData(0x35E, &data[0]);
|
||
}
|
||
// if(CAN_SendCount ==7)
|
||
// {
|
||
// data[0] = 0xAA;
|
||
// data[1] = 0xAA;
|
||
// data[2] = 0xAA;
|
||
// data[3] = 0xAA;
|
||
// data[4] = 0xAA;
|
||
// data[5] = 0xAA;
|
||
// data[6] = 0xAA;
|
||
// data[7] = 0xAA;
|
||
// CAN1_SendData(0x305, &data[0]);
|
||
// }
|
||
|
||
if(CAN_SendCount>=7)
|
||
{
|
||
CAN_SendCount = 0;
|
||
}
|
||
}
|
||
|
||
//MODBUS:
|
||
//SRNE 硕日
|
||
void MOD_Protocol_SRNE(void)
|
||
{
|
||
uint8_t i;
|
||
uint16_t protectByte = 0; //0x0000-0xFFFF
|
||
uint16_t alarmByte = 0;
|
||
uint16_t statusByte = 0;
|
||
|
||
|
||
//保护
|
||
// //单体过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if(((canMem[0].status_byte1 & 0x0001) != 0) || ((canMem[0].status_byte1 & 0x0040) != 0))
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte |= 0x0001;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
|
||
//单体欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0002) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
alarmByte |= 0x0002;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFFD;
|
||
}
|
||
|
||
// //总体过压保护
|
||
// if((canMem[0].status_byte1 & 0x0100) != 0)
|
||
// {
|
||
// alarmByte |= 0x0004;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFB;
|
||
// }
|
||
|
||
//总体欠压保护
|
||
if((canMem[0].status_byte1 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFF7;
|
||
}
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte |= 0x0010;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFFEF;
|
||
}
|
||
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte |= 0x0020;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFFDF;
|
||
}
|
||
|
||
//充电高温保护
|
||
//charge over temp 高温
|
||
if( ((canMem[0].status_byte2 & 0x0002) !=0) || ((canMem[0].status_byte4 & 0x0101) !=0) )
|
||
{
|
||
protectByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFEFF;
|
||
}
|
||
|
||
//放电高温保护
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x0008) !=0) || ((canMem[0].status_byte4 & 0x0202) !=0) )
|
||
{
|
||
protectByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFDFF;
|
||
}
|
||
|
||
//充电低温保护
|
||
//charge under temp 低温
|
||
if( ((canMem[0].status_byte2 & 0x0001) !=0) || ((canMem[0].status_byte4 & 0x0404) !=0) )
|
||
{
|
||
protectByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFBFF;
|
||
}
|
||
|
||
//放电低温保护
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x0004) !=0) || ((canMem[0].status_byte4 & 0x0808) !=0) )
|
||
{
|
||
protectByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xF7FF;
|
||
}
|
||
|
||
//环境低温保护 0x4000
|
||
if((canMem[0].status_byte4 & 0x0C00) !=0) //环境充放电低温
|
||
{
|
||
protectByte |= 0x4000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xBFFF;
|
||
}
|
||
|
||
//环境高温保护 0x2000
|
||
if((canMem[0].status_byte4 & 0x0300) !=0) //环境充放电高温
|
||
{
|
||
protectByte |= 0x2000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xDFFF;
|
||
}
|
||
|
||
//MOS高温保护 0x1000
|
||
if((canMem[0].status_byte2 & 0x0300) !=0) //MOS充放电高温
|
||
{
|
||
protectByte |= 0x1000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xEFFF;
|
||
}
|
||
|
||
|
||
//告警
|
||
// //单体过压告警
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte3 & 0x0100) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte |= 0x0001;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
|
||
//单体欠压告警
|
||
//cell_uv+pack_uv+l0v
|
||
if((canMem[0].status_byte3 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0002;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFFD;
|
||
}
|
||
|
||
// //总体过压告警
|
||
// if((canMem[0].status_byte3 & 0x0400) != 0)
|
||
// {
|
||
// alarmByte |= 0x0004;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFB;
|
||
// }
|
||
|
||
//总体欠压告警
|
||
if((canMem[0].status_byte3 & 0x0800) != 0)
|
||
{
|
||
alarmByte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFF7;
|
||
}
|
||
|
||
//充电过流告警
|
||
//charge over current
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte |= 0x0010;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFEF;
|
||
}
|
||
|
||
//放电过流告警
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if((canMem[0].status_byte3 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0020;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFDF;
|
||
}
|
||
|
||
//充电高温告警
|
||
//charge over temp 高温
|
||
if( ((canMem[0].status_byte2 & 0x1100) !=0) || ((canMem[0].status_byte4 & 0x1000) !=0) )
|
||
{
|
||
alarmByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFEFF;
|
||
}
|
||
|
||
//放电高温告警
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x2200) !=0) || ((canMem[0].status_byte4 & 0x2000) !=0) )
|
||
{
|
||
alarmByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFDFF;
|
||
}
|
||
|
||
//充电低温告警
|
||
//charge under temp 低温
|
||
if( ((canMem[0].status_byte2 & 0x4400) !=0) || ((canMem[0].status_byte4 & 0x4000) !=0) )
|
||
{
|
||
alarmByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFBFF;
|
||
}
|
||
|
||
//放电低温告警
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x8800) !=0) || ((canMem[0].status_byte4 & 0x8000) !=0) )
|
||
{
|
||
alarmByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xF7FF;
|
||
}
|
||
|
||
//环境低温告警 0x4000
|
||
if((canMem[0].status_byte4 & 0xC000) !=0) //环境充放电低温
|
||
{
|
||
alarmByte |= 0x4000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xBFFF;
|
||
}
|
||
|
||
//环境高温告警 0x2000
|
||
if((canMem[0].status_byte4 & 0x3000) !=0) //环境充放电高温
|
||
{
|
||
alarmByte |= 0x2000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xDFFF;
|
||
}
|
||
|
||
//MOS高温告警 0x1000
|
||
if((canMem[0].status_byte2 & 0x3000) !=0) //MOS充放电高温
|
||
{
|
||
alarmByte |= 0x1000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xEFFF;
|
||
}
|
||
|
||
|
||
SRNEMem.protect_byte = protectByte; //保护标志 Hex 2byte
|
||
SRNEMem.alarm_byte = alarmByte; //告警标志 Hex 2byte
|
||
|
||
//状态位赋值
|
||
if(bCHGING == 1) //充电
|
||
{
|
||
statusByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFEFF;
|
||
}
|
||
if(bDSGING == 1) //放电
|
||
{
|
||
statusByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFDFF;
|
||
}
|
||
if((canMem[0].status_byte3 & 0x02) !=0) //充电MOS状态
|
||
{
|
||
statusByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFBFF;
|
||
}
|
||
if((canMem[0].status_byte3 & 0x01) !=0) //放电MOS状态
|
||
{
|
||
statusByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xF7FF;
|
||
}
|
||
SRNEMem.status_byte = statusByte; //状态/故障标志 Hex 2byte
|
||
|
||
|
||
SRNEMem.balanceStatus = bmsMem.balanceStatus;//平衡状态 Hex 2byte
|
||
|
||
|
||
SRNEMem.packCurrent = (int16_t)(canMem[0].cur); //电流 10mA 2byte
|
||
SRNEMem.packVoltage = (uint16_t)(bmsMem.packVoltage/10); //电池组电压 10mA 2byte
|
||
|
||
SRNEMem.soc = (uint8_t)canMem[0].soc; //SOC % 2byte
|
||
SRNEMem.soh = (uint8_t)canMem[0].soh; //SOH % 2byte
|
||
|
||
SRNEMem.fcc = 100 * ncc_Ah * OnlineNum; //满容量 10mAH 2byte
|
||
SRNEMem.rcc = 100 * ncc_Ah * OnlineNum * SRNEMem.soc/100; //剩余容量 10mAH 2byte
|
||
|
||
|
||
//电芯电压
|
||
for(i=0;i<16;i++)
|
||
{
|
||
SRNEMem.vCell[i] = bmsMem.vCell[i]; //电池电压 mV 32byte
|
||
}
|
||
//电芯温度
|
||
SRNEMem.Tcell[0] = (int16_t)(bmsMem.mcu_T1-2731); //电池温度 0.1℃ 8byte
|
||
SRNEMem.Tcell[1] = (int16_t)(bmsMem.mcu_T2-2731);
|
||
SRNEMem.Tcell[2] = (int16_t)(bmsMem.mcu_T3-2731);
|
||
SRNEMem.Tcell[3] = (int16_t)(bmsMem.mcu_T4-2731);
|
||
|
||
SRNEMem.afe_MOS = (int16_t)((bmsMem.afe_T1 + bmsMem.afe_T2)/2 - 2731); //MOS温度 0.1℃ 2byte 对应上下MOS的温度平均值
|
||
SRNEMem.afe_MCU = (int16_t)(bmsMem.afe_T3-2731); //环境温度 0.1℃ 2byte 对应MCU芯片温度
|
||
|
||
//充放电电流限制需要有符号区别吗?
|
||
SRNEMem.chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
//SRNEMem.dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
SRNEMem.chgCurLimit = 0; //SRNE禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
SRNEMem.chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
SRNEMem.chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
SRNEMem.dsgCurLimit = 0; //SRNE禁放
|
||
}
|
||
else
|
||
{
|
||
SRNEMem.dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
}
|
||
|
||
//Voltronic 日月元
|
||
void MOD_Protocol_Voltronic(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
uint16_t chg_alarm_byte = 0;
|
||
uint16_t dsg_alarm_byte = 0;
|
||
uint16_t chg_protect1_byte = 0;
|
||
uint16_t dsg_protect1_byte = 0;
|
||
|
||
//充电告警
|
||
//充电过流告警
|
||
//charge over current
|
||
if((canMem[0].status_byte3 & 0x1000) !=0)
|
||
{
|
||
chg_alarm_byte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
chg_alarm_byte &= 0xFFF7;
|
||
}
|
||
|
||
//充电低温告警
|
||
//charge under temp
|
||
if( ((canMem[0].status_byte2 & 0x4400) !=0) || ((canMem[0].status_byte4 & 0x4000) !=0) )
|
||
{
|
||
chg_alarm_byte |= 0x0004;
|
||
}
|
||
else
|
||
{
|
||
chg_alarm_byte &= 0xFFFB;
|
||
}
|
||
|
||
// //过压告警
|
||
// if((canMem[0].status_byte3 & 0x0500) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// chg_alarm_byte |= 0x0002;
|
||
// }
|
||
// else
|
||
// {
|
||
// chg_alarm_byte &= 0xFFFD;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// chg_alarm_byte &= 0xFFFD;
|
||
// }
|
||
|
||
//充电高温告警
|
||
//charge over temp
|
||
if( ((canMem[0].status_byte2 & 0x1100) !=0) || ((canMem[0].status_byte4 & 0x1000) !=0) )
|
||
{
|
||
chg_alarm_byte |= 0x0001;
|
||
}
|
||
else
|
||
{
|
||
chg_alarm_byte &= 0xFFFE;
|
||
}
|
||
|
||
//放电告警
|
||
//欠压告警
|
||
if((canMem[0].status_byte3 & 0x0A00) != 0)
|
||
{
|
||
dsg_alarm_byte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
dsg_alarm_byte &= 0xFFF7;
|
||
}
|
||
|
||
//MOS高温告警
|
||
if((canMem[0].status_byte2 & 0x0200) != 0)
|
||
{
|
||
dsg_alarm_byte |= 0x0004;
|
||
}
|
||
else
|
||
{
|
||
dsg_alarm_byte &= 0xFFFB;
|
||
}
|
||
|
||
//放电低温告警
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x8800) !=0) || ((canMem[0].status_byte4 & 0x8000) !=0) )
|
||
{
|
||
dsg_alarm_byte |= 0x0002;
|
||
}
|
||
else
|
||
{
|
||
dsg_alarm_byte &= 0xFFFD;
|
||
}
|
||
|
||
//放电高温告警
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x2200) !=0) || ((canMem[0].status_byte4 & 0x2000) !=0) )
|
||
{
|
||
dsg_alarm_byte |= 0x0001;
|
||
}
|
||
else
|
||
{
|
||
dsg_alarm_byte &= 0xFFFE;
|
||
}
|
||
|
||
//保护
|
||
//充电保护1
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
chg_protect1_byte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
chg_protect1_byte &= 0xF7FF;
|
||
}
|
||
|
||
//过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte1 & 0x0141) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// chg_protect1_byte |= 0x0400;
|
||
// }
|
||
// else
|
||
// {
|
||
// chg_protect1_byte &= 0xFBFF;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// chg_protect1_byte &= 0xFBFF;
|
||
// }
|
||
|
||
//充电低温保护
|
||
//charge under temp
|
||
if( ((canMem[0].status_byte2 & 0x0001) !=0) || ((canMem[0].status_byte4 & 0x0404) !=0) )
|
||
{
|
||
chg_protect1_byte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
chg_protect1_byte &= 0xFBFF;
|
||
}
|
||
|
||
//充电高温保护
|
||
//charge over temp
|
||
if( ((canMem[0].status_byte2 & 0x0002) !=0) || ((canMem[0].status_byte4 & 0x0101) !=0) )
|
||
{
|
||
chg_protect1_byte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
chg_protect1_byte &= 0xFEFF;
|
||
}
|
||
|
||
//MOS高温保护
|
||
if((canMem[0].status_byte2 & 0x0100) != 0)
|
||
{
|
||
dsg_alarm_byte |= 0x0040;
|
||
}
|
||
else
|
||
{
|
||
dsg_alarm_byte &= 0xFFBF;
|
||
}
|
||
|
||
//放电保护1
|
||
//放电高温保护
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x0008) !=0) || ((canMem[0].status_byte4 & 0x0202) !=0) )
|
||
{
|
||
dsg_protect1_byte |= 0x4000;
|
||
}
|
||
else
|
||
{
|
||
dsg_protect1_byte &= 0xBFFF;
|
||
}
|
||
|
||
//放电低温保护
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x0004) !=0) || ((canMem[0].status_byte4 & 0x0808) !=0) )
|
||
{
|
||
dsg_protect1_byte |= 0x2000;
|
||
}
|
||
else
|
||
{
|
||
dsg_protect1_byte &= 0xBFFF;
|
||
}
|
||
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) !=0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) !=0) )
|
||
{
|
||
dsg_protect1_byte |= 0x1000;
|
||
}
|
||
else
|
||
{
|
||
dsg_protect1_byte &= 0xEFFF;
|
||
}
|
||
|
||
//欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
dsg_protect1_byte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
dsg_protect1_byte &= 0xF7FF;
|
||
}
|
||
|
||
RequestFlag = 0x00C0; //充电允许0x0080,放电允许0x0040,不强充~0x0020
|
||
if(chg_forbidFlg == 1)//Voltronic
|
||
{
|
||
RequestFlag &= 0xFF7F; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//Voltronic
|
||
{
|
||
RequestFlag &= 0xFFBF; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//Voltronic
|
||
{
|
||
RequestFlag |= 0x0020; //强充
|
||
}
|
||
|
||
|
||
VoltronicMem.chg_alarm_byte = chg_alarm_byte; // 充电报警
|
||
VoltronicMem.dsg_alarm_byte = dsg_alarm_byte; // 放电报警
|
||
VoltronicMem.chg_protect1_byte = chg_protect1_byte; // 充电保护
|
||
VoltronicMem.dsg_protect1_byte = dsg_protect1_byte; // 放电保护
|
||
VoltronicMem.status_byte = RequestFlag; // 充放电允许
|
||
|
||
|
||
//常规数据填充
|
||
VoltronicMem.protocolType = 0x0000;
|
||
VoltronicMem.protocolVer = 0x0100;
|
||
VoltronicMem.SoftwareH = VersionMem.Software[0]<<8 | VersionMem.Software[1];
|
||
VoltronicMem.SoftwareL = VersionMem.Software[2]<<8 | VersionMem.Software[3];
|
||
VoltronicMem.HardwareH = VersionMem.Hardware[0];
|
||
VoltronicMem.HardwareL = VersionMem.Hardware[1]<<8 | VersionMem.Hardware[2];
|
||
|
||
//实时数据
|
||
VoltronicMem.packNum = OnlineNum;
|
||
|
||
VoltronicMem.cellNum = bmsMem.ucCellNum;
|
||
VoltronicMem.tempNum = 6;
|
||
|
||
//电芯电压
|
||
for(i=0;i<16;i++)
|
||
{
|
||
VoltronicMem.cellVol[i] = bmsMem.vCell[i]/100; //电池电压 0.1V
|
||
}
|
||
//电芯温度
|
||
VoltronicMem.T[0] = bmsMem.mcu_T1; //电池温度 0.1K
|
||
VoltronicMem.T[1] = bmsMem.mcu_T2;
|
||
VoltronicMem.T[2] = bmsMem.mcu_T3;
|
||
VoltronicMem.T[3] = bmsMem.mcu_T4;
|
||
VoltronicMem.T[4] = bmsMem.afe_T3;
|
||
VoltronicMem.T[5] = (bmsMem.afe_T1 + bmsMem.afe_T2)/2;
|
||
|
||
if(bCHGING==1)
|
||
{
|
||
VoltronicMem.chg_packCurrent = (uint16_t)(canMem[0].cur/10); //充电电流 0.1A 2byte
|
||
VoltronicMem.dsg_packCurrent = 0;
|
||
}
|
||
else
|
||
{
|
||
VoltronicMem.dsg_packCurrent = (uint16_t)(-canMem[0].cur/10); //放电电流 0.1A 2byte
|
||
VoltronicMem.chg_packCurrent = 0;
|
||
}
|
||
VoltronicMem.packVoltage = (uint16_t)(bmsMem.packVoltage/100); //模块电压 0.1V 2byte
|
||
|
||
//mAH /3600
|
||
VoltronicMem.soc = canMem[0].soc; //SOC % 2byte
|
||
VoltronicMem.fccH = ((1000 * ncc_Ah * OnlineNum)>>16) & 0xFFFF; //满容量 mAH 4byte
|
||
VoltronicMem.fccL = (1000 * ncc_Ah * OnlineNum) & 0xFFFF;
|
||
VoltronicMem.rccH = ((1000 * ncc_Ah * OnlineNum * VoltronicMem.soc/100)>>16) & 0xFFFF; //剩余容量 mAH 4byte
|
||
VoltronicMem.rccL = (1000 * ncc_Ah * OnlineNum * VoltronicMem.soc/100) & 0xFFFF;
|
||
|
||
VoltronicMem.chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
VoltronicMem.dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
VoltronicMem.chgCurLimit = 0; //Voltronic禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
VoltronicMem.chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
VoltronicMem.chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
VoltronicMem.dsgCurLimit = 0; //Voltronic禁放
|
||
}
|
||
else
|
||
{
|
||
VoltronicMem.dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
|
||
VoltronicMem.cellNum2 = bmsMem.ucCellNum;
|
||
VoltronicMem.tempNum2 = 6;
|
||
|
||
//各种状态位,0xF0表示未实现
|
||
for(i=0;i<10;i++)
|
||
{
|
||
VoltronicMem.Vol_status[i]=0xF0;
|
||
}
|
||
for(i=0;i<5;i++)
|
||
{
|
||
VoltronicMem.T_status[i]=0xF0;
|
||
}
|
||
for(i=0;i<10;i++)
|
||
{
|
||
VoltronicMem.other_status[i]=0xF0;
|
||
}
|
||
|
||
}
|
||
|
||
//COSUPER 古顶
|
||
void MOD_Protocol_COSUPER(void)
|
||
{
|
||
uint8_t i;
|
||
uint16_t protectByte = 0; //0x0000-0xFFFF
|
||
uint16_t alarmByte = 0;
|
||
uint16_t statusByte = 0;
|
||
|
||
|
||
//保护
|
||
// //单体过压保护
|
||
// //cell_ov+pack_ov+pf
|
||
// if(((canMem[0].status_byte1 & 0x0001) != 0) || ((canMem[0].status_byte1 & 0x0040) != 0))
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte |= 0x0001;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
|
||
//单体欠压保护
|
||
//cell_uv+pack_uv+l0v
|
||
if(((canMem[0].status_byte1 & 0x0002) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
|
||
{
|
||
alarmByte |= 0x0002;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFFD;
|
||
}
|
||
|
||
// //总体过压保护
|
||
// if((canMem[0].status_byte1 & 0x0100) != 0)
|
||
// {
|
||
// alarmByte |= 0x0004;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFB;
|
||
// }
|
||
|
||
//总体欠压保护
|
||
if((canMem[0].status_byte1 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFF7;
|
||
}
|
||
|
||
//充电过流保护
|
||
//charge over current
|
||
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
|
||
{
|
||
protectByte |= 0x0010;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFFEF;
|
||
}
|
||
|
||
//放电过流保护
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
|
||
{
|
||
protectByte |= 0x0020;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFFDF;
|
||
}
|
||
|
||
//充电高温保护
|
||
//charge over temp 高温
|
||
if( ((canMem[0].status_byte2 & 0x0002) !=0) || ((canMem[0].status_byte4 & 0x0101) !=0) )
|
||
{
|
||
protectByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFEFF;
|
||
}
|
||
|
||
//放电高温保护
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x0008) !=0) || ((canMem[0].status_byte4 & 0x0202) !=0) )
|
||
{
|
||
protectByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFDFF;
|
||
}
|
||
|
||
//充电低温保护
|
||
//charge under temp 低温
|
||
if( ((canMem[0].status_byte2 & 0x0001) !=0) || ((canMem[0].status_byte4 & 0x0404) !=0) )
|
||
{
|
||
protectByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xFBFF;
|
||
}
|
||
|
||
//放电低温保护
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x0004) !=0) || ((canMem[0].status_byte4 & 0x0808) !=0) )
|
||
{
|
||
protectByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xF7FF;
|
||
}
|
||
|
||
//环境低温保护 0x4000
|
||
if((canMem[0].status_byte4 & 0x0C00) !=0) //环境充放电低温
|
||
{
|
||
protectByte |= 0x4000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xBFFF;
|
||
}
|
||
|
||
//环境高温保护 0x2000
|
||
if((canMem[0].status_byte4 & 0x0300) !=0) //环境充放电高温
|
||
{
|
||
protectByte |= 0x2000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xDFFF;
|
||
}
|
||
|
||
//MOS高温保护 0x1000
|
||
if((canMem[0].status_byte2 & 0x0300) !=0) //MOS充放电高温
|
||
{
|
||
protectByte |= 0x1000;
|
||
}
|
||
else
|
||
{
|
||
protectByte &= 0xEFFF;
|
||
}
|
||
|
||
|
||
//告警
|
||
// //单体过压告警
|
||
// //cell_ov+pack_ov+pf
|
||
// if((canMem[0].status_byte3 & 0x0100) != 0)
|
||
// {
|
||
// if(canMem[0].soc < 99)
|
||
// {
|
||
// alarmByte |= 0x0001;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFE;
|
||
// }
|
||
|
||
//单体欠压告警
|
||
//cell_uv+pack_uv+l0v
|
||
if((canMem[0].status_byte3 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0002;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFFD;
|
||
}
|
||
|
||
// //总体过压告警
|
||
// if((canMem[0].status_byte3 & 0x0400) != 0)
|
||
// {
|
||
// alarmByte |= 0x0004;
|
||
// }
|
||
// else
|
||
// {
|
||
// alarmByte &= 0xFFFB;
|
||
// }
|
||
|
||
//总体欠压告警
|
||
if((canMem[0].status_byte3 & 0x0800) != 0)
|
||
{
|
||
alarmByte |= 0x0008;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFF7;
|
||
}
|
||
|
||
//充电过流告警
|
||
//charge over current
|
||
if((canMem[0].status_byte3 & 0x1000) != 0)
|
||
{
|
||
alarmByte |= 0x0010;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFEF;
|
||
}
|
||
|
||
//放电过流告警
|
||
//discharge over current,SC, OCD1, OCD2
|
||
if((canMem[0].status_byte3 & 0x0200) != 0)
|
||
{
|
||
alarmByte |= 0x0020;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFFDF;
|
||
}
|
||
|
||
//充电高温告警
|
||
//charge over temp 高温
|
||
if( ((canMem[0].status_byte2 & 0x1100) !=0) || ((canMem[0].status_byte4 & 0x1000) !=0) )
|
||
{
|
||
alarmByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFEFF;
|
||
}
|
||
|
||
//放电高温告警
|
||
//discharge over temp
|
||
if( ((canMem[0].status_byte2 & 0x2200) !=0) || ((canMem[0].status_byte4 & 0x2000) !=0) )
|
||
{
|
||
alarmByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFDFF;
|
||
}
|
||
|
||
//充电低温告警
|
||
//charge under temp 低温
|
||
if( ((canMem[0].status_byte2 & 0x4400) !=0) || ((canMem[0].status_byte4 & 0x4000) !=0) )
|
||
{
|
||
alarmByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xFBFF;
|
||
}
|
||
|
||
//放电低温告警
|
||
//discharge under temp
|
||
if( ((canMem[0].status_byte2 & 0x8800) !=0) || ((canMem[0].status_byte4 & 0x8000) !=0) )
|
||
{
|
||
alarmByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xF7FF;
|
||
}
|
||
|
||
//环境低温告警 0x4000
|
||
if((canMem[0].status_byte4 & 0xC000) !=0) //环境充放电低温
|
||
{
|
||
alarmByte |= 0x4000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xBFFF;
|
||
}
|
||
|
||
//环境高温告警 0x2000
|
||
if((canMem[0].status_byte4 & 0x3000) !=0) //环境充放电高温
|
||
{
|
||
alarmByte |= 0x2000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xDFFF;
|
||
}
|
||
|
||
//MOS高温告警 0x1000
|
||
if((canMem[0].status_byte2 & 0x3000) !=0) //MOS充放电高温
|
||
{
|
||
alarmByte |= 0x1000;
|
||
}
|
||
else
|
||
{
|
||
alarmByte &= 0xEFFF;
|
||
}
|
||
|
||
|
||
SRNEMem.protect_byte = protectByte; //保护标志 Hex 2byte
|
||
SRNEMem.alarm_byte = alarmByte; //告警标志 Hex 2byte
|
||
|
||
//状态位赋值
|
||
if(bCHGING == 1) //充电
|
||
{
|
||
statusByte |= 0x0100;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFEFF;
|
||
}
|
||
if(bDSGING == 1) //放电
|
||
{
|
||
statusByte |= 0x0200;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFDFF;
|
||
}
|
||
if((canMem[0].status_byte3 & 0x02) !=0) //充电MOS状态
|
||
{
|
||
statusByte |= 0x0400;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xFBFF;
|
||
}
|
||
if((canMem[0].status_byte3 & 0x01) !=0) //放电MOS状态
|
||
{
|
||
statusByte |= 0x0800;
|
||
}
|
||
else
|
||
{
|
||
statusByte &= 0xF7FF;
|
||
}
|
||
SRNEMem.status_byte = statusByte; //状态/故障标志 Hex 2byte
|
||
|
||
|
||
SRNEMem.balanceStatus = bmsMem.balanceStatus;//平衡状态 Hex 2byte
|
||
|
||
|
||
SRNEMem.packCurrent = (int16_t)(canMem[0].cur); //电流 10mA 2byte
|
||
SRNEMem.packVoltage = (uint16_t)(bmsMem.packVoltage/10); //电池组电压 10mA 2byte
|
||
|
||
SRNEMem.soc = (uint8_t)canMem[0].soc; //SOC % 2byte
|
||
SRNEMem.soh = (uint8_t)canMem[0].soh; //SOH % 2byte
|
||
|
||
SRNEMem.fcc = 100 * ncc_Ah * OnlineNum; //满容量 10mAH 2byte
|
||
SRNEMem.rcc = 100 * ncc_Ah * OnlineNum * SRNEMem.soc/100; //剩余容量 10mAH 2byte
|
||
|
||
|
||
//电芯电压
|
||
if( bmsMem.ucCellNum == 8) //板子设定为8串
|
||
{
|
||
for(i=0;i<8;i++)
|
||
{
|
||
SRNEMem.vCell[i] = bmsMem.vCell[i]; //电池电压 mV 32byte
|
||
}
|
||
for(i=0;i<8;i++)
|
||
{
|
||
SRNEMem.vCell[8+i] = bmsMem.vCell[i]; //电池电压 mV 32byte
|
||
}
|
||
}
|
||
else //其他默认为16串
|
||
{
|
||
for(i=0;i<16;i++)
|
||
{
|
||
SRNEMem.vCell[i] = bmsMem.vCell[i]; //电池电压 mV 32byte
|
||
}
|
||
}
|
||
|
||
//电芯温度
|
||
SRNEMem.Tcell[0] = (int16_t)(bmsMem.mcu_T1-2731); //电池温度 0.1℃ 8byte
|
||
SRNEMem.Tcell[1] = (int16_t)(bmsMem.mcu_T2-2731);
|
||
SRNEMem.Tcell[2] = (int16_t)(bmsMem.mcu_T3-2731);
|
||
SRNEMem.Tcell[3] = (int16_t)(bmsMem.mcu_T4-2731);
|
||
|
||
SRNEMem.afe_MOS = (int16_t)((bmsMem.afe_T1 + bmsMem.afe_T2)/2 - 2731); //MOS温度 0.1℃ 2byte 对应上下MOS的温度平均值
|
||
SRNEMem.afe_MCU = (int16_t)(bmsMem.afe_T3-2731); //环境温度 0.1℃ 2byte 对应MCU芯片温度
|
||
|
||
//充放电电流限制需要有符号区别吗?
|
||
SRNEMem.chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
|
||
//SRNEMem.dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
|
||
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
SRNEMem.chgCurLimit = 0; //COSUPER禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
SRNEMem.chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
SRNEMem.chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
SRNEMem.dsgCurLimit = 0; //COSUPER禁放
|
||
}
|
||
else
|
||
{
|
||
SRNEMem.dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
}
|
||
|
||
//SMK
|
||
void MOD_Protocol_SMK(void)
|
||
{
|
||
RequestFlag = 0x0060; //充电允许0x0040,放电允许0x0020,不强充~0x1000
|
||
if(chg_forbidFlg == 1)//SMK
|
||
{
|
||
RequestFlag &= 0xFFBF; //禁充
|
||
}
|
||
if(dsg_forbidFlg == 1)//SMK
|
||
{
|
||
RequestFlag &= 0xFFDF; //禁放
|
||
}
|
||
if(chg_forceFlg == 1)//SMK
|
||
{
|
||
RequestFlag |= 0x1000; //强充
|
||
}
|
||
|
||
SMKMem.status_byte = RequestFlag; //状态:bit6充电禁止bit5放电禁止
|
||
SMKMem.soc = (uint8_t)canMem[0].soc; //SOC % 2byte
|
||
SMKMem.rcc = 100 * ncc_Ah * OnlineNum * SMKMem.soc/100;//剩余容量 10mAH 2byte
|
||
SMKMem.fcc = 100 * ncc_Ah * OnlineNum; //额定容量 10mAH 2byte
|
||
SMKMem.packVoltage = (int16_t)(bmsMem.packVoltage/10); //模块电压 10mV 2byte
|
||
SMKMem.packCurrent = (int16_t)(canMem[0].cur); //模块电流 10mA 2byte
|
||
|
||
SMKMem.chgVolLimit = bmsMem.inverter_chgVolLimit * 10; //充电电压限制,上位机配置,默认值57.6V
|
||
if(chg_forbidFlg == 1)
|
||
{
|
||
SMKMem.chgCurLimit = 0; //SMK禁充
|
||
}
|
||
else if(chg_curlimitFlg == 1)
|
||
{
|
||
SMKMem.chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
|
||
}
|
||
else
|
||
{
|
||
SMKMem.chgCurLimit = (bmsMem.inverter_chgCurLimit * 10) * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
|
||
}
|
||
if(dsg_forbidFlg == 1)
|
||
{
|
||
SMKMem.dcsCurLimit = 0; //SMK禁放
|
||
}
|
||
else
|
||
{
|
||
SMKMem.dcsCurLimit = (bmsMem.inverter_dsgCurLimit * 10) * (OnlineNum-chg_curLimitNum); //放电电流限制,上位机配置,默认值100A
|
||
}
|
||
|
||
}
|
||
|
||
//SAKO 三科
|
||
void MOD_Protocol_SAKO(void)
|
||
{
|
||
MOD_Protocol_Voltronic();
|
||
}
|
||
|
||
//SNADI 佛山斯奈特
|
||
void MOD_Protocol_SNADI(void)
|
||
{
|
||
|
||
}
|
||
|
||
//invt 英威腾
|
||
void MOD_Protocol_invt(void)
|
||
{
|
||
|
||
}
|
||
|