/******************************************************************************** Copyright (C), Sinowealth Electronic. Ltd. Author: Sino Version: V0.0 Date: 2020/04/26 History: V2.0 2020/04/26 Preliminary ********************************************************************************/ #include "Main.h" U8 xdata ucChgingCheckCnt; U8 xdata ucDsgingCheckCnt; /************************************************************************************************* * 函数名: CalcuTemp * 参 数: 无 * 返回值: 无 * 描 述: 根据计算的阻值来查表,获取对应温度。温度变量保存的为开尔文温度*10 例如摄氏度25°,温度变量保存的值为2731+250 *************************************************************************************************/ U16 CalcuTemp(U16 getdata) { U8 i; U16 Temperature; U32 Tempcalcu; #if (AFE_ID == 0x34) Tempcalcu = (U32)getdata*REF_RES_VAL/(32768-getdata); #else Tempcalcu= (U32)getdata*REF_RES_VAL/(4096-getdata); //calculte the resistance value of 103AT if(Tempcalcu > 10) { Tempcalcu -= 10; } #endif if(Tempcalcu >= NTC103AT[0]) //look up table to find the resieter correspond temp { Temperature = 2731+(TEMP_LOWER_LIMIT *10); } else if(Tempcalcu <= NTC103AT[NTC103AT_ARRAY_LEN-1]) { Temperature = 2731+(TEMP_UPPER_LIMIT *10); } else { i = ucTempeMiddle; //the ucTempeMiddle must be initialized in InitVar() if(Tempcalcu > NTC103AT[i]) { for(i=ucTempeMiddle-1; i>=0; i--) { if(Tempcalcu <= NTC103AT[i]) //NTC103AT[i+1] NTC103AT[i]) //NTC103AT[i-1] 5) //6~10串应用时 { if(!AFEReadReg(AFE_TEMP2H, 2, (U8 xdata *)&AFE.uiICTempe[1])) { Result = 0; } } return Result; } /************************************************************************************************* * 函数名: AfeCalcuTempe * 参 数: 无 * 返回值: 无 * 描 述: 计算温度,更新uiTempeMax、uiTempeMin *************************************************************************************************/ void AfeCalcuTempe(void) { U16 TempeData; if(AfeGetTempe()) { TempeData = CalcuTemp(AFE.uiTS[0]) + E2siTS0Offset; //计算外部温度1 #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.uiTS[0] = TempeData; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif TempeData = (U32)AFE.uiICTempe[0]*17/10+31; //计算内部温度1 #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.uiICTempe[0] = TempeData; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif if(ucCellNum > 5) //6~10串应用时 { TempeData = (U32)AFE.uiICTempe[1]*17/10+31; //计算内部温度2 #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.uiICTempe[1] = TempeData; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif } uiTempeMin = Info.uiTS[0]; uiTempeMax = Info.uiTS[0]; if(bTempNum) { TempeData = CalcuTemp(AFE.uiTS[1]) + E2siTS1Offset; //计算外部温度2 #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.uiTS[1] = TempeData; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif if(TempeData < uiTempeMin) { uiTempeMin = TempeData; } else { uiTempeMax = TempeData; } } } } /************************************************************************************************* * 函数名: AfeCalcuVol * 参 数: 无 * 返回值: 无 * 描 述: 计算电压,同步更新最大值最小值uiVadcVmax、uiVadcVmin,用于断线判断 当没有平衡时,才更新uiCellVmax、uiCellVmin,用于保护判断 *************************************************************************************************/ void AfeCalcuVol(void) { U8 i; U32 TempPackVol=0, TempCellVol=0; uiVadcVmax = 0; uiVadcVmin = 6000; if(AfeGetVol()) { for(i=ucCellNumOffset; i<(ucCellNum+ucCellNumOffset); i++) { TempCellVol = (U32)AFE.uiCell[i]*CALIVOL/E2uiVPackGain; if(TempCellVol > uiVadcVmax) //计算最大值&最小值 { uiVadcVmax = TempCellVol; } if(TempCellVol < uiVadcVmin) { uiVadcVmin = TempCellVol; } if(!bBalancingFlg) //if bCellOpenDecFlag this data will throw away { #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.uiVCell[i] = TempCellVol; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif TempPackVol += TempCellVol; } } if(!bBalancingFlg) { uiCellVmax = uiVadcVmax; uiCellVmin = uiVadcVmin; #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.ulVoltage = TempPackVol; //Calculate the total voltage #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif } } } /************************************************************************************************* * 函数名: CurTempOffset * 参 数: 无 * 返回值: 无 * 描 述: 不同芯片温度下ADC的补偿值 *************************************************************************************************/ S16 code siCurTempOffset[2][13]= { /**0****1****2****3***4***5***6***7***8***9**10**11**12**/ {-40, -30, -20, -10, 0, 10, 25, 35, 45, 55, 65, 75, 85}, { -5, -4, -3, -2, -1, -1, 0, 1, 1, 2, 3, 4, 5}, }; /************************************************************************************************* * 函数名: OffsetCalculate() * 参 数: 无 * 返回值: 无 * 描 述: 根据芯片内部温度实时调整0电流补偿值,以便消除温度对ADC采集产生的影响 *************************************************************************************************/ S16 OffsetCalculate(void) { S16 xdata siCadcTempOffset=0; //20220620 U8 xdata i; for(i=0; i<12; i++) { if(Info.uiICTempe[0] <= (((S32)siCurTempOffset[0][i] + siCurTempOffset[0][i+1]) / 2 * 10 + 2731)) { siCadcTempOffset = siCurTempOffset[1][i]; break; } } return siCadcTempOffset; } /************************************************************************************************* * 函数名: AfeCalcuCurr * 参 数: 无 * 返回值: 无 * 描 述: 计算CADC采集的电流数据 *************************************************************************************************/ void AfeCalcuCurr(void) { U8 i; S32 Tempdata=0; AFEReadReg(AFE_CURH, 2, (U8 xdata *)&AFE.siCurr); //通过TWI读取CADC采集的电流值 if((AFE.siCurr&0x1000) != 0) //根据bit12判断是否为负数(放电电流为负值),如为负值高位补0 { AFE.siCurr|=0xE000; } slCadcCurrent = (S32)CALICUR*(AFE.siCurr-E2siCadcOffset+OffsetCalculate())/E2siCadcGain; slCadcCurBuf[ucCadcCnt] = slCadcCurrent; //对连续采集的16次电流取平均值,作为当前电流值 if(++ucCadcCnt >= 16) { ucCadcCnt = 0; } for(i=0; i<16; i++) { Tempdata += slCadcCurBuf[i]; } slCadcCurAverage = Tempdata/16; bDSGING = 0; //根据电流判定充放电状态 bCHGING = 0; if(slCadcCurAverage < (-E2siDfilterCur)) { if(++ucDsgingCheckCnt >= TIME_50MS_500MS) //充放电状态检测延时10*50mS { ucDsgingCheckCnt = TIME_50MS_500MS; bDSGING = 1; #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.slCurr = slCadcCurAverage; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif } } else if(slCadcCurAverage > E2siDfilterCur) { if(++ucChgingCheckCnt >= TIME_50MS_500MS) //充放电状态检测延时10*50mS { ucChgingCheckCnt = TIME_50MS_500MS; bCHGING = 1; McuPWM2Set(4000, 100); #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.slCurr = slCadcCurAverage; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif } } else { #if (UART0_DEFINE != 0) IrqUart0Dis(); #endif #if (UART1_DEFINE != 0) IrqUart1Dis(); #endif #if (UART2_DEFINE != 0) IrqUart2Dis(); #endif Info.slCurr = 0; #if (UART0_DEFINE != 0) IrqUart0En(); //开启uart0中断 #endif #if (UART1_DEFINE != 0) IrqUart1En(); //开启uart1中断 #endif #if (UART2_DEFINE != 0) IrqUart2En(); //初始化UART2中断使能,根据具体使用UART模块来进行选择 #endif } } /************************************************************************************************* * 函数名: AFEInfoProcess * 参 数: 无 * 返回值: 无 * 描 述: 每50mS读取AFE信息,并更新电压、电流、温度数据 *************************************************************************************************/ void AFEInfoProcess(void) { AFERdFlg(); bVADCFlg = 0; AfeCalcuVol(); AfeCalcuTempe(); if(bCADCFlg) //当CADC转换完成后,才读取AFE电流信息并计算 { bCADCFlg = 0; AfeCalcuCurr(); } }