Files
jiacun-20s-200A/PROTOCOL/ProtocolSwitch_P1.c
T
2026-08-25 17:30:40 +08:00

4811 lines
103 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.
/**
******************************************************************************
* @file InverterSwitch_Page1.c
* @author -
* @version -
* @date 2026.3.26
* @brief -
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
//这里放的是基本款的第1页函数,不根据发货要求变动
//CAN:
//1.Sol-Ark 2.GoodWe 3.Megarevo 4.Pylon
//5.Deye 6.MUST 7.solis 8.Growatt
//9.Aiswei 10.Afore 11.Victron 12.Sorotec
//Modbus:
//8.Growatt 12.Sorotec
//YDN:
//4.Pylon
//CAN:
//Sol-Ark
void CAN_Protocol_SolArk(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; // 平均温度
uint8_t alarmByte1 = 0;
uint8_t alarmByte2 = 0;
//保护
//放电过流保护
//discharge over currentSC, 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
{
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)
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//Sol-Ark
{
RequestFlag &= 0x7F; //禁充
}
if(dsg_forbidFlg == 1)//Sol-Ark
{
RequestFlag &= 0xBF; //禁放
}
if(chg_forceFlg == 1)//Sol-Ark
{
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) //0x379
{
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
data[0] = totalCapacity & 0xFF; //充电电压限制低位
data[1] = (totalCapacity >> 8) & 0xFF;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0X00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0X00;
CAN1_SendData(0x379, &data[0]);
}
if(CAN_SendCount ==6)
{
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>=7)
{
CAN_SendCount = 0;
}
}
//GoodWe 固德威
void CAN_Protocol_GoodWe(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 alarmByte1 = 0; //固德威在Cell Balance功能上protect和alarm显示不同
uint8_t alarmByte2 = 0;
int16_t T_Average; // 平均温度
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压-固德威
int16_t cellVolMin=0; // 电芯单体最低电压-固德威
uint16_t cellVolMaxIndex; // 电芯单体最高电压序号,范围0-15-固德威
int16_t cellVolMinIndex; // 电芯单体最低电压序号,范围0-15-固德威
//保护
//放电过流保护
//discharge over currentSC, 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;
}
// //Data1 BIT4 cell balance
// if((bmsMem.balanceStatus & 0x01) !=0)
// {
// protectByte2 |= 0x10;
// alarmByte2 &= 0xef;
// }
// else
// {
// protectByte2 &= 0xef;
// alarmByte2 |= 0x10;
// }
if(CAN_SendCount ==0) //ID = 0x359 - 报警/警告信息(前4行数据改为更直接的值,后面置0)
{
data[0] = protectByte1;
data[1] = protectByte2;
data[2] = alarmByte1;
data[3] = alarmByte2;
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 == 1)
{
chgCurLimit = 0; //GoodWe禁充
}
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; //GoodWe禁放
}
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] = 0x00;
data[7] = 0x00;
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; //温度-暂时取平均温度,具体哪一路需要客户确认 //signed有符号数
data[6] = 0x00;
data[7] = 0X00;
CAN1_SendData(0x356, &data[0]);
}
if(CAN_SendCount ==4) //ID = 0x35C - 充电/放电开关(已修改,由Data[0]的bit6、7控制)
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//GoodWe
{
RequestFlag &= 0x7F; //禁充
}
if(dsg_forbidFlg == 1)//GoodWe
{
RequestFlag &= 0xBF; //禁放
}
if(chg_forceFlg == 1)//GoodWe
{
RequestFlag |= 0x20; //强充
}
data[0] = 0XC0; //充电允许,放电允许
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) //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 ==6) //ID = 0x371 - 最大/最小单体温度ID,最大/最小单体电压ID(新加入)
{
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
cellVolMaxIndex = canMem[0].VolMaxIndex;
cellVolMinIndex = canMem[0].VolMinIndex;
data[0] = (T_MaxIndex+1) & 0xFF; //最大单体温度序号,实际显示从1开始
data[1] = ((T_MaxIndex+1) >> 8) & 0xFF;
data[2] = (T_MinIndex+1) & 0xFF; //最小单体温度序号
data[3] = ((T_MinIndex+1) >> 8) & 0xFF;
data[4] = (cellVolMaxIndex+1) & 0xFF; //最大单体电压序号
data[5] = ((cellVolMaxIndex+1) >> 8) & 0xFF;
data[6] = (cellVolMinIndex+1) & 0xFF; //最小单体电压序号
data[7] = ((cellVolMinIndex+1) >> 8) & 0xFF;
CAN1_SendData(0x371, &data[0]);
}
// if(CAN_SendCount ==7) //ID = 0x380 - 传递信息1-4(无要求)
// {
// data[0] = 'B';
// data[1] = ('B' >> 8) & 0xFF;
// data[2] = 'T';
// data[3] = ('T' >> 8) & 0xFF;
// data[4] = 'Y';
// data[5] = ('Y' >> 8) & 0xFF;
// data[6] = 'G';
// data[7] = ('G' >> 8) & 0xFF;
// CAN1_SendData(0x380, &data[0]);
// }
// if(CAN_SendCount ==8) //ID = 0x381 - 传递信息5-8(无要求)
// {
// data[0] = '-';
// data[1] = ('-' >> 8) & 0xFF;
// data[2] = 'B';
// data[3] = ('B' >> 8) & 0xFF;
// data[4] = 'M';
// data[5] = ('M' >> 8) & 0xFF;
// data[6] = 'S';
// data[7] = ('S' >> 8) & 0xFF;
// CAN1_SendData(0x381, &data[0]);
// }
if(CAN_SendCount>=7)
{
CAN_SendCount = 0;
}
}
//Megarevo 迈格瑞能
void CAN_Protocol_Megarevo(void)
{
uint8_t data[8];
uint16_t tempVol;
int16_t tempCur; //总电流
uint16_t chgVolLimit;
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_Average; // 平均温度
//保护
//放电过流保护
//discharge over currentSC, 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 |= 0x02;
}
else
{
protectByte2 &= 0xfD;
}
//告警
//放电过流告警
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] = 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 == 1)
{
chgCurLimit = 0; //Megarevo禁充
}
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; //Megarevo禁放
}
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] = 0x00;
data[7] = 0x00;
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;//单位0.1
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 = 0x35C --- 充放电允许
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//Megarevo
{
RequestFlag &= 0x7F; //禁充
}
if(dsg_forbidFlg == 1)//Megarevo
{
RequestFlag &= 0xBF; //禁放
}
if(chg_forceFlg == 1)//Megarevo
{
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;
}
}
//Pylon 派能
void CAN_Protocol_Pylon(void)
{
uint8_t data[8];
uint32_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 protectByte3 = 0;
uint8_t protectByte4 = 0;
uint8_t protectByte5 = 0;
uint8_t protectByte6 = 0;
uint8_t alarmByte1 = 0;
uint8_t alarmByte2 = 0;
int16_t T_Average; // 平均温度
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压-Pylon
uint16_t cellVolMin=0; // 电芯单体最低电压-Pylon
uint16_t cellVolMaxIndex_Byte1; // 电芯单体最高电压序号,范围0-15-Pylon
uint16_t cellVolMaxIndex_Byte2;
uint16_t cellVolMinIndex_Byte1; // 电芯单体最低电压序号,范围0-15-Pylon
uint16_t cellVolMinIndex_Byte2;
//保护
//放电过流保护
//discharge over currentSC, 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;
}
//Data0 BIT0.1 General[Cancel] //0000 0010
protectByte3 |= 0x02;
//保护
//放电高温保护
//over temp at discharging
if(((canMem[0].status_byte2 & 0x0008) != 0) || ((canMem[0].status_byte4 & 0x0202) != 0))
{
protectByte3 &= 0x7f;
protectByte3 |= 0x40;
}
else
{
protectByte3 &= 0xbf;
protectByte3 |= 0x80;
}
//欠压保护
//cell_uv+pack_uv+l0v
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
{
protectByte3 &= 0xdf;
protectByte3 |= 0x10;
}
else
{
protectByte3 &= 0xef;
protectByte3 |= 0x20;
}
// //过压保护
// //cell_ov+pack_ov+pf
// if((canMem[0].status_byte1 & 0x0141) != 0)
// {
// if(canMem[0].soc < 99)
// {
// protectByte3 &= 0xf7; //去掉leave
// protectByte3 |= 0x04; //赋值arrive
// }
// else
// {
// protectByte3 &= 0xfb;
// protectByte3 |= 0x08;
// }
// }
// else
// {
// protectByte3 &= 0xfb;
// protectByte3 |= 0x08;
// }
//放电过流保护
//discharge over currentSC, OCD1, OCD2
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
{
protectByte4 &= 0x7f;
protectByte4 |= 0x40;
}
else
{
protectByte4 &= 0xbf;
protectByte4 |= 0x80;
}
//充电低温保护
//Data1 BIT4.5 under temp at charging //0001 0000
if( ((canMem[0].status_byte2 & 0x0001) != 0) || ((canMem[0].status_byte4 & 0x0404) != 0) )
{
protectByte4 &= 0xdf;
protectByte4 |= 0x10;
}
else
{
protectByte4 &= 0xef;
protectByte4 |= 0x20;
}
//充电高温保护
//Data1 BIT2.3 over temp at charging //0000 0100
if( ((canMem[0].status_byte2 & 0x0002) != 0) || ((canMem[0].status_byte4 & 0x0101) != 0) )
{
protectByte4 &= 0xf7;
protectByte4 |= 0x04;
}
else
{
protectByte4 &= 0xfb;
protectByte4 |= 0x08;
}
//放电低温保护
//Data1 BIT0.1 under temp at discharging //0000 0001
if( ((canMem[0].status_byte2 & 0x0004) != 0) || ((canMem[0].status_byte4 & 0x0808) != 0) )
{
protectByte4 &= 0xfd;
protectByte4 |= 0x01;
}
else
{
protectByte4 &= 0xfe;
protectByte4 |= 0x02;
}
//短路
//Data2 BIT4.5 short circuit //0001 0000
if((canMem[0].status_byte1 & 0x20) != 0)
{
protectByte5 &= 0xdf;
protectByte5 |= 0x10;
}
else
{
protectByte5 &= 0xef;
protectByte5 |= 0x20;
}
//充电过流保护
//charge over current
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
{
protectByte5 &= 0xfd;
protectByte5 |= 0x01;
}
else
{
protectByte5 &= 0xfe;
protectByte5 |= 0x02;
}
//Data2 BIT2.3 Contactor[Cancel] //0000 1000
protectByte5 |= 0x08;
//Data2 BIT6.7 BMS internal[Cancel] //1000 0000
protectByte5 |= 0x80;
// //Data3 BIT0.1 cell imbanlance //0000 0001
// if((bmsMem.balanceStatus & 0x01) !=0) //0x01表示平衡
// {
// protectByte6 &= 0xfe;
// protectByte6 |= 0x02;
// }
// else
// {
// protectByte6 &= 0xfd;
// protectByte6 |= 0x01;
// }
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; //Pylon禁充
}
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; //Pylon禁放
}
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 = 0x35C --- 充放电允许
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//Pylon
{
RequestFlag &= 0x7F; //禁充
}
if(dsg_forbidFlg == 1)//Pylon
{
RequestFlag &= 0xBF; //禁放
}
if(chg_forceFlg == 1)//Pylon
{
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) //ID = 0x35E --- 电池厂商
{
data[0] = 'P';
data[1] = 'Y';
data[2] = 'L';
data[3] = 'O';
data[4] = 'N';
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x35E, &data[0]);
}
if(CAN_SendCount ==6) //ID = 0x373 - 最大/最小单体电压/温度(与固德威配置相同)
{
cellVolMax = canMem[0].VolMax;
cellVolMin = canMem[0].VolMin;
T_Max = canMem[0].TempMax/10; // 最高温度
T_Min = canMem[0].TempMin/10; // 最低温度
data[0] = cellVolMin & 0xFF; //最小单体电压
data[1] = (cellVolMin >> 8) & 0xFF;
data[2] = cellVolMax & 0xFF; //最大单体电压
data[3] = (cellVolMax >> 8) & 0xFF;
data[4] = (T_Min ) & 0xFF; //最小单体温度
data[5] = ((T_Min ) >> 8) & 0xFF;
data[6] = (T_Max ) & 0xFF; //最大单体温度
data[7] = ((T_Max ) >> 8) & 0xFF;
CAN1_SendData(0x373, &data[0]);
}
if(CAN_SendCount ==7) //ID = 0x379 --- 容量
{
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
data[0] = (totalCapacity >> 0 ) & 0xFF; //电池容量
data[1] = (totalCapacity >> 8 ) & 0xFF;
data[2] = (totalCapacity >> 16) & 0xFF;
data[3] = (totalCapacity >> 24) & 0xFF;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x379, &data[0]);
}
if(CAN_SendCount ==8) //ID = 0x35A - Alarms/Warnings
{
data[0] = protectByte3;
data[1] = protectByte4;
data[2] = protectByte5;
data[3] = protectByte6;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x35A, &data[0]);
}
if(CAN_SendCount ==9) //ID = 0x374 - 最小电池电压地址
{
if((canMem[0].VolMinIndex + 1) >= 10)
{
cellVolMinIndex_Byte1 = 1;
cellVolMinIndex_Byte2 = (canMem[0].VolMinIndex+1)-10;
}
else
{
cellVolMinIndex_Byte1 = 0;
cellVolMinIndex_Byte2 = (canMem[0].VolMinIndex+1);
}
data[0] = '0';
data[1] = '1';
data[2] = 0x30 + cellVolMinIndex_Byte1;
data[3] = 0X30 + cellVolMinIndex_Byte2;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x374, &data[0]);
}
if(CAN_SendCount ==10) //ID = 0x375 - 最大电池电压地址
{
if((canMem[0].VolMaxIndex+1)>= 10)
{
cellVolMaxIndex_Byte1 = 1;
cellVolMaxIndex_Byte2 = (canMem[0].VolMaxIndex+1)-10;
}
else
{
cellVolMaxIndex_Byte1 = 0;
cellVolMaxIndex_Byte2 = (canMem[0].VolMaxIndex+1);
}
data[0] = '0';
data[1] = '1';
data[2] = 0x30 + cellVolMaxIndex_Byte1;
data[3] = 0x30 + cellVolMaxIndex_Byte2;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x375, &data[0]);
}
if(CAN_SendCount ==11) //ID = 0x376 - 最小电池温度地址
{
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
data[0] = '0';
data[1] = '1';
data[2] = '0';
data[3] = 0x30 + (T_MinIndex+1);
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x376, &data[0]);
}
if(CAN_SendCount ==12) //ID = 0x377 - 最大电池温度地址
{
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
data[0] = '0';
data[1] = '1';
data[2] = '0';
data[3] = 0x30 + (T_MaxIndex+1);
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x377, &data[0]);
}
if(CAN_SendCount>=13)
{
CAN_SendCount = 0;
}
}
//Deye 德业
uint8_t Deye_dsg_forbidFlg; //单独属于德业的标志
void CAN_Protocol_Deye(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_Average; // 平均温度
//保护
//放电过流保护
//discharge over currentSC, 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(canMem[0].soc<=5) //Deye自己的强充标志变化值
{
Deye_dsg_forbidFlg = 1;
}
else if(canMem[0].soc>=10)
{
Deye_dsg_forbidFlg = 0;
}
if(CAN_SendCount ==0) //ID = 0x359 --- 报警/保护
{
data[0] = protectByte1; //电芯过压
data[1] = protectByte2;
data[2] = alarmByte1;
data[3] = alarmByte2;
data[4] = 0X00;
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; //Deye禁充
}
else if(chg_curlimitFlg == 1)
{
chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
}
else
{
chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
}
if(Deye_dsg_forbidFlg == 1)
{
dsgCurLimit = 0; //Deye禁放(范围是5%和10%,与其他协议分开)
}
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;//单位0.1
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 = 0x35C --- 强充
{
if(Deye_dsg_forbidFlg == 1) //Deye独有的强充标志变化值
{
RequestFlag = 0x20; //强充请求
}
else
{
RequestFlag = 0x00; //停止强充
}
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) //0x35E --- 电池品牌
{
data[0] = 0x00;
data[1] = 0x00;
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>=6)
{
CAN_SendCount = 0;
}
}
//MUST 美世乐
void CAN_Protocol_MUST(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 alarmByte1 = 0;
int16_t T_Average; // 平均温度
//告警
// //过压告警
// if((canMem[0].status_byte3 & 0x0500) != 0)
// {
// if(canMem[0].soc < 99)
// {
// protectByte1 |= 0x01;
// }
// else
// {
// protectByte1 &= 0xfe;
// }
// }
// else
// {
// protectByte1 &= 0xfe;
// }
//欠压告警
if((canMem[0].status_byte3 & 0x0A00) != 0)
{
alarmByte1 |= 0x02;
}
else
{
alarmByte1 &= 0xfd;
}
//充电过流告警
if((canMem[0].status_byte3 & 0x1000) != 0)
{
alarmByte1 |= 0x04;
}
else
{
alarmByte1 &= 0xfb;
}
//放电过流告警
if((canMem[0].status_byte3 & 0x2000) != 0)
{
alarmByte1 |= 0x08;
}
else
{
alarmByte1 &= 0xf7;
}
//过温告警
if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0))
{
alarmByte1 |= 0x10;
}
else
{
alarmByte1 &= 0xEF;
}
//低温告警
if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0))
{
alarmByte1 |= 0x20;
}
else
{
alarmByte1 &= 0xdf;
}
// BIT6 short circuit
if((canMem[0].status_byte1 & 0x20) != 0)
{
alarmByte1 |= 0x40;
}
else
{
alarmByte1 &= 0xbf;
}
if(CAN_SendCount ==0) //ID = 0x00030400 - 电池电压、电流、温度、报警
{
tempVol = (uint16_t)(bmsMem.packVoltage/100); //单位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)/10) & 0xFF;
data[5] = ((T_Average -2731)/10 >>8) & 0xFF; //温度-暂时取平均温度,具体哪一路需要客户确认 //signed有符号数
data[6] = alarmByte1;
data[7] = 0x00;
CAN1_SendData(0x00030400, &data[0]);
}
if(CAN_SendCount ==1) //ID = 0x00030500 —— 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(0x00030500, &data[0]);
}
if(CAN_SendCount ==2) //ID = 0x00030200 --- 电池禁用/SOC禁用(先给0x00测试,后换成0xFF测试)
{
data[0] = 0x00; //电池禁用标志
data[1] = 0x00;
data[2] = 0x00; //SOC禁用标志
data[3] = 0x00;
if(chg_forbidFlg == 1)//MUST
{
RequestFlag = 0xFF; //禁充
}
else
{
RequestFlag = 0x00; //充电允许
}
data[4] = RequestFlag; //电池充电禁用标志
data[5] = RequestFlag;
if(dsg_forbidFlg == 1)//MUST
{
RequestFlag = 0xFF; //禁放
}
else
{
RequestFlag = 0x00; //放电允许
}
data[6] = RequestFlag; //电池放电禁用标志
data[7] = RequestFlag;
CAN1_SendData(0x00030200, &data[0]);
}
if(CAN_SendCount ==3) //ID = 0x00030100 —— 充放电限压/限流
{
//充放电电流限制需要有符号区别吗?
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
if(chg_forbidFlg == 1)
{
chgCurLimit = 0; //MUST禁充
}
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; //MUST禁放
}
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] = dsgVolLimit & 0xFF; //放电电压限制低位
data[5] = (dsgVolLimit >> 8) & 0xFF;
data[6] = dsgCurLimit & 0xFF; //放电电流限制低位
data[7] = (dsgCurLimit >> 8) & 0xFF;
CAN1_SendData(0x00030100, &data[0]);
}
if(CAN_SendCount ==4) //ID = 0x00030700 - 充放电/循环/远程快速停止命令(需要定制,先给0xFF)
{
if(chg_forceFlg == 1)//MUST
{
RequestFlag = 0xFF; //强充
}
else
{
RequestFlag = 0x00; //不强充
}
data[0] = RequestFlag; //强充指令
data[1] = RequestFlag;
data[2] = 0x00; //强放指令
data[3] = 0x00;
data[4] = 0x00; //循环指令
data[5] = 0x00;
data[6] = 0x00; //远程快速停止指令
data[7] = 0x00;
CAN1_SendData(0x00030700, &data[0]);
}
if(CAN_SendCount>=5)
{
CAN_SendCount = 0;
}
}
//solis 锦浪
void CAN_Protocol_solis(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_Average; // 平均温度
//保护
//放电过流保护
//discharge over currentSC, 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 告警
{
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 == 1)
{
chgCurLimit = 0; //GINLONG禁充
}
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; //GINLONG禁放
}
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 = 0x35C 强充/满充
{
if(chg_forceFlg == 1)//QINLONG
{
RequestFlag = 0x20; //强充请求
}
else
{
RequestFlag = 0x00; //停止强充
}
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) //0x35E
{
totalCapacity = ncc_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 ==6) //ID = 0x71C
{
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00; //电池序列号
data[4] = 0x00;
data[5] = 0x00; //BMS固件版本
data[6] = 0x00; //产品型号
data[7] = 0x00;
CAN1_SendData(0x71C, &data[0]);
}
if(CAN_SendCount>=7)
{
CAN_SendCount = 0;
}
}
//Growatt 古瑞瓦特
void CAN_Protocol_Growatt(void) //特改8.8
{
uint8_t data[8];
uint16_t totalCapacity; //总容量
uint16_t remainCapacity; //剩余容量
int16_t tempVol; //总电压
int16_t tempCur; //总电流
uint16_t chgVolLimit; //充电限压
// uint16_t dsgVolLimit; //放电限压
uint16_t chgCurLimit; //充电限流
uint16_t dsgCurLimit; //放电限流
uint8_t protectByte1 = 0; //保护位1,与告警位1值相同
uint8_t protectByte2 = 0; //保护位2,与告警位2值相同
uint8_t statusByte1 = 0; //状态位1
uint8_t statusByte2 = 0; //状态位2
uint8_t totalNum = 0; //总电池节数
int16_t T_Average; // 平均温度
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压
uint16_t cellVolMin=0; // 电芯单体最低电压
uint16_t cellVolMaxIndex; // 电芯单体最高电压序号,范围0-15
uint16_t cellVolMinIndex; // 电芯单体最低电压序号,范围0-15
//保护、报警赋值:
//Data0 BIT3 cell uv-under voltage
if((canMem[0].status_byte1 & 0x02) !=0)
{
protectByte1 |= 0x08;
}
else
{
protectByte1 &= 0xF7;
}
//Data0 BIT4 cell ov-over voltage
if((canMem[0].status_byte1 & 0x01) !=0)
{
if(canMem[0].soc < 99)
{
protectByte1 |= 0x10;
}
else
{
protectByte1 &= 0xEF;
}
}
else
{
protectByte1 &= 0xEF;
}
//Data0 BIT5 sc-short circuit
//Data0 BIT6 occ-charge over current
if( ((canMem[0].status_byte1 & 0x10) !=0) || ((canMem[0].status_byte4 & 0x10) !=0) )
{
protectByte1 |= 0x40;
}
else
{
protectByte1 &= 0xBF;
}
//Data0 BIT7 ocd-discharge over current
if( ((canMem[0].status_byte1 & 0x2c) !=0) || ((canMem[0].status_byte4 & 0x20) !=0) )
{
protectByte1 |= 0x80;
}
else
{
protectByte1 &= 0x7F;
}
// //Data1 BIT2 cell imbalance
// if((bmsMem.balanceStatus & 0x01) !=0) //表示开启了均衡
// {
// protectByte2 |= 0xFB;
// }
// else
// {
// protectByte2 &= 0x04;
// }
//Data1 BIT4 cell utc-charge under temp
if( ((canMem[0].status_byte2 & 0x01) !=0) || ((canMem[0].status_byte4 & 0x04) !=0) )
{
protectByte2 |= 0x10;
}
else
{
protectByte2 &= 0xEF;
}
//Data1 BIT5 cell utd-discharge under temp
if( ((canMem[0].status_byte2 & 0x04) !=0) || ((canMem[0].status_byte4 & 0x08) !=0) )
{
protectByte2 |= 0x20;
}
else
{
protectByte2 &= 0xDF;
}
//Data1 BIT6 cell otc-charge over temp
if( ((canMem[0].status_byte2 & 0x02) !=0) || ((canMem[0].status_byte4 & 0x01) !=0) )
{
protectByte2 |= 0x40;
}
else
{
protectByte2 &= 0xBF;
}
//Data1 BIT7 cell otd-discharge over temp
if( ((canMem[0].status_byte2 & 0x08) !=0) || ((canMem[0].status_byte4 & 0x02) !=0) )
{
protectByte2 |= 0x80;
}
else
{
protectByte2 &= 0x7F;
}
//状态位赋值:
if(bmsMem.E2_485Snum != 1) //01并机/00单机模式
{
statusByte1 |= 0x01;
}
else
{
statusByte1 &= 0xFE;
}
if(bCHGING == 1) //充电
{
statusByte2 |= 0x02;
}
else
{
statusByte2 &= 0xFD;
}
if(bDSGING == 1) //放电
{
statusByte2 |= 0x03;
}
else
{
statusByte2 &= 0xFC;
}
// if((bmsMem.balanceStatus & 0x01) !=0) //均衡状态
// {
// statusByte2 |= 0x08;
// }
// else
// {
// statusByte2 &= 0xF7;
// }
if(CAN_SendCount ==0) //ID = 0x311
{
//充放电电流限制需要有符号区别吗?
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; //Growatt禁充
}
if(dsg_forbidFlg == 0)
{
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
}
else
{
dsgCurLimit = 0; //Growatt禁放
}
statusByte2 |= 0x60;
if(chg_forbidFlg == 1)//Growatt
{
statusByte2 &= ~0x40; //禁充 bit6
}
if(dsg_forbidFlg == 1)//Growatt
{
statusByte2 &= ~0x20; //禁放 bit5
}
data[0] = (chgVolLimit >> 8) & 0xFF;
data[1] = chgVolLimit & 0xFF; //充电电压限制低位
data[2] = (chgCurLimit >> 8) & 0xFF;
data[3] = chgCurLimit & 0xFF; //充电电流限制低位
data[4] = (dsgCurLimit >> 8) & 0xFF;
data[5] = dsgCurLimit & 0xFF; //放电电流限制低位
data[6] = statusByte1;
data[7] = statusByte2; //状态位
CAN1_SendData(0x311, &data[0]);
}
if(CAN_SendCount ==1) //ID = 0x312 - 保护/告警
{
data[0] = protectByte1;
data[1] = protectByte2;
data[2] = protectByte1;
data[3] = protectByte2;
data[4] = OnlineNum;
data[5] = 0X00;
data[6] = 0X00; //电池降功率原因(暂无)
data[7] = 0X00;
CAN1_SendData(0x312, &data[0]);
}
if(CAN_SendCount ==2) //ID = 0x313
{
tempVol = (int16_t)(bmsMem.packVoltage/10); //单位0.01
tempCur = (int16_t)(canMem[0].cur/10); //单位0.1
T_Average = canMem[0].temp;// 平均温度
data[0] = (tempVol >>8) & 0xFF; //电池组电压 0.01
data[1] = tempVol & 0xFF;
data[2] = (tempCur >>8) & 0xFF; //电池组电流 0.1
data[3] = tempCur & 0xFF;
data[4] = ((T_Average-2731) >>8) & 0xFF;
data[5] = (T_Average-2731) & 0xFF; //平均温度 0.1
data[6] = canMem[0].soc & 0xFF; //SOC
data[7] = canMem[0].soh & 0xFF; //SOH
CAN1_SendData(0x313, &data[0]);
}
if(CAN_SendCount ==3) //ID = 0x314
{
totalCapacity = 100 * fcc_Ah * OnlineNum; //单位0.01Ah
remainCapacity = 100 * rcc_Ah * OnlineNum; //单位0.01Ah
data[0] = (remainCapacity >> 8) & 0xFF;
data[1] = remainCapacity & 0xFF; //剩余容量 10mAh
data[2] = (totalCapacity >> 8) & 0xFF;
data[3] = totalCapacity & 0xFF; //电池满充容量 10mAh
data[4] = 0x00;
data[5] = (canMem[0].VolMax - canMem[0].VolMin) & 0xFF; //最大电压差 1mV
data[6] = 0x00;
data[7] = 0x00; //循环次数(暂无)
CAN1_SendData(0x314, &data[0]);
}
if(CAN_SendCount ==4) //ID = 0x319 - 电池最低最高单体电压
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//Growatt
{
RequestFlag &= ~0x80; //禁充
}
if(dsg_forbidFlg == 1)//Growatt
{
RequestFlag &= ~0x40; //禁放
}
if(chg_forceFlg == 1)//Growatt
{
RequestFlag |= 0x20; //强充
}
cellVolMax = canMem[0].VolMax;
cellVolMin = canMem[0].VolMin;
cellVolMaxIndex = canMem[0].VolMaxIndex;
cellVolMinIndex = canMem[0].VolMinIndex;
data[0] = RequestFlag; //充电允许放电允许 电池类型00
data[1] = (cellVolMax >> 8) & 0xFF;
data[2] = cellVolMax & 0xFF; //最大单体电压
data[3] = (cellVolMin >> 8) & 0xFF;
data[4] = cellVolMin & 0xFF; //最小单体电压
data[5] = (cellVolMaxIndex+1) & 0xFF; //最大单体电压序号
data[6] = (cellVolMinIndex+1) & 0xFF; //最小单体电压序号
data[7] = 0x00; //故障电池地址(暂无)
CAN1_SendData(0x319, &data[0]);
}
if(CAN_SendCount ==5) //ID = 0x320 - 制造商缩写RICN SMART
{
data[0] = 'S';
data[1] = 'R'; //制造商缩写
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x320, &data[0]);
}
if(CAN_SendCount ==6) //ID = 0x322 - 电池最低最高单体温度
{
T_Max = canMem[0].TempMax; // 最高温度
T_Min = canMem[0].TempMin; // 最低温度
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
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] = (T_MaxIndex+1) & 0xFF; //最高单体温度序号
data[5] = (T_MinIndex+1) & 0xFF; //最低单体温度序号
data[6] = 100; //最大SOC
data[7] = 0; //最小SOC
CAN1_SendData(0x322, &data[0]);
}
if(CAN_SendCount ==7) //ID = 0x323 - 总电池节数
{
totalNum = bmsMem.ucCellNum * OnlineNum;
data[0] = totalNum; //总电池节数 1-254 U8
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x323, &data[0]);
}
if(CAN_SendCount>=8)
{
CAN_SendCount = 0;
}
}
//Aiswei 爱士惟
void CAN_Protocol_Aiswei(void)
{
uint8_t data[8];
uint16_t totalCapacity;
uint16_t tempVol;
int16_t tempCur;
uint16_t chgVolLimit;
// uint16_t dsgVolLimit;
uint16_t chgCurLimit;
uint16_t dsgCurLimit;
uint8_t protectByte1 = 0;
uint8_t protectByte2 = 0;
int16_t T_Average; // 平均温度
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压-Aiswei
uint16_t cellVolMin=0; // 电芯单体最低电压-Aiswei
uint16_t cellVolMaxIndex; // 电芯单体最高电压序号,范围0-15-Aiswei
uint16_t cellVolMinIndex; // 电芯单体最低电压序号,范围0-15-Aiswei
uint8_t alarmByte1 = 0;
uint8_t alarmByte2 = 0;
//保护
//放电过流保护
//discharge over currentSC, 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 - 保护与警告(与Sol-Ark配置相同)
{
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 - 充电电压/充电限流/放电限流(前3个与Sol-Ark配置相同,无4)
{
//充放电电流限制需要有符号区别吗?
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
//dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
if(chg_forbidFlg == 1)
{
chgCurLimit = 0; //Aiswei禁充
}
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; //Aiswei禁放
}
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] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x351, &data[0]);
}
if(CAN_SendCount ==2) //ID: 0x355 - SOC/SOH(与Sol-Ark配置相同)
{
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 - 系统电压/系统总电流/平均单体温度(与Sol-Ark配置相同)
{
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: 0x35C - 满充请求/强制充电请求I/强制充电请求II/放电允许/充电允许(与Sol-Ark配置相同)
{
RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20
if(chg_forbidFlg == 1)//Aiswei
{
RequestFlag &= 0x7F; //禁充
}
if(dsg_forbidFlg == 1)//Aiswei
{
RequestFlag &= 0xBF; //禁放
}
if(chg_forceFlg == 1)//Aiswei
{
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) //ID: 0x379 - 总容量/当前在线数量(与Sol-Ark配置相同)
{
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
data[0] = totalCapacity & 0xFF; //电池容量
data[1] = (totalCapacity >> 8) & 0xFF;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0X00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0X00;
CAN1_SendData(0x379, &data[0]);
}
if(CAN_SendCount ==6) //ID: 0x35e - 厂家名称"AISWEI"-ASCII(与Sol-Ark配置相同)
{
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 ==7) //ID = 0x373 - 最大/最小单体电压/温度(与固德威配置相同)
{
cellVolMax = canMem[0].VolMax/100;
cellVolMin = canMem[0].VolMin/100;
T_Max = canMem[0].TempMax; // 最高温度
T_Min = canMem[0].TempMin; // 最低温度
data[0] = cellVolMin & 0xFF; //最小单体电压
data[1] = (cellVolMin >> 8) & 0xFF;
data[2] = cellVolMax & 0xFF; //最大单体电压
data[3] = (cellVolMax >> 8) & 0xFF;
data[4] = (T_Min -2731) & 0xFF; //最小单体温度
data[5] = ((T_Min -2731) >> 8) & 0xFF;
data[6] = (T_Max -2731) & 0xFF; //最大单体温度
data[7] = ((T_Max -2731) >> 8) & 0xFF;
CAN1_SendData(0x373, &data[0]);
}
if(CAN_SendCount ==8) //ID: 0x374 - 最大/最小单体温度/电压的ID(与固德威配置相同)
{
cellVolMaxIndex = canMem[0].VolMaxIndex;
cellVolMinIndex = canMem[0].VolMinIndex;
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
data[0] = (cellVolMinIndex+1) & 0xFF; //最小单体电压序号
data[1] = ((cellVolMinIndex+1) >> 8) & 0xFF;
data[2] = (cellVolMaxIndex+1) & 0xFF; //最大单体电压序号
data[3] = ((cellVolMaxIndex+1) >> 8) & 0xFF;
data[4] = (T_MinIndex+1) & 0xFF; //最小单体温度序号
data[5] = ((T_MinIndex+1) >> 8) & 0xFF;
data[6] = (T_MaxIndex+1) & 0xFF; //最大单体温度序号,实际显示从1开始
data[7] = ((T_MaxIndex+1) >> 8) & 0xFF;
CAN1_SendData(0x374, &data[0]);
}
if(CAN_SendCount>=9)
{
CAN_SendCount = 0;
}
}
//Afore 艾伏
void CAN_Protocol_Afore(void)
{
uint8_t data[8];
uint16_t tempVol;
int16_t tempCur;
uint16_t chgVolLimit;
uint16_t dsgVolLimit;
uint16_t chgCurLimit;
uint16_t dsgCurLimit;
uint8_t protectByte1 = 0; //故障H
uint8_t protectByte2 = 0; //故障
uint8_t statusbyte = 0; //故障L
uint8_t alarmByte1 = 0; //告警
uint8_t alarmByte2 = 0;
int16_t T_Average; // 平均温度
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压-Afore
uint16_t cellVolMin=0; // 电芯单体最低电压-Afore
uint16_t cellVolMaxIndex; // 电芯单体最高电压序号,范围0-15-Afore
uint16_t cellVolMinIndex; // 电芯单体最低电压序号,范围0-15-Afore
//保护
//充电过流保护
//charge over current
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 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 |= 0x20;
}
else
{
protectByte1 &= 0xDF;
}
//过温保护
//over temp at charging or discharging
if(((canMem[0].status_byte2 & 0x000A) != 0) || ((canMem[0].status_byte4 & 0x0303) != 0))
{
protectByte1 |= 0x40;
}
else
{
protectByte1 &= 0xBF;
}
//总体欠压保护
if((canMem[0].status_byte1 & 0x0200) !=0)
{
protectByte1 |= 0x08;
}
else
{
protectByte1 &= 0xF7;
}
// //总体过压保护
// if((canMem[0].status_byte1 & 0x0100) !=0)
// {
// if(canMem[0].soc < 99)
// {
// protectByte1 |= 0x04;
// }
// else
// {
// protectByte1 &= 0xFb;
// }
// }
// else
// {
// protectByte1 &= 0xFb;
// }
//单体欠压保护
if(((canMem[0].status_byte1 & 0x0002) !=0) || ((canMem[0].status_byte3 & 0x0008) != 0))
{
protectByte1 |= 0x02;
}
else
{
protectByte1 &= 0xFD;
}
// //单体过压保护
// if(((canMem[0].status_byte1 & 0x0001) !=0) || ((canMem[0].status_byte1 & 0x0040) != 0))
// {
// if(canMem[0].soc < 99)
// {
// protectByte1 |= 0x01;
// }
// else
// {
// protectByte1 &= 0xFE;
// }
// }
// else
// {
// protectByte1 &= 0xFE;
// }
//放电过流保护
//discharge over currentSC, OCD1, OCD2
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
{
protectByte2 |= 0x01;
}
else
{
protectByte2 &= 0xFE;
}
//告警
//低温告警
if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0))
{
alarmByte1 |= 0x80;
}
else
{
alarmByte1 &= 0x7F;
}
//过温告警
if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0))
{
alarmByte1 |= 0x40;
}
else
{
alarmByte1 &= 0xBF;
}
//总体欠压告警
if((canMem[0].status_byte3 & 0x0800) !=0)
{
alarmByte1 |= 0x08;
}
else
{
alarmByte1 &= 0xF7;
}
// //总体过压告警
// if((canMem[0].status_byte3 & 0x0400) !=0)
// {
// if(canMem[0].soc < 99)
// {
// alarmByte1 |= 0x04;
// }
// else
// {
// alarmByte1 &= 0xFb;
// }
// }
// else
// {
// alarmByte1 &= 0xFb;
// }
//单体欠压告警
if((canMem[0].status_byte3 & 0x0200) !=0)
{
alarmByte1 |= 0x02;
}
else
{
alarmByte1 &= 0xFD;
}
// //单体过压告警
// if((canMem[0].status_byte3 & 0x0100) !=0)
// {
// alarmByte1 |= 0x01;
// }
// else
// {
// alarmByte1 &= 0xFE;
// }
//放电过流告警
if((canMem[0].status_byte3 & 0x2000) != 0)
{
alarmByte2 |= 0x02;
}
else
{
alarmByte2 &= 0xFD;
}
//充电过流告警
if((canMem[0].status_byte3 & 0x1000) != 0)
{
alarmByte2 |= 0x01;
}
else
{
alarmByte2 &= 0xFE;
}
// if((bmsMem.balanceStatus & 0x01) !=0) //均衡状态
// {
// statusbyte |= 0x80;
// }
// else
// {
// statusbyte &= 0x7F;
// }
if(CAN_SendCount ==0) //ID: 0x350 - 运行信息(系统电压/系统总电流/平均单体温度)
{
tempVol = (uint16_t)(bmsMem.packVoltage/100); //单位0.1V
tempCur = (int16_t)((canMem[0].cur/10) + 5000); //单位0.1A(偏移5000)
T_Average = (canMem[0].temp + 1000);// 平均温度 单位0.1℃(偏移1000)
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(0x350, &data[0]);
}
if(CAN_SendCount ==1) //ID: 0x351 - 电池信息(SOC/SOH)
{
RequestFlag = 0x23; //充电允许0x01,放电允许0x02,不强充~0x04
if(chg_forbidFlg == 1)//Afore
{
RequestFlag &= 0xFE; //禁充
}
if(dsg_forbidFlg == 1)//Afore
{
RequestFlag &= 0xFD; //禁放
}
if(chg_forceFlg == 1)//Afore
{
RequestFlag |= 0x04; //强充
}
data[0] = canMem[0].soc & 0xFF; //SOC
data[1] = canMem[0].soh & 0xFF; //SOH
data[2] = 0x64; //最大SOC
data[3] = 0x00; //最小SOC
data[4] = RequestFlag; //充放电允许及BMS工作状态
data[5] = 0x00;
data[6] = bmsMem.ucCellNum; //电芯数量
data[7] = 0X00;
CAN1_SendData(0x351, &data[0]);
}
if(CAN_SendCount ==2) //ID: 0x352 - 保护参数(充/放电限流/压)
{
//充放电电流限制需要有符号区别吗?
chgVolLimit = bmsMem.inverter_chgVolLimit; //充电电压限制,上位机配置,默认值57.6V
dsgVolLimit = bmsMem.inverter_dsgVolLimit; //放电电压限制,上位机配置,默认值41.6V
if(chg_forbidFlg == 1)
{
chgCurLimit = 0; //Afore禁充
}
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; //Afore禁放
}
else
{
dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A
}
data[0] = chgCurLimit & 0xFF; //充电电流限制低位
data[1] = (chgCurLimit >> 8) & 0xFF;
data[2] = dsgCurLimit & 0xFF; //放电电流限制低位
data[3] = (dsgCurLimit >> 8) & 0xFF;
data[4] = chgVolLimit & 0xFF; //充电电压限制低位
data[5] = (chgVolLimit >> 8) & 0xFF;
data[6] = dsgVolLimit & 0xFF; //放电电压限制低位
data[7] = (dsgVolLimit >> 8) & 0xFF;
CAN1_SendData(0x352, &data[0]);
}
if(CAN_SendCount ==3) //ID: 0x353 - 故障
{
data[0] = protectByte1;//故障H
data[1] = protectByte2;//故障L
data[2] = 0x00;
data[3] = statusbyte;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x353, &data[0]);
}
if(CAN_SendCount ==4) //ID = 0x354 - 单体电压参数(最大/最小单体电压及序号)
{
cellVolMax = canMem[0].VolMax;
cellVolMin = canMem[0].VolMin;
cellVolMaxIndex = canMem[0].VolMaxIndex;
cellVolMinIndex = canMem[0].VolMinIndex;
data[0] = cellVolMax & 0xFF; //最大单体电压
data[1] = (cellVolMax >> 8) & 0xFF;
data[2] = cellVolMin & 0xFF; //最小单体电压
data[3] = (cellVolMin >> 8) & 0xFF;
data[4] = (cellVolMaxIndex+1) & 0xFF; //最大单体电压序号
data[5] = ((cellVolMaxIndex+1) >> 8) & 0xFF;
data[6] = (cellVolMinIndex+1) & 0xFF; //最小单体电压序号
data[7] = ((cellVolMinIndex+1) >> 8) & 0xFF;
CAN1_SendData(0x354, &data[0]);
}
if(CAN_SendCount ==5) //ID = 0x355 - 单体温度参数(最大/最小温度及序号)
{
T_Max = (canMem[0].TempMax + 1000); // 最高温度 单位0.1℃ (偏移1000)
T_Min = canMem[0].TempMin; // 最低温度 单位0.1℃ (协议中未要求偏移)
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
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] = (T_MaxIndex+1) & 0xFF; //最大单体温度序号,实际显示从1开始
data[5] = ((T_MaxIndex+1) >> 8) & 0xFF;
data[6] = (T_MinIndex+1) & 0xFF; //最小单体温度序号
data[7] = ((T_MinIndex+1) >> 8) & 0xFF;
CAN1_SendData(0x355, &data[0]);
}
if(CAN_SendCount ==6) //ID = 0x357 - 告警信息
{
data[0] = alarmByte1;
data[1] = alarmByte2;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x357, &data[0]);
}
if(CAN_SendCount ==7) //ID: 0x356 - 单体保护参数(因电池特性不同,参数暂未给定)
{
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x356, &data[0]);
}
if(CAN_SendCount ==8) //ID=0x358 - 版本信息
{
data[0] = 0x00;//硬件版本V
data[1] = 0x00;//硬件版本R
data[2] = 0x00;//软件版本V
data[3] = 0x00;//软件版本R
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x358, &data[0]);
}
if(CAN_SendCount ==9) //ID=0x359 电池SN 0~7
{
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x359, &data[0]);
}
if(CAN_SendCount ==10) //ID=0x35A - 电池SN 8~15
{
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x00;
CAN1_SendData(0x35A, &data[0]);
}
if(CAN_SendCount>=11)
{
CAN_SendCount = 0;
}
}
//Victron 维克托
void CAN_Protocol_Victron(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 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 = 0;
int16_t T_Max; // 最高温度
int16_t T_Min; // 最低温度
uint16_t T_MaxIndex;// 最高温度序号,范围0-6
uint16_t T_MinIndex;// 最低温度序号,范围0-6
uint16_t cellVolMax=0; // 电芯单体最高电压-Victron
uint16_t cellVolMin=0; // 电芯单体最低电压-Victron
uint16_t cellVolMaxIndex_Byte1; // 电芯单体最高电压序号,范围0-15-Victron
uint16_t cellVolMaxIndex_Byte2;
uint16_t cellVolMinIndex_Byte1; // 电芯单体最低电压序号,范围0-15-Victron
uint16_t cellVolMinIndex_Byte2;
//Data0 BIT0.1 General[Cancel] //0000 0010
protectByte1 |= 0x01;
//保护
//放电高温保护
//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 currentSC, 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; //Victron禁充
}
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; //Victron禁放
}
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;//单位0.1
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 = 0x370 - 电池/BMS名称第1部分
{
data[0] = 'B';
data[1] = 'T';
data[2] = 'Y';
data[3] = 'G';
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x370, &data[0]);
}
if(CAN_SendCount ==6) //ID = 0x371 - 电池/BMS名称第2部分
{
data[0] = 'B';
data[1] = 'M';
data[2] = 'S';
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x371, &data[0]);
}
if(CAN_SendCount ==7) //ID = 0x373 - 最大/最小单体电压/温度(与固德威配置相同)
{
cellVolMax = canMem[0].VolMax;
cellVolMin = canMem[0].VolMin;
T_Max = canMem[0].TempMax/10; // 最高温度
T_Min = canMem[0].TempMin/10; // 最低温度
data[0] = cellVolMin & 0xFF; //最小单体电压
data[1] = (cellVolMin >> 8) & 0xFF;
data[2] = cellVolMax & 0xFF; //最大单体电压
data[3] = (cellVolMax >> 8) & 0xFF;
data[4] = (T_Min ) & 0xFF; //最小单体温度
data[5] = ((T_Min ) >> 8) & 0xFF;
data[6] = (T_Max ) & 0xFF; //最大单体温度
data[7] = ((T_Max ) >> 8) & 0xFF;
CAN1_SendData(0x373, &data[0]);
}
if(CAN_SendCount ==8) //ID = 0x374 - 最小电池电压地址
{
if((canMem[0].VolMinIndex + 1) >= 10)
{
cellVolMinIndex_Byte1 = 1;
cellVolMinIndex_Byte2 = (canMem[0].VolMinIndex+1)-10;
}
else
{
cellVolMinIndex_Byte1 = 0;
cellVolMinIndex_Byte2 = (canMem[0].VolMinIndex+1);
}
data[0] = 0x30 + cellVolMinIndex_Byte1;
data[1] = 0X30 + cellVolMinIndex_Byte2;
data[2] = 0X00;
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x374, &data[0]);
}
if(CAN_SendCount ==9) //ID = 0x375 - 最大电池电压地址
{
if((canMem[0].VolMaxIndex+1)>= 10)
{
cellVolMaxIndex_Byte1 = 1;
cellVolMaxIndex_Byte2 = (canMem[0].VolMaxIndex+1)-10;
}
else
{
cellVolMaxIndex_Byte1 = 0;
cellVolMaxIndex_Byte2 = (canMem[0].VolMaxIndex+1);
}
data[0] = 0x30 + cellVolMaxIndex_Byte1;
data[1] = 0x30 + cellVolMaxIndex_Byte2;
data[2] = 0X00;
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x375, &data[0]);
}
if(CAN_SendCount ==10) //ID = 0x376 - 最小电池温度地址
{
T_MinIndex = canMem[0].TempMinIndex;// 最低温度序号,范围0-6
data[0] = 0x30 + (T_MinIndex+1);
data[1] = 0X00;
data[2] = 0X00;
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x376, &data[0]);
}
if(CAN_SendCount ==11) //ID = 0x377 - 最大电池温度地址
{
T_MaxIndex = canMem[0].TempMaxIndex;// 最高温度序号,范围0-6
data[0] = 0x30 + (T_MaxIndex+1);
data[1] = 0X00;
data[2] = 0X00;
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x377, &data[0]);
}
if(CAN_SendCount ==12) //ID = 0x379 --- 容量
{
totalCapacity = ncc_Ah * OnlineNum; //单位1Ah
data[0] = totalCapacity & 0xFF; //电池容量
data[1] = (totalCapacity >> 8) & 0xFF;
data[2] = 0X00;
data[3] = 0X00;
data[4] = 0X00;
data[5] = 0X00;
data[6] = 0X00;
data[7] = 0X00;
CAN1_SendData(0x379, &data[0]);
}
if(CAN_SendCount>=13)
{
CAN_SendCount = 0;
}
}
//Sorotec 索瑞德
void CAN_Protocol_Sorotec(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 |= 0x01;
//保护
//放电高温保护
//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 currentSC, 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; //Sorotec禁充
}
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; //Sorotec禁放
}
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
{
data[0] = canMem[0].soc & 0xFF; //SOC
data[1] = 0;
data[2] = 0X00;
data[3] = 0X00;
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版本号/总容量
{
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;
}
}
//Modbus:
//Growatt 古瑞瓦特
void MOD_Protocol_Growatt(void)
{
uint8_t i;
uint16_t protectByte = 0;
uint16_t alarmByte = 0;
uint16_t statusByte = 0;
//保护
// //过压保护
// //cell_ov+pack_ov+pf
// if((canMem[0].status_byte1 & 0x0141) != 0)
// {
// if(canMem[0].soc < 99)
// {
// protectByte |= 0x0004;
// }
// else
// {
// protectByte &= 0xFFFB;
// }
// }
// else
// {
// protectByte &= 0xFFFB;
// }
//欠压保护
//cell_uv+pack_uv+l0v
if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0))
{
protectByte |= 0x0008;
}
else
{
protectByte &= 0xFFF7;
}
//放电过流保护
//discharge over currentSC, OCD1, OCD2
if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0))
{
protectByte |= 0x0001;
}
else
{
protectByte &= 0xFFFE;
}
//充电过流保护
//charge over current
if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0))
{
protectByte |= 0x0800;
}
else
{
protectByte &= 0xF7FF;
}
//sc-short circuit (测) 短路
if((canMem[0].status_byte1 & 0x20) != 0)
{
protectByte |= 0x0002;
}
else
{
protectByte &= 0xFFFD;
}
//放电高温保护
//discharge over temp
if( ((canMem[0].status_byte2 & 0x0008) !=0) || ((canMem[0].status_byte4 & 0x0202) !=0) )
{
protectByte |= 0x0010;
}
else
{
protectByte &= 0xFFEF;
}
//充电高温保护
//charge over temp 高温
if( ((canMem[0].status_byte2 & 0x0002) !=0) || ((canMem[0].status_byte4 & 0x0101) !=0) )
{
protectByte |= 0x0020;
}
else
{
protectByte &= 0xFFDF;
}
//放电低温保护
//discharge under temp
if( ((canMem[0].status_byte2 & 0x0004) !=0) || ((canMem[0].status_byte4 & 0x0808) !=0) )
{
protectByte |= 0x0040;
}
else
{
protectByte &= 0xFFBF;
}
//充电低温保护
//charge under temp 低温
if( ((canMem[0].status_byte2 & 0x0001) !=0) || ((canMem[0].status_byte4 & 0x0404) !=0) )
{
protectByte |= 0x0080;
}
else
{
protectByte &= 0xFF7F;
}
//环境低温保护 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;
}
//放电过流告警
//discharge over currentSC, OCD1, OCD2
if((canMem[0].status_byte3 & 0x0200) != 0)
{
alarmByte |= 0x0010;
}
else
{
alarmByte &= 0xFFEF;
}
//充电过流告警
//charge over current
if((canMem[0].status_byte3 & 0x1000) != 0)
{
alarmByte |= 0x0020;
}
else
{
alarmByte &= 0xFFDF;
}
//放电高温告警
//discharge over temp
if( ((canMem[0].status_byte2 & 0x2200) !=0) || ((canMem[0].status_byte4 & 0x2000) !=0) )
{
alarmByte |= 0x0040;
}
else
{
alarmByte &= 0xFFBF;
}
//充电高温告警
//charge over temp 高温
if( ((canMem[0].status_byte2 & 0x1100) !=0) || ((canMem[0].status_byte4 & 0x1000) !=0) )
{
alarmByte |= 0x0100;
}
else
{
alarmByte &= 0xFEFF;
}
//放电低温告警
//discharge under temp
if( ((canMem[0].status_byte2 & 0x8800) !=0) || ((canMem[0].status_byte4 & 0x8000) !=0) )
{
alarmByte |= 0x0080;
}
else
{
alarmByte &= 0xFF7F;
}
//充电低温告警
//charge under temp 低温
if( ((canMem[0].status_byte2 & 0x4400) !=0) || ((canMem[0].status_byte4 & 0x4000) !=0) )
{
alarmByte |= 0x0200;
}
else
{
alarmByte &= 0xFDFF;
}
//环境低温告警 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;
}
//状态位赋值:
if(bmsMem.E2_485Snum != 1) //0100并机/0000单机模式
{
statusByte |= 0x0100;
}
else
{
statusByte &= 0xFEFF;
}
if(bCHGING == 1) //充电
{
statusByte |= 0x0002;
}
else
{
statusByte &= 0xFFFD;
}
if(bDSGING == 1) //放电
{
statusByte |= 0x0003;
}
else
{
statusByte &= 0xFFFC;
}
// if((bmsMem.balanceStatus & 0x01) !=0) //均衡状态
// {
// statusByte |= 0x0008;
// }
// else
// {
// statusByte &= 0xFFF7;
// }
if( ((canMem[0].status_byte3 & 0x02) !=0) ) //充电MOS状态 0x0013 Bit6
{
statusByte |= 0x0040;
}
else
{
statusByte &= 0xFFBF;
}
if( ((canMem[0].status_byte3 & 0x01) !=0) ) //放电MOS状态 0x0013 Bit5
{
statusByte |= 0x0020;
}
else
{
statusByte &= 0xFFDF;
}
if(chg_forceFlg == 1)//Growatt
{
statusByte |= 0x1000; //bit12 强充标志
}
else
{
statusByte &= 0xEFFF;
}
GrowattMem.status_byte = statusByte; //状态
GrowattMem.protect_byte = protectByte; //保护
GrowattMem.alarm_byte = alarmByte; //报警
GrowattMem.soc = (uint8_t)canMem[0].soc; //SOC % 2byte
GrowattMem.soh = (uint8_t)canMem[0].soh; //SOH % 2byte
GrowattMem.packVoltage = (uint16_t)(bmsMem.packVoltage/10); //模块电压 10mV 2byte
GrowattMem.packCurrent = (int16_t)(canMem[0].cur); //充电电流 10mA 2byte
GrowattMem.T_Average = (int16_t)((canMem[0].temp - 2731)/10); //电芯温度 ℃
GrowattMem.rcc = 100 * ncc_Ah * OnlineNum * GrowattMem.soc/100; //剩余容量 10mAH 2byte
GrowattMem.fcc = 100 * ncc_Ah * OnlineNum; //满容量 10mAH 2byte
GrowattMem.CV_Vol = bmsMem.inverter_chgVolLimit * 10; //CV电压&充电限压,上位机配置,默认值57.6V,10mV
if(chg_forbidFlg == 1)
{
GrowattMem.chgCurLimit = 0; //Growatt_485禁充
}
else if(chg_curlimitFlg == 1)
{
GrowattMem.chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数
}
else
{
GrowattMem.chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A
}
if(dsg_forbidFlg == 1)
{
GrowattMem.dsgCurLimit = 0; //Growatt_485禁放
}
else
{
GrowattMem.dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A,10mA
}
GrowattMem.Delta = canMem[0].VolMax - canMem[0].VolMin;//压差 V
GrowattMem.cellVolMax = canMem[0].VolMax ; //单芯最高电压
GrowattMem.cellVolMin = canMem[0].VolMin ; //单芯最低电压
GrowattMem.cellVolMaxIndex = canMem[0].VolMaxIndex + 1; //最大电压序号
GrowattMem.cellVolMinIndex = canMem[0].VolMinIndex + 1; //最小电压序号
GrowattMem.cellNum = bmsMem.ucCellNum * OnlineNum;
for(i=0;i<16;i++)
{
GrowattMem.cellVol[i] = bmsMem.vCell[i]; //电池电压 mV
}
}
//Sorotec 索瑞德
void MOD_Protocol_Sorotec(void)
{
MOD_Protocol_Growatt();
}
//YDN:
//Pylon 派能(电总协议)
void YDN_Protocol_Pylon(void)
{
YDN();
}