ZDBMS/code_drv/Calculate.c

500 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************
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]<resis<NTC103AT[i]
{
break;
}
}
}
else
{
for(i=ucTempeMiddle+1; i<NTC103AT_ARRAY_LEN-1; i++)
{
if(Tempcalcu > NTC103AT[i]) //NTC103AT[i-1]<resis<NTC103AT[i]
{
break;
}
}
i--;
}
ucTempeMiddle = i;
#if NTC_SL //SL热敏电阻
Temperature = (U16)(ucTempeMiddle-20)*10+(NTC103AT[i]-Tempcalcu)*10/(NTC103AT[i]-NTC103AT[i+1])+2731;
#else
Temperature = (U16)(ucTempeMiddle-50)*10+(NTC103AT[i]-Tempcalcu)*10/(NTC103AT[i]-NTC103AT[i+1])+2731;
#endif
}
return Temperature;
}
/*************************************************************************************************
* 函数名: AfeGetVol、AfeGetTempe
* 参 数: 无
* 返回值: 无
* 描 述: 从AFE读取电压、温度采集数据
*************************************************************************************************/
BOOL AfeGetVol(void)
{
U8 i;
BOOL Result=1;
for(i=ucCellNumOffset; i<(ucCellNum+ucCellNumOffset); i++)
{
if(!AFEReadReg(AFE_CELL1H+2*i, 2, (U8 xdata *)(&AFE.uiCell[i]))) //通过TWI读取VADC采集的电压值()
{
Result = 0;
return Result;
}
}
return Result;
}
BOOL AfeGetTempe(void)
{
BOOL Result=1;
if(!AFEReadReg(AFE_TS1H, 2, (U8 xdata *)&AFE.uiTS[0]))
{
Result = 0;
}
if(!AFEReadReg(AFE_TS2H, 2, (U8 xdata *)&AFE.uiTS[1]))
{
Result = 0;
}
if(!AFEReadReg(AFE_TEMP1H, 2, (U8 xdata *)&AFE.uiICTempe[0]))
{
Result = 0;
}
if(ucCellNum > 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();
}
}