ZDBMS/code_drv/AFE.c

518 lines
14 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"
//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, &REG.AFEFLAG1))
{
if((REG.AFEFLAG1!=0) || (REG.AFEFLAG2!=0))
{
REG.AFESCONF1 |= 0x80;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
REG.AFESCONF1 &= ~0x80;
AFEWriteReg(AFE_SCONF1, 1, &REG.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位ADCVADC只采集电压转换周期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, &REG.AFEINTEN))
{
for(i=3; i<=11; i=i+2)
{
AFEReadReg(i, 2, RdBuf);
if((RdBuf[0]!=*(&REG.AFEFLAG1+i)) || (RdBuf[1]!=*(&REG.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, &REG.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))//&REG.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]!=*(&REG.AFEFLAG1+i)) || (RdBuf[1]!=*(&REG.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, &REG.AFESCONF10))
{
REG.AFESCONF1 |= 0x20;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
}
/*************************************************************************************************
* 函数名: AFEMosCtl
* 参 数: MosStatusMOS状态。1开启0关闭
* 返回值: 无
* 描 述: 控制充放电MOS的开启和关闭
*************************************************************************************************/
void AFEMosCtl(U8 MosStatus)
{
REG.AFESCONF2 &= ~0x03;
REG.AFESCONF2 |= MosStatus;
AFEWriteReg(AFE_SCONF2, 1, &REG.AFESCONF2);
}
/*************************************************************************************************
* 函数名: AFEChgerCheckEn、AFEChgerCheckDis、AFELoadCheckEn、AFELoadCheckDis
* 参 数:
* 返回值: 无
* 描 述: 使能/关闭充电器检测、负载检测
*************************************************************************************************/
void AFEChgerCheckEn(void)
{
REG.AFESCONF1 |= 0x01;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
void AFEChgerCheckDis(void)
{
REG.AFESCONF1 &= ~0x01;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
void AFELoadCheckEn(void)
{
REG.AFESCONF1 |= 0x02;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
void AFELoadCheckDis(void)
{
REG.AFESCONF1 &= ~0x02;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
/*************************************************************************************************
* 函数名: AfeBalEn
* 参 数: BalChTemp平衡对应的CELL如果全部为0则关闭平衡
* 返回值: 无
* 描 述: 开启和关闭平衡
*************************************************************************************************/
void AfeBalCtl(U16 BalChTemp)
{
REG.AFESCONF4 = BalChTemp>>5;
if(AFEWriteReg(AFE_SCONF4, 1, &REG.AFESCONF4))
{
REG.AFESCONF5 = BalChTemp;
AFEWriteReg(AFE_SCONF5, 1, &REG.AFESCONF5);
}
}
/*************************************************************************************************
* 函数名: AfeWDTEn AfeWDTDis
* 参 数:
* 返回值: 无
* 描 述: 开启和关闭看门狗模块
*************************************************************************************************/
void AfeWDTEn(void)
{
REG.AFESCONF1 |= 0x10;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
void AfeWDTDis(void)
{
REG.AFESCONF1 &= ~0x10;
AFEWriteReg(AFE_SCONF1, 1, &REG.AFESCONF1);
}
/*************************************************************************************************
* 函数名: AfeWDTEn AfeWDTDis
* 参 数: 无
* 返回值: 无
* 描 述: 开启和关闭看门狗模块
*************************************************************************************************/
void AfeADCEn(void)
{
REG.AFESCONF3 |= 0xf8;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
void AfeADCDis(void)
{
REG.AFESCONF3 &= ~0xf8;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
void AfeCADCEn(void)
{
REG.AFESCONF3 |= 0xe0;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
void AfeCADCDis(void)
{
REG.AFESCONF3 &= ~0xe0;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
void AfeTempADCEn(void)
{
REG.AFESCONF3 |= 0x08;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
void AfeTempADCDis(void)
{
REG.AFESCONF3 &= ~0x08;
AFEWriteReg(AFE_SCONF3, 1, &REG.AFESCONF3);
}
/*************************************************************************************************
* 函数名: AfeAlarmEnAfeAlarmDis
* 参 数: AlarmFlg置位对应的ALARM位
* 返回值: 无
* 描 述: 开启和关闭对应的ALARM中断触发
*************************************************************************************************/
void AfeAlarmEn(U8 AlarmFlg)
{
REG.AFEINTEN |= AlarmFlg;
AFEWriteReg(AFE_INT_EN, 1, &REG.AFEINTEN);
}
void AfeAlarmDis(U8 AlarmFlg)
{
REG.AFEINTEN &= ~AlarmFlg;
AFEWriteReg(AFE_INT_EN, 1, &REG.AFEINTEN);
}