//******************************************************************** // Ver 1.0 // 2021.08.12 1、新建文件。 // 2021.08.15 2、增加读取上一次保护状态标志命令。 // 2021.09.17 3、增加读取预放电压数据历史命令。 // 4、修正放电功率计算数值为正数返回。 // 2021.09.30 5、增加读取校准数据命令。addr:a3,读取15个字节, // 在IAP升级之前读取数据,升级完成后,再通过写入 // 校准数据命令将数据回写到MCU里,保留原校准数据。 //******************************************************************** #include "config.h" SBS_Str SBS_Info; /* code INT8U SBS_Tab[]={ 0x00, 0x02, (INT16U)&SBS_Info.Volt, 0x02, 0x02, (INT16U)&SBS_Info.Current, 0x04, 0x02, (INT16U)&SBS_Info.Ts1, 0x06, 0x02, (INT16U)&SBS_Info.Ts2, 0x08, 0x02, (INT16U)&SBS_Info.Ts3, 0x31, 0x02, (INT16U)&SBS_Info.Ts1, }; */ void SBS_Find(INT8U Addr, INT8U *ptr) { ptr[0] = (I2C_SlaveAddr << 1); ptr[1] = Addr; ptr[2] = (I2C_SlaveAddr << 1) | 0x01; switch(Addr) { case 0x00: ptr[3] = (INT8U)((BATT_Voltage / 10) >> 8); //case 0x01: ptr[4] = (INT8U)((BATT_Voltage / 10)); break; case 0x02: ptr[3] = (INT8U)((BATT_Current / 10) >> 8); //case 0x03: ptr[4] = (INT8U)((BATT_Current / 10)); break; case 0x04: ptr[3] = (INT8U)((CELL_T1 + 40) >> 8); //case 0x05: ptr[4] = (INT8U)((CELL_T1 + 40)); break; case 0x06: ptr[3] = (INT8U)((CELL_T2 + 40) >> 8); //case 0x07: ptr[4] = (INT8U)((CELL_T2 + 40)); break; case 0x08: ptr[3] = (INT8U)((CELL_T3 + 40) >> 8); //case 0x09: ptr[4] = (INT8U)((CELL_T3 + 40)); break; case 0x31: ptr[3] = (INT8U)((BATT_Rsoc) >> 8); //case 0x32: ptr[4] = (INT8U)((BATT_Rsoc)); break; case 0x33: ptr[3] = (INT8U)((BATT_RC / 10) >> 8); //case 0x34: ptr[4] = (INT8U)((BATT_RC / 10)); break; case 0x35: ptr[3] = (INT8U)((BATT_FCC / 10) >> 8); //case 0x36: ptr[4] = (INT8U)((BATT_FCC / 10)); break; case 0x37: ptr[3] = (INT8U)((BATT_Cycle) >> 8); //case 0x38: ptr[4] = (INT8U)((BATT_Cycle)); break; case 0x39: ptr[3] = (INT8U)((BATT_FDC / 10) >> 8); //case 0x3a: ptr[4] = (INT8U)((BATT_FDC / 10)); break; case 0x51: ptr[3] = (INT8U)((CELL_V1) >> 8); //case 0x52: ptr[4] = (INT8U)((CELL_V1)); //case 0x53: ptr[5] = (INT8U)((CELL_V2) >> 8); //case 0x54: ptr[6] = (INT8U)((CELL_V2)); //case 0x55: ptr[7] = (INT8U)((CELL_V3) >> 8); //case 0x56: ptr[8] = (INT8U)((CELL_V3)); //case 0x57: ptr[9] = (INT8U)((CELL_V4) >> 8); //case 0x58: ptr[10] = (INT8U)((CELL_V4)); //case 0x59: ptr[11] = (INT8U)((CELL_V5) >> 8); //case 0x5a: ptr[12] = (INT8U)((CELL_V5)); //case 0x5b: ptr[13] = (INT8U)((CELL_V6) >> 8); //case 0x5c: ptr[14] = (INT8U)((CELL_V6)); //case 0x5d: ptr[15] = (INT8U)((CELL_V7) >> 8); //case 0x5e: ptr[16] = (INT8U)((CELL_V7)); //case 0x5f: ptr[17] = (INT8U)((CELL_V8) >> 8); //case 0x60: ptr[18] = (INT8U)((CELL_V8)); break; case 0x53: ptr[3] = (INT8U)((CELL_V2) >> 8); //case 0x54: ptr[4] = (INT8U)((CELL_V2)); break; case 0x55: ptr[3] = (INT8U)((CELL_V3) >> 8); //case 0x56: ptr[4] = (INT8U)((CELL_V3)); break; case 0x57: ptr[3] = (INT8U)((CELL_V4) >> 8); //case 0x58: ptr[4] = (INT8U)((CELL_V4)); break; case 0x59: ptr[3] = (INT8U)((CELL_V5) >> 8); //case 0x5a: ptr[4] = (INT8U)((CELL_V5)); break; case 0x5b: ptr[3] = (INT8U)((CELL_V6) >> 8); //case 0x5c: ptr[4] = (INT8U)((CELL_V6)); break; case 0x5d: ptr[3] = (INT8U)((CELL_V7) >> 8); //case 0x5e: ptr[4] = (INT8U)((CELL_V7)); break; case 0x5f: ptr[3] = (INT8U)((CELL_V8) >> 8); //case 0x60: ptr[4] = (INT8U)((CELL_V8)); //ptr[3] = (INT8U)((BATT_CrgVolt) >> 8); //ptr[4] = (INT8U)((BATT_CrgVolt)); break; case 0x81: ptr[3] = (INT8U)((BATT_CellBal) >> 8); //case 0x82: ptr[4] = (INT8U)((BATT_CellBal)); break; case 0x83: ptr[3] = SBS_Info.Status.Bytes[1]; //case 0x84: if(BATT_FLAG_CHG != 0) { SBS_Info.Status.Bits.Chg = 1; SBS_Info.Status.Bits.Dsg = 0; SBS_Info.Status.Bits.Idle = 0; } else if(BATT_FLAG_DSG != 0) { SBS_Info.Status.Bits.Chg = 0; SBS_Info.Status.Bits.Dsg = 1; SBS_Info.Status.Bits.Idle = 0; } else { SBS_Info.Status.Bits.Chg = 0; SBS_Info.Status.Bits.Dsg = 0; SBS_Info.Status.Bits.Idle = 1; } SBS_Info.Status.Bits.Dfet = SYS_CTRL2_DSG_ON; SBS_Info.Status.Bits.Cfet = SYS_CTRL2_CHG_ON; //SBS_Info.Status.Bits.SocL = (BATT_Rsoc < 1) ? 1 : 0; SBS_Info.Status.Bits.SocL = BATT_FLAG_UVP; SBS_Info.Status.Bits.ChgFull = SOC_FLAG_FULL; SBS_Info.Status.Bits.CellBal = BATT_FLAG_BAL; SBS_Info.Status.Bits.KEY1 = BATT_FLAG_POWERON; SBS_Info.Status.Bits.KEY2 = (BATT_FLAG_POWERON >> 1); SBS_Info.Status.Bits.PCFET = BATT_FLAG_PCFET; SBS_Info.Status.Bits.CRG = KEY_ReadFlag(K2, Press); SBS_Info.Status.Bits.CRGLOCK = BATT_FLAG_CRGLOCK; SBS_Info.Status.Bits.CFETLOCK = FET_FLAG_LOCK; SBS_Info.Status.Bits.DFETLOCK = (FET_FLAG_LOCK >> 1); //SBS_Info.Status.Bits.FETLOCK = BATT_FLAG_FETUNLOCK; SBS_Info.Status.Bits.TEST = BATT_FLAG_RUNMODE; ptr[4] = SBS_Info.Status.Bytes[0]; break; case 0x85: ptr[3] = SBS_Info.Alarm.Bytes[1]; if(SBS_Info.Alarm.Bytes[1] != 0) { SBS_Info.AlarmLog.Bytes[1] = SBS_Info.Alarm.Bytes[1]; } SBS_Info.Alarm.Bytes[1] = 0; //case 0x86: /* SBS_Info.AlarmLog.Bits.CUV = (BATT_FLAG_UV > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.COV = (BATT_FLAG_OV > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.PUV = (BATT_FLAG_PUV > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.POV = (BATT_FLAG_POV > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.OTC = (BATT_FLAG_OTC > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.UTC = (BATT_FLAG_UTC > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.OTD = (BATT_FLAG_OTD > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.UTD = (BATT_FLAG_UTD > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.OCC = (BATT_FLAG_OCC > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.OCD = (BATT_FLAG_OCD > 1) ? 1: 0; SBS_Info.AlarmLog.Bits.SCD = (BATT_FLAG_ASCD > 0) ? 1: 0; SBS_Info.AlarmLog.Bits.OTF = (BATT_FLAG_OTF > 1) ? 1: 0; */ ptr[4] = SBS_Info.Alarm.Bytes[0]; if(SBS_Info.Alarm.Bytes[0] != 0) { SBS_Info.AlarmLog.Bytes[0] = SBS_Info.Alarm.Bytes[0]; } SBS_Info.Alarm.Bytes[0] = 0; //读取后清除 break; case 0x4f: //电芯压差 ptr[3] = (INT8U)((CELL_V_Bl) >> 8); //case 0x50: ptr[4] = (INT8U)((CELL_V_Bl) >> 0); //ptr[3] = (INT8U)((BATT_CrgVolt) >> 8); //case 0x50: //ptr[4] = (INT8U)((BATT_CrgVolt) >> 0); break; case 0x87: //充电MOS状态 ptr[3] = SYS_CTRL2_CHG_ON; //case 0x88: //放电MOS状态 ptr[4] = SYS_CTRL2_DSG_ON; break; case 0x89: //软件版本 ptr[3] = 0; //case 0x90: ptr[4] = _SW_VER; break; case 0x8b: //功率 ptr[3] = (INT8U)((BATT_Voltage * Abs(BATT_Current) / 1000000) >> 8); //case 0x8c: ptr[4] = (INT8U)((BATT_Voltage * Abs(BATT_Current) / 1000000) >> 0); break; case 0x8d: //电压系数 ptr[3] = (INT8U)((FLASH_Info.CrgvGain) >> 8); //case 0x8e: ptr[4] = (INT8U)((FLASH_Info.CrgvGain) >> 0); break; case 0x8f: //电流系数 ptr[3] = (INT8U)((FLASH_Info.CcGain) >> 8); //case 0x90: ptr[4] = (INT8U)((FLASH_Info.CcGain) >> 0); break; case 0x91: //平均电流 ptr[3] = (INT8U)((BATT_Current / 10) >> 8); //case 0x92: ptr[4] = (INT8U)((BATT_Current / 10) >> 0); break; case 0x93: //初始电流 ptr[3] = (INT8U)((CC) >> 8); //case 0x94: ptr[4] = (INT8U)((CC) >> 0); break; case 0xa0: //读取上一次的保护标志 ptr[3] = SBS_Info.AlarmLog.Bytes[1]; //case 0xa1: ptr[4] = SBS_Info.AlarmLog.Bytes[0]; break; case 0xa2: //读取上一次的保护标志 ptr[3] = (INT8U)(BATT_Info.CRGVB[0] >> 8); ptr[4] = (INT8U)(BATT_Info.CRGVB[0]); ptr[5] = (INT8U)(BATT_Info.CRGVB[1] >> 8); ptr[6] = (INT8U)(BATT_Info.CRGVB[1]); ptr[7] = (INT8U)(BATT_Info.CRGVB[2] >> 8); ptr[8] = (INT8U)(BATT_Info.CRGVB[2]); ptr[9] = (INT8U)(BATT_Info.CRGVB[3] >> 8); ptr[10] = (INT8U)(BATT_Info.CRGVB[3]); ptr[11] = (INT8U)(BATT_Info.CRGVB[4] >> 8); ptr[12] = (INT8U)(BATT_Info.CRGVB[4]); ptr[13] = (INT8U)(BATT_Info.CRGVB[5] >> 8); ptr[14] = (INT8U)(BATT_Info.CRGVB[5]); ptr[15] = (INT8U)(BATT_Info.CRGVB[6] >> 8); ptr[16] = (INT8U)(BATT_Info.CRGVB[6]); break; case 0xa3: //读回校准数据 ptr[3] = (INT8U)((FLASH_Info.CrgvGain) >> 8); ptr[4] = (INT8U)((FLASH_Info.CrgvGain) >> 0); ptr[5] = (INT8U)((FLASH_Info.CcOffset) >> 8); ptr[6] = (INT8U)((FLASH_Info.CcOffset) >> 0); ptr[7] = (INT8U)((FLASH_Info.CcGain) >> 8); ptr[8] = (INT8U)((FLASH_Info.CcGain) >> 0); ptr[9] = (INT8U)((FLASH_Info.SOH) >> 8); ptr[10] = (INT8U)((FLASH_Info.SOH) >> 0); ptr[11] = (INT8U)((FLASH_Info.CycleCount) >> 8); ptr[12] = (INT8U)((FLASH_Info.CycleCount) >> 0); ptr[13] = (INT8U)((FLASH_Info.FullChargeCapacity) >> 24); ptr[14] = (INT8U)((FLASH_Info.FullChargeCapacity) >> 16); ptr[15] = (INT8U)((FLASH_Info.FullChargeCapacity) >> 8); ptr[16] = (INT8U)((FLASH_Info.FullChargeCapacity) >> 0); break; case 0xa4: //读取电池信息 MEM_Copy((INT8U *) & (BATT_Info.Info.Voltage), &ptr[3], 38); break; case 0xee: //收到复位信号,重启标志 ptr[3] = 0x02; //case 0xef: ptr[4] = 0x02; break; default: ptr[4] = 0xff; ptr[3] = 0xff; break; } if(Addr == 0x51) { ptr[19] = _CRC8_((ptr + 3), 16); } else if((Addr == 0xa2) || (Addr == 0xa3)) { ptr[17] = _CRC8_((ptr + 3), 14); } /* else if(Addr == 0xa3) { ptr[11] = _CRC8_((ptr+3), 8); } */ else if(Addr == 0xa4) { ptr[41] = _CRC8_((ptr + 3), 38); } else { ptr[5] = _CRC8_((ptr + 3), 2); } }