500 lines
13 KiB
C
500 lines
13 KiB
C
/********************************************************************************
|
||
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();
|
||
}
|
||
}
|
||
|
||
|