/** ****************************************************************************** * @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 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 { 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 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; } // //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 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 |= 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 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; } //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 current,SC, 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 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(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 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 告警 { 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 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 - 保护与警告(与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 current,SC, 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 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; //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 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; //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 current,SC, 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 current,SC, 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(); }