518 lines
14 KiB
C
518 lines
14 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"
|
||
|
||
//AFE相关的变量
|
||
BOOL bAfeAlarmFlg;
|
||
BOOL bCADCFlg;
|
||
BOOL bVADCFlg;
|
||
BOOL bAfeI2CRWErrFlg;
|
||
BOOL bAfeErr;
|
||
U8 data ucCellNum; //当前硬件电芯串数
|
||
U8 data ucCellNumOffset; //当前硬件电芯连接方式对应的偏移,用于程序读取AFE对应寄存器
|
||
U16 data uiCellVmax; //电芯电压最大值
|
||
U16 data uiCellVmin; //电芯电压最小值
|
||
U16 xdata uiVadcVmax; //ADC采集最大值
|
||
U16 xdata uiVadcVmin; //ADC采集最小值
|
||
U8 xdata ucTempeMiddle;
|
||
U16 xdata uiTempeMin;
|
||
U16 xdata uiTempeMax;
|
||
S32 xdata slCadcCurrent;
|
||
S32 xdata slCadcCurAverage;
|
||
U8 xdata ucCadcCnt;
|
||
S32 xdata slCadcCurBuf[16];
|
||
U8 xdata ucAfeI2CErrDelayCnt;
|
||
SYSINFOR xdata Info; //经过计算的值
|
||
AFEDATA xdata AFE; //AFE寄存器读取的值
|
||
AFEREG xdata REG; //AFE寄存器预设值
|
||
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFETwiCheck
|
||
* 参 数: 无
|
||
* 返回值: 无
|
||
* 描 述: 连续5S检测到AFE的I2C通讯错误,则置位bAfeErr=1
|
||
*************************************************************************************************/
|
||
void AFETwiCheck(void)
|
||
{
|
||
if(bAfeI2CRWErrFlg)
|
||
{
|
||
if(++ucAfeI2CErrDelayCnt >= TIME_1S_5S)
|
||
{
|
||
bAfeErr = 1;
|
||
ucAfeI2CErrDelayCnt = TIME_1S_5S;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ucAfeI2CErrDelayCnt = 0;
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEWriteReg
|
||
* 参 数: Reg:寄存器地址
|
||
WrBuf:写的数据:1Byte数据+1Byte CRC
|
||
* 返回值: 1:成功;0:失败
|
||
* 描 述: 写AFE寄存器,每次写一个寄存器
|
||
*************************************************************************************************/
|
||
BOOL AFEWriteReg(U8 Reg, U8 Length, U8 xdata *WrBuf)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 Times = 0;
|
||
U8 i;
|
||
|
||
if(!bAfeErr)
|
||
{
|
||
for(i=0; i<Length; i++)
|
||
{
|
||
while(Times++ < 5)
|
||
{
|
||
#ifdef TWI_Hardware_Module
|
||
{
|
||
Result = TwiWrite(AFE_ID, Reg, TWI_ADDR_1B, 1, TWI_CRC_YES, WrBuf);
|
||
}
|
||
#else
|
||
{
|
||
Result = TwiWrite(AFE_ID, Reg, 1, WrBuf);
|
||
}
|
||
#endif
|
||
if(Result)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
TWICON = 0; //Close TWI module
|
||
Delay1ms(1);
|
||
TwiInit(); //Reinitial
|
||
Delay1ms(1);
|
||
}
|
||
}
|
||
if(Times >= 5)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
Times = 0;
|
||
Reg++;
|
||
WrBuf++;
|
||
}
|
||
Delay1ms(1);
|
||
}
|
||
}
|
||
bAfeI2CRWErrFlg = !Result; //标记通讯是否正常
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEReadReg
|
||
* 参 数: Reg:寄存器地址
|
||
RdBuf:读的数据:2Byte数据+1Byte CRC
|
||
* 返回值: 1:成功;0:失败
|
||
* 描 述: 读AFE寄存器,每次连续读两个寄存器
|
||
*************************************************************************************************/
|
||
BOOL AFEReadReg(U8 Reg, U8 Length , U8 xdata *RdBuf)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 Times = 0;
|
||
|
||
if(!bAfeErr)
|
||
{
|
||
while(Times++ < 5) //如果读数出错,则Try 5次
|
||
{
|
||
#ifdef TWI_Hardware_Module
|
||
Result = TwiRead(AFE_ID, Reg, TWI_ADDR_1B, Length, TWI_CRC_YES, RdBuf);
|
||
#else
|
||
Result = TwiRead(AFE_ID, Reg, Length, RdBuf);
|
||
#endif
|
||
if(Result) //如果读数成功且CRC校验正确,则退出循环返回成功标标志
|
||
{
|
||
break;
|
||
}
|
||
else //如果TWI读数或CRC校验失败,则延时1mS之后再读取
|
||
{
|
||
TWICON = 0; //Close TWI module
|
||
Delay1ms(1);
|
||
TwiInit(); //Reinitial
|
||
Delay1ms(1);
|
||
}
|
||
}
|
||
}
|
||
bAfeI2CRWErrFlg = !Result; //标记通讯是否正常
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEClrFlg
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 清零AFE标志寄存器
|
||
*************************************************************************************************/
|
||
void AFEClrFlg(void)
|
||
{
|
||
if(AFEReadReg(AFE_FLAG1, 2, ®.AFEFLAG1))
|
||
{
|
||
if((REG.AFEFLAG1!=0) || (REG.AFEFLAG2!=0))
|
||
{
|
||
REG.AFESCONF1 |= 0x80;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
REG.AFESCONF1 &= ~0x80;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEInitReg
|
||
* 参 数: 无
|
||
* 返回值: 无
|
||
* 描 述: 初始化AFE寄存器
|
||
*************************************************************************************************/
|
||
void AFEInitReg(void)
|
||
{
|
||
U16 TempVar;
|
||
|
||
REG.AFEINTEN = 0x00; //采取查询式,故不需要ALARM中断
|
||
REG.AFESCONF1 = 0x50; //使能CTLD和WDT功能
|
||
REG.AFESCONF2 = 0x00; //AFE引脚配置为复位信号,ALARM输出低电平脉冲,放电MOS与充电MOS都关闭
|
||
REG.AFESCONF3 = 0xF8; //默认VADC和CADC都开启,CADC连续采样,10位ADC,VADC只采集电压转换周期50ms
|
||
REG.AFESCONF4 = 0x00; //默认关闭平衡BAT6-10
|
||
REG.AFESCONF5 = 0x00; //默认关闭平衡BAT1-5
|
||
REG.AFESCONF6 = 0x70; //CADC采集200mV范围,复位信号宽度1S,硬件短路保护电压100mV,硬件短路保护延时50uS
|
||
REG.AFESCONF7 = 0x01; //硬件过冲保护延时1个转换周期,充放电状态阈值选择位1.4mV,配置看门狗溢出10S
|
||
REG.AFESCONF8 = 0x03; //SCONF8 + SCONF9 = 11 1111 1111 = 1023
|
||
REG.AFESCONF9 = 0xff; //硬件过冲保护阈值1023*5.86mV = 5994.78
|
||
REG.AFESCONF10= 0x00; //低功耗控制位,写入0x33再写PD_EN=1进入低功耗
|
||
|
||
if(bSC_EN) //配置使能AFE短路功能
|
||
{
|
||
REG.AFESCONF1 |= 0x08;
|
||
REG.AFESCONF6 |= (E2ucAFEProtectConfig&0x0f);//将FLASH内参数写入AFE寄存器
|
||
}
|
||
if(bOV_EN) //配置使能AFE过压功能
|
||
{
|
||
REG.AFESCONF1 |= 0x04;
|
||
REG.AFESCONF7 |= (E2ucAFEProtectConfig&0xf0);//将FLASH内参数写入AFE寄存器
|
||
TempVar = (U32)E2uiAFEOVvol*50/293; //取出过压保护电压
|
||
REG.AFESCONF8 = TempVar>>8; //写高两位
|
||
REG.AFESCONF9 = TempVar; //写低八位
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEInit
|
||
* 参 数:
|
||
* 返回值: 1:成功;0:失败
|
||
* 描 述: 初始化AFE
|
||
*************************************************************************************************/
|
||
BOOL AFEInit(void)
|
||
{
|
||
U8 xdata RdBuf[2];
|
||
U8 i;
|
||
BOOL Result = 1;
|
||
U8 j = 3;
|
||
|
||
while(j--)
|
||
{
|
||
if( AFEWriteReg(AFE_INT_EN, 11, ®.AFEINTEN))
|
||
{
|
||
for(i=3; i<=11; i=i+2)
|
||
{
|
||
AFEReadReg(i, 2, RdBuf);
|
||
|
||
if((RdBuf[0]!=*(®.AFEFLAG1+i)) || (RdBuf[1]!=*(®.AFEFLAG1+i+1)))
|
||
{
|
||
if(i != 7) //平衡寄存器除外,因为平衡寄存器不置位,持续30s会自动清零
|
||
{
|
||
Result = 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Result = 0;
|
||
}
|
||
if(Result)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
return Result;
|
||
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFERdFlg
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 读取AFE标志寄存器
|
||
AFE_SC表示发生短路保护
|
||
FLAG2的bit2为1表示发生LVR复位,需要重新初始化AFE
|
||
*************************************************************************************************/
|
||
void AFERdFlg(void)
|
||
{
|
||
if(AFEReadReg(AFE_FLAG1, 2, ®.AFEFLAG1))
|
||
{
|
||
if((REG.AFEFLAG2&0x02) != 0) //CADC 电流转换完成
|
||
{
|
||
bCADCFlg = 1;
|
||
}
|
||
|
||
if((REG.AFEFLAG2&0x01) != 0) //VADC 电压转换完成
|
||
{
|
||
bVADCFlg = 1;
|
||
}
|
||
|
||
if((REG.AFEFLAG1&0x08) != 0 && (bLoadChkingFlg != 1)) //AFE短路保护
|
||
{
|
||
bAFE_SC = 1;
|
||
bLoadStartCheckFlg = 1; //开启负载检测
|
||
}
|
||
if((REG.AFEFLAG1&0x04) != 0) //AFE 硬件过压保护
|
||
{
|
||
bAFE_OV= 1;
|
||
}
|
||
|
||
if((REG.AFEFLAG2&0x04) != 0) //判断FLAG2的bit2是否为1,如为1则表示AFE发生过LVR,需要重新初始化AFE寄存器
|
||
{
|
||
AFEInit();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFERdStatus
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 读取AFE状态寄存器
|
||
*************************************************************************************************/
|
||
void AFERdStatus(void)
|
||
{
|
||
U8 RegTemp[2];
|
||
if(AFEReadReg(AFE_BSTATUS, 2, RegTemp))//®.AFEBSTATUS))//AFE固定读2Bytes,只取1Byte
|
||
{
|
||
ucAFEStatus = REG.AFEBSTATUS = RegTemp[0]; //更新充电器、负载的检测结果
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFERamCheck
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 定时检测AFE的寄存器是否被改写,如果是则重新初始化
|
||
*************************************************************************************************/
|
||
void AFERamCheck(void)
|
||
{
|
||
U8 xdata RdBuf[2];
|
||
U8 i;
|
||
|
||
for(i=3; i<=11; i=i+2)
|
||
{
|
||
AFEReadReg(i, 2, RdBuf);
|
||
|
||
if((RdBuf[0]!=*(®.AFEFLAG1+i)) || (RdBuf[1]!=*(®.AFEFLAG1+i+1)))
|
||
{
|
||
if(i != 7) //平衡寄存器除外,因为平衡寄存器不置位,持续30s会自动清零
|
||
{
|
||
if(!AFEInit())
|
||
{
|
||
bPDFlg = 1;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEEnterPD
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 控制AFE进入PD状态,关闭3.3V输出
|
||
*************************************************************************************************/
|
||
void AFEEnterPD(void)
|
||
{
|
||
REG.AFESCONF10 = 0x33;
|
||
if(AFEWriteReg(AFE_SCONF10, 1, ®.AFESCONF10))
|
||
{
|
||
REG.AFESCONF1 |= 0x20;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEMosCtl
|
||
* 参 数: MosStatus:MOS状态。1:开启;0:关闭
|
||
* 返回值: 无
|
||
* 描 述: 控制充放电MOS的开启和关闭
|
||
*************************************************************************************************/
|
||
void AFEMosCtl(U8 MosStatus)
|
||
{
|
||
REG.AFESCONF2 &= ~0x03;
|
||
REG.AFESCONF2 |= MosStatus;
|
||
AFEWriteReg(AFE_SCONF2, 1, ®.AFESCONF2);
|
||
}
|
||
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AFEChgerCheckEn、AFEChgerCheckDis、AFELoadCheckEn、AFELoadCheckDis
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 使能/关闭充电器检测、负载检测
|
||
*************************************************************************************************/
|
||
void AFEChgerCheckEn(void)
|
||
{
|
||
REG.AFESCONF1 |= 0x01;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
void AFEChgerCheckDis(void)
|
||
{
|
||
REG.AFESCONF1 &= ~0x01;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
void AFELoadCheckEn(void)
|
||
{
|
||
REG.AFESCONF1 |= 0x02;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
void AFELoadCheckDis(void)
|
||
{
|
||
REG.AFESCONF1 &= ~0x02;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AfeBalEn
|
||
* 参 数: BalChTemp:平衡对应的CELL,如果全部为0,则关闭平衡
|
||
* 返回值: 无
|
||
* 描 述: 开启和关闭平衡
|
||
*************************************************************************************************/
|
||
void AfeBalCtl(U16 BalChTemp)
|
||
{
|
||
REG.AFESCONF4 = BalChTemp>>5;
|
||
if(AFEWriteReg(AFE_SCONF4, 1, ®.AFESCONF4))
|
||
{
|
||
REG.AFESCONF5 = BalChTemp;
|
||
AFEWriteReg(AFE_SCONF5, 1, ®.AFESCONF5);
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AfeWDTEn, AfeWDTDis
|
||
* 参 数:
|
||
* 返回值: 无
|
||
* 描 述: 开启和关闭看门狗模块
|
||
*************************************************************************************************/
|
||
void AfeWDTEn(void)
|
||
{
|
||
REG.AFESCONF1 |= 0x10;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
void AfeWDTDis(void)
|
||
{
|
||
REG.AFESCONF1 &= ~0x10;
|
||
AFEWriteReg(AFE_SCONF1, 1, ®.AFESCONF1);
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AfeWDTEn, AfeWDTDis
|
||
* 参 数: 无
|
||
* 返回值: 无
|
||
* 描 述: 开启和关闭看门狗模块
|
||
*************************************************************************************************/
|
||
void AfeADCEn(void)
|
||
{
|
||
REG.AFESCONF3 |= 0xf8;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
|
||
void AfeADCDis(void)
|
||
{
|
||
REG.AFESCONF3 &= ~0xf8;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
void AfeCADCEn(void)
|
||
{
|
||
REG.AFESCONF3 |= 0xe0;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
|
||
void AfeCADCDis(void)
|
||
{
|
||
REG.AFESCONF3 &= ~0xe0;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
void AfeTempADCEn(void)
|
||
{
|
||
REG.AFESCONF3 |= 0x08;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
|
||
void AfeTempADCDis(void)
|
||
{
|
||
REG.AFESCONF3 &= ~0x08;
|
||
AFEWriteReg(AFE_SCONF3, 1, ®.AFESCONF3);
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: AfeAlarmEn,AfeAlarmDis
|
||
* 参 数: AlarmFlg:置位对应的ALARM位
|
||
* 返回值: 无
|
||
* 描 述: 开启和关闭对应的ALARM中断触发
|
||
*************************************************************************************************/
|
||
void AfeAlarmEn(U8 AlarmFlg)
|
||
{
|
||
REG.AFEINTEN |= AlarmFlg;
|
||
AFEWriteReg(AFE_INT_EN, 1, ®.AFEINTEN);
|
||
}
|
||
|
||
void AfeAlarmDis(U8 AlarmFlg)
|
||
{
|
||
REG.AFEINTEN &= ~AlarmFlg;
|
||
AFEWriteReg(AFE_INT_EN, 1, ®.AFEINTEN);
|
||
}
|
||
|
||
|