/* * AppTaskUart0.c * * Created on: 2022年2月22日 * Author: QiXiang_CHENJIE */ #include "AppTaskUart0.h" #ifdef APP_UART0_ENABLE static process_Uart0 gProcess_Uart0_Task = PROCESS_UART_STATE_IDLE; #define PROC_UART0_STATE_SWITCH(a) (gProcess_Uart0_Task = a) bool bmsCellInfoDecode(uint8 *dataPtr); bool bmsOtherInfoDecode(uint8 *dataPtr); void battDataCalFunc(void); void Uart0Task(void *pvParameters) { (void)pvParameters; UartQueryType Uart0AskMsg; uint16 Reg_Num = 0; uint16 RegAddrBegin = 0; uint16 CRC_chk_buffer = 0; uint16 pReadLen = 0; UartAnsType UartAnsData; static uint8 writecounter = 0; uint16 UartNoDataReadCounter = 0; while (1) { switch (gProcess_Uart0_Task) { case PROCESS_UART_STATE_IDLE: { vTaskDelay(pdMS_TO_TICKS(10)); if ((TimerCounter % 1000) == 0 && 1) { PROC_UART0_STATE_SWITCH(PROCESS_UART_STATE_READ); } else if (TimerCounter % 100 == 0) { PROC_UART0_STATE_SWITCH(PROCESS_UART_STATE_WRITE); } break; } case PROCESS_UART_STATE_READ: { static uint16 readCnt = 0; /*电压电流数据读取(第一次读取)*/ uint8 *UartDataRecv = NULL; pReadLen = 0; Dio_FlipChannel(DioConf_DioChannel_PTE1_GPIO_OUT_MCU_LED2); RegAddrBegin = 0x00; Reg_Num =AppDataInfo.BattCellCount + 3; Uart0AskMsg.Bms_Address = BMS_ADDRESS_CODE; Uart0AskMsg.Bms_Funcode = UART_READ_CODE; Uart0AskMsg.Reg_Begin_H = RegAddrBegin>>8; Uart0AskMsg.Reg_Begin_L = RegAddrBegin; Uart0AskMsg.Reg_Num_H = Reg_Num >> 8; Uart0AskMsg.Reg_Num_L = Reg_Num; CRC_chk_buffer = crc_chk((uint8 *)&Uart0AskMsg, 6); Uart0AskMsg.CRC_L = CRC_chk_buffer; Uart0AskMsg.CRC_H = CRC_chk_buffer >> 8; /*RS485查询命令需要使能*/ UART_Send_Data(UART_LPUART0, (uint8 *)&Uart0AskMsg, sizeof(Uart0AskMsg), 1000); uint16 ReadLen1 = 0; uint16 ReadLenTar = 0; uint8 ReadDelayCounter = 0; ReadLenTar = (Reg_Num)*2+5; memset((uint8 *)&UartAnsData,0x00,sizeof(UartAnsData)); while(1) { UART_Receive_Data(UART_LPUART0, &UartDataRecv, &pReadLen, 100); if(pReadLen>2) { memcpy((uint8 *)&UartAnsData+ReadLen1,UartDataRecv,pReadLen); ReadLen1 = ReadLen1 + pReadLen; } else { ReadDelayCounter++; } if(ReadLen1>=ReadLenTar) { ReadDelayCounter = 0; pReadLen = ReadLen1; ReadLen1 = 0; break; } if(ReadDelayCounter>=20) { ReadDelayCounter = 0; pReadLen = 0; ReadLen1 = 0; break; } if(UartDataRecv!=NULL) { free(UartDataRecv); } UartDataRecv=NULL; } if (pReadLen > 0) { uint16 CrcChkGet = 0xffff; uint16 CrcChkCal = 0x0000; CrcChkCal = crc_chk((uint8 *)&UartAnsData, pReadLen-2); CrcChkGet = ((uint16)(UartAnsData.Data[pReadLen-1-3])<<8) | ((uint16)(UartAnsData.Data[pReadLen-2-3])); if(CrcChkCal==CrcChkGet) { bmsCellInfoDecode(UartAnsData.Data); UartNoDataReadCounter = 0; } else { UartNoDataReadCounter++; } } else { UartNoDataReadCounter++; } /*温度及其他状态信息读取(第二次读取)*/ pReadLen = 0; RegAddrBegin = 0x03 + AppDataInfo.BattCellCount; Reg_Num = 0x1B + AppDataInfo.BattTempCount; //读取的寄存器数据,暂定,分开读取 Uart0AskMsg.Bms_Address = BMS_ADDRESS_CODE; Uart0AskMsg.Bms_Funcode = UART_READ_CODE; Uart0AskMsg.Reg_Begin_H = RegAddrBegin>>8; Uart0AskMsg.Reg_Begin_L = RegAddrBegin; Uart0AskMsg.Reg_Num_H = Reg_Num >> 8; Uart0AskMsg.Reg_Num_L = Reg_Num; CRC_chk_buffer = crc_chk((uint8 *)&Uart0AskMsg, 6); Uart0AskMsg.CRC_L = CRC_chk_buffer; Uart0AskMsg.CRC_H = CRC_chk_buffer >> 8; /*RS485查询命令需要使能*/ UART_Send_Data(UART_LPUART0, (uint8 *)&Uart0AskMsg, sizeof(Uart0AskMsg), 1000); memset((uint8 *)&UartAnsData,0x00,sizeof(UartAnsData)); ReadLenTar = (Reg_Num)*2+5; while(1) { UART_Receive_Data(UART_LPUART0, &UartDataRecv, &pReadLen, 100); if(pReadLen>2) { memcpy((uint8 *)&UartAnsData+ReadLen1,UartDataRecv,pReadLen); ReadLen1 = ReadLen1 + pReadLen; } else { ReadDelayCounter++; } if(ReadLen1>=ReadLenTar) { ReadDelayCounter = 0; pReadLen = ReadLen1; ReadLen1 = 0; break; } if(ReadDelayCounter>=20) { ReadDelayCounter = 0; pReadLen = 0; ReadLen1 = 0; break; } if(UartDataRecv!=NULL) { free(UartDataRecv); } UartDataRecv=NULL; } if (pReadLen > 0) { uint16 CrcChkGet = 0xffff; uint16 CrcChkCal = 0x0000; CrcChkCal = crc_chk((uint8 *)&UartAnsData, pReadLen-2); CrcChkGet = ((uint16)(UartAnsData.Data[pReadLen-1-3])<<8) | ((uint16)(UartAnsData.Data[pReadLen-2-3])); if(CrcChkCal==CrcChkGet) { bmsOtherInfoDecode(UartAnsData.Data); UartNoDataReadCounter = 0; } else { UartNoDataReadCounter++; } } else { UartNoDataReadCounter++; } //没有读到数据时的默认值 if(UartNoDataReadCounter>10) { memset((uint8 *)&UartAnsData,0x00,sizeof(UartAnsData)); bmsCellInfoDecode(UartAnsData.Data); bmsOtherInfoDecode(UartAnsData.Data); PutErrorNum(ErrorArray, sizeof(ErrorArray)/2, 1); vTaskDelay(pdMS_TO_TICKS(5000)); } if(readCnt%60==0) { /**电表数据读取*/ for(uint8 i=0;i<2;i++) { /*电表参数读取*/ static uint16 pt[2] = {0}; static uint16 ct[2] = {0}; pReadLen = 0; uint8 *UartRecvPtr=NULL; RegAddrBegin = 0x03; Reg_Num = 0x02; Uart0AskMsg.Bms_Address = METER1_ADDRESS_CODE+i;//第一次读02,第二次读03 Uart0AskMsg.Bms_Funcode = UART_READ_CODE; Uart0AskMsg.Reg_Begin_H = RegAddrBegin>>8; Uart0AskMsg.Reg_Begin_L = RegAddrBegin; Uart0AskMsg.Reg_Num_H = Reg_Num >> 8; Uart0AskMsg.Reg_Num_L = Reg_Num; CRC_chk_buffer = crc_chk((uint8 *)&Uart0AskMsg, 6); Uart0AskMsg.CRC_L = CRC_chk_buffer; Uart0AskMsg.CRC_H = CRC_chk_buffer >> 8; UART_Send_Data(UART_LPUART0, (uint8 *)&Uart0AskMsg, sizeof(Uart0AskMsg), 100); UART_Receive_Data(UART_LPUART0, &UartRecvPtr, &pReadLen, 1000); //电表数据解析 if (pReadLen > 0) { uint16 CrcChkGet = 0xffff; uint16 CrcChkCal = 0x0000; CrcChkCal = crc_chk(UartRecvPtr, pReadLen-2); CrcChkGet = ((uint16)(*(UartRecvPtr+pReadLen-1))<<8) | ((uint16)(*(UartRecvPtr+pReadLen-2))); if(CrcChkCal==CrcChkGet) { pt[i] = ((uint16)(*(UartRecvPtr+3))<<8) | ((uint16)(*(UartRecvPtr+4))); ct[i] = ((uint16)(*(UartRecvPtr+5))<<8) | ((uint16)(*(UartRecvPtr+6))); } } if(UartRecvPtr!=NULL) { free(UartRecvPtr); } UartRecvPtr=NULL; /*电表电量数据读取*/ pReadLen = 0; RegAddrBegin = 0x3F; Reg_Num = 0x04; Uart0AskMsg.Bms_Address = METER1_ADDRESS_CODE+i;//第一次读02,第二次读03 Uart0AskMsg.Bms_Funcode = UART_READ_CODE; Uart0AskMsg.Reg_Begin_H = RegAddrBegin>>8; Uart0AskMsg.Reg_Begin_L = RegAddrBegin; Uart0AskMsg.Reg_Num_H = Reg_Num >> 8; Uart0AskMsg.Reg_Num_L = Reg_Num; CRC_chk_buffer = crc_chk((uint8 *)&Uart0AskMsg, 6); Uart0AskMsg.CRC_L = CRC_chk_buffer; Uart0AskMsg.CRC_H = CRC_chk_buffer >> 8; UART_Send_Data(UART_LPUART0, (uint8 *)&Uart0AskMsg, sizeof(Uart0AskMsg), 100); UART_Receive_Data(UART_LPUART0, &UartRecvPtr, &pReadLen, 1000); //电表数据解析 if (pReadLen > 0) { uint16 CrcChkGet = 0xffff; uint16 CrcChkCal = 0x0000; CrcChkCal = crc_chk(UartRecvPtr, pReadLen-2); CrcChkGet = ((uint16)(*(UartRecvPtr+pReadLen-1))<<8) | ((uint16)(*(UartRecvPtr+pReadLen-2))); if(CrcChkCal==CrcChkGet) { //meterAllPwr[i] = pt[i]*ct[i]*(((uint32)(*(UartRecvPtr+3))<<24)|((uint32)(*(UartRecvPtr+4))<<16)|((uint32)(*(UartRecvPtr+5))<<8) | ((uint32)(*(UartRecvPtr+6)))); meterPosPwr[i] = pt[i]*ct[i]*((uint32)(*(UartRecvPtr+3))<<24)|((uint32)(*(UartRecvPtr+4))<<16)|((uint32)(*(UartRecvPtr+5))<<8) | ((uint32)(*(UartRecvPtr+6))); meterNegPwr[i] = pt[i]*ct[i]*((uint32)(*(UartRecvPtr+7))<<24)|((uint32)(*(UartRecvPtr+8))<<16)|((uint32)(*(UartRecvPtr+9))<<8) | ((uint32)(*(UartRecvPtr+10))); meterPosPwr[i] = meterPosPwr[i] * 100; meterNegPwr[i] = meterNegPwr[i] * 100; meterAllPwr[i] = meterPosPwr[i] + meterNegPwr[i]; } } if(UartRecvPtr!=NULL) { free(UartRecvPtr); } UartRecvPtr=NULL; } } readCnt++; PROC_UART0_STATE_SWITCH(PROCESS_UART_STATE_IDLE); break; } case PROCESS_UART_STATE_WRITE: { if(battSeparateEnable)//最多重新写5次 { uint16 RegAddress = 0; uint16 CRC_chk_buffer = 0; uint8 WriteData[2] = {0x00,0x00}; if(!battSeparateCtlState) { setbit(WriteData[0],7); } else { clrbit(WriteData[0],7); } RegAddress = 0x1B + AppDataInfo.BattCellCount + AppDataInfo.BattTempCount; UartWriteMsgType Uart_Write_Msg; Uart_Write_Msg.Bms_Address = BMS_ADDRESS_CODE; Uart_Write_Msg.Bms_Funcode = UART_WRITE_CODE; Uart_Write_Msg.Reg_Begin_H = RegAddress >> 8; Uart_Write_Msg.Reg_Begin_L = RegAddress; Uart_Write_Msg.Reg_Num_H = 0x00; Uart_Write_Msg.Reg_Num_L = 0x01; Uart_Write_Msg.Data_Count = 0x02; //要写入的字节数 memcpy(Uart_Write_Msg.Data, WriteData, 2); CRC_chk_buffer = crc_chk((uint8 *)&Uart_Write_Msg, sizeof(Uart_Write_Msg) - 2); Uart_Write_Msg.CRC_L = CRC_chk_buffer; Uart_Write_Msg.CRC_H = CRC_chk_buffer >> 8; uint8 *UartRecvPtr = NULL; UART_Query_Data(UART_LPUART0,UART_LPUART0,(uint8 *)&Uart_Write_Msg,sizeof(Uart_Write_Msg),&UartRecvPtr, &pReadLen,500); if (pReadLen>3&&*(UartRecvPtr+1) == 0x10) { writecounter = 0; battSeparateEnable = 0; } else { writecounter++; } if(UartRecvPtr != NULL) { free(UartRecvPtr); } UartRecvPtr = NULL; } if(writecounter>=5) { battSeparateEnable = 0; writecounter = 0; } PROC_UART0_STATE_SWITCH(PROCESS_UART_STATE_IDLE); break; } case PROCESS_UART_STATE_SLEEP: { break; } default: break; } } } bool bmsCellInfoDecode(uint8 *dataPtr) //根据串口协议确定的解码函数,电压电流解码 { uint8 i = 0; sint8 BattCurrentNegFlag = 1; uint16 Batt_current; uint8 BATT_CELL_VOL_NUM = 0, BATT_TEMP_NUM = 0; uint32 Battsumvoltage = 0; BATT_CELL_VOL_NUM = (dataPtr[(0x00) * 2] << 8) | (dataPtr[(0x00) * 2 + 1]); BATT_TEMP_NUM = ((dataPtr[(0x01) * 2] << 8) | (dataPtr[(0x01) * 2 + 1])) - BmsOtherTemp; if (BATT_CELL_VOL_NUM != AppDataInfo.BattCellCount || BATT_TEMP_NUM != AppDataInfo.BattTempCount) { BATT_CELL_VOL_NUM = AppDataInfo.BattCellCount; BATT_TEMP_NUM = AppDataInfo.BattTempCount; } Batt_current = (dataPtr[(0x02 + BATT_CELL_VOL_NUM) * 2] << 8) | (dataPtr[(0x02 + BATT_CELL_VOL_NUM) * 2 + 1]); Batt_current = Batt_current*100;//平峰协议单位是1A //原始数据:充电为负,放电为正 if (Batt_current < 0x8000) //充电过程 { if (Batt_current > 0x8000) // 数据为负 { //求补码,结果为负 Batt_current = (uint16)((uint16)(~(Batt_current)) + 1); Batt_current = Batt_current / 10; BattCurrentNegFlag = -1; } else { //源码,结果为负 Batt_current = Batt_current / 10; BattCurrentNegFlag = -1; } } else //放电过程 { if (Batt_current > 0x8000) // 数据为负 { //求补码,结果为正 Batt_current = (uint16)((uint16)(~(Batt_current)) + 1); Batt_current = Batt_current / 10; BattCurrentNegFlag = 1; } else { //源码,结果为正 Batt_current = Batt_current / 10; BattCurrentNegFlag = 1; } } battI = Batt_current * BattCurrentNegFlag + 0x2710; // sint16 BattI_Temp = 0;//做电压补偿需要的参数 // BattI_Temp = Batt_current * BattCurrentNegFlag; for (i = 0; i < BATT_CELL_VOL_NUM; i++) { //battCellU[i] = ((dataPtr[(0x02 + i) * 2] << 8) | dataPtr[(0x02 + i) * 2 + 1]) + (INT16)(cmnm_R_voloffset[i] * BattI_Temp / 10000);//不使用电压补偿 battCellU[i] = ((dataPtr[(0x02 + i) * 2] << 8) | dataPtr[(0x02 + i) * 2 + 1]); Battsumvoltage = Battsumvoltage + battCellU[i]; } avrgCellVol = Battsumvoltage / BATT_CELL_VOL_NUM; battPackVol = Battsumvoltage/100; battDataCalFunc(); return true; } bool bmsOtherInfoDecode(uint8 *dataPtr)//其他数据解析 { uint8 TEMP_NUM = 0, temp = 0; sint8 OtherInfoAddrOffset = -3;//其他数据解析的起始位置改变,需要向前减3 TEMP_NUM = AppDataInfo.BattTempCount + BmsOtherTemp; bmsHwVersion = dataPtr[(0x08 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]; bmsSwVersion = dataPtr[(0x08 + OtherInfoAddrOffset + TEMP_NUM) * 2]; temp = ((dataPtr[(0x09 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]) >> 1) & 0x03; battMOSSwitchState = ((temp & 0x01) << 1) | ((temp & 0x02) >> 1); battSOC = dataPtr[(0x0B + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]; battSOH = dataPtr[(0x0C + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]; Battdesigncap = (dataPtr[(0x0E + OtherInfoAddrOffset + TEMP_NUM) * 2]) << 24 | (dataPtr[(0x0E + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]) << 16 | (dataPtr[(0x0F + OtherInfoAddrOffset + TEMP_NUM) * 2]) << 8 | (dataPtr[(0x0F + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]); // battPackVol = ((dataPtr[(0x18 + OtherInfoAddrOffset + TEMP_NUM) * 2]) << 8 | (dataPtr[(0x18 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1])) / 10; // uint 100mV maxCellVol = (dataPtr[(0x19 + OtherInfoAddrOffset + TEMP_NUM) * 2] << 8) | dataPtr[(0x19 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]; minCellVol = (dataPtr[(0x1A + OtherInfoAddrOffset + TEMP_NUM) * 2] << 8) | dataPtr[(0x1A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1]; for (uint8 i = 0; i < AppDataInfo.BattTempCount; i++) { battCellTemp[i] = dataPtr[(0x06 + OtherInfoAddrOffset + i) * 2 + 1]; } battWorkState = (dataPtr[(0x03 + OtherInfoAddrOffset) * 2 + 1]) & 0x03; //电池状态(原始数据),0表示静置,1表示放电,2表示充电 //状态量上传 battHeatState = getbit(dataPtr[(0x09 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],5); battFanState = getbit(dataPtr[(0x09 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],3); battRelayState = getbit(dataPtr[(0x09 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],4); battConverState = getbit(dataPtr[(0x09 + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],6); battSeparateState = !getbit(dataPtr[(0x1B + OtherInfoAddrOffset + TEMP_NUM) * 2],7); if (battSeparateState==1) { battMOSSwitchState = battMOSSwitchState | (0x01 << 2); } else { battMOSSwitchState = battMOSSwitchState | (0x00 << 2); } //故障状态映关系(先完成告警状态简单上传) uint8 ErrorArrayTemp[32] ={0}; uint8 ErrorArrayNumTemp[32]={81,87,83,89,97,99,132,131,134,84,90,82,88,135,136,98,100}; ErrorArrayTemp[0] = getbit(dataPtr[(0x03 + OtherInfoAddrOffset) * 2],0);//电芯电压过高切断告警-0-81 ErrorArrayTemp[1] = getbit(dataPtr[(0x03 + OtherInfoAddrOffset) * 2],1);//总压过高切断告警-1-87 ErrorArrayTemp[2] = getbit(dataPtr[(0x04 + OtherInfoAddrOffset) * 2 + 1],0);//电芯电压过低切断告警2-83 ErrorArrayTemp[3] = getbit(dataPtr[(0x04 + OtherInfoAddrOffset) * 2 + 1],1);//总压过低切断告警3-89 ErrorArrayTemp[4] = getbit(dataPtr[(0x04 + OtherInfoAddrOffset) * 2],4);//单节温度过高切断4-97 ErrorArrayTemp[5] = getbit(dataPtr[(0x04 + OtherInfoAddrOffset) * 2],5);//单节温度过低切断5-99 ErrorArrayTemp[6] = getbit(dataPtr[(0x05 + OtherInfoAddrOffset) * 2 + 1],1);//放电电流切断6-132 ErrorArrayTemp[7] = getbit(dataPtr[(0x05 + OtherInfoAddrOffset) * 2 + 1],2);//充电电流切断7-131 ErrorArrayTemp[8] = getbit(dataPtr[(0x05 + OtherInfoAddrOffset) * 2 + 1],3);//BTU连接告警8-134 ErrorArrayTemp[9] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],0);//单节电压下限告警9-84 ErrorArrayTemp[10] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],1);//组电压下限告警10-90 ErrorArrayTemp[11] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],2);//单节电压上限告警11-82 ErrorArrayTemp[12] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],3);//组单节电压上限告警12-88 ErrorArrayTemp[13] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],4);//放电电流告警13-135 ErrorArrayTemp[14] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],5);//充电电流告警14-136 ErrorArrayTemp[15] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],6);//单节温度上限告警15-98 ErrorArrayTemp[16] = getbit(dataPtr[(0x0A + OtherInfoAddrOffset + TEMP_NUM) * 2 + 1],7);//单节温度下线告警16-100 for(uint8 i=0,j=0;(i<32&&j<5);i++) { if(ErrorArrayTemp[i]==1) { PutErrorNum(ErrorArray, sizeof(ErrorArray)/2, ErrorArrayNumTemp[i]); j++; } } return true; } void battDataCalFunc(void) { static uint32 timercounterCal = 0; uint16 timediff = 0; float battCapTempOnce = 0; static float battCapTemp = 0; static float battEnrgTemp = 0; timediff = TimerCounter - timercounterCal; timercounterCal = TimerCounter; if(timediff==0 ||timediff>10000) { return; } if(battI>10000) { battCapTempOnce = ((battI - 10000)/10.0)*(timediff/1000/3600.0); battCapTemp = battCapTempOnce + battCapTemp; battEnrgTemp = (battCapTempOnce*battPackVol)/10000.0 + battEnrgTemp; if(battEnrgTemp>1) { AppConfigInfo.AppDataInfo.battDischrgAccCap = AppConfigInfo.AppDataInfo.battDischrgAccCap + (uint32)battCapTemp; AppConfigInfo.AppDataInfo.battDischrgAccEnrg = AppConfigInfo.AppDataInfo.battDischrgAccEnrg + (uint32)battEnrgTemp; AppConfigInfo.AppDataInfo.battCycleTimes = AppConfigInfo.AppDataInfo.battDischrgAccEnrg/49; AppConfigInfo.appSaveFlg = true; battEnrgTemp = 0; battCapTemp = 0; } } } #endif