Files
2026-08-25 17:30:40 +08:00

1603 lines
37 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.
/**
******************************************************************************
* @file tim.c
* @author Jerry
* @version V2.1
* @date 19-April-2022
* @brief tim program body.
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
#include "string.h"
#include "soe.h"
CALI_STRUCT cali;
uint8_t bAlarmFlag;
uint8_t bAlarmFlagOld;
AFE_RAM afeRam;
AFE_FLG afeFlg;
int16_t siCurBuf[4]; //CADC以250ms周期采样4次
uint8_t ucCadcTimeCnt; //CADC采样计数
uint8_t bDSGING; //放电状态标记
uint8_t bCHGING; //充电状态标记
uint8_t bSTANDBY; //待机状态标记
uint8_t bFC; //=1充满电
uint8_t ucChgEndTimeCnt; //充电截止条件判断计数器
uint8_t ucChgEndRTimeCnt;//
uint8_t E2ucChgEndDelay; //充电截止条件判断延时
uint8_t E2uiChgEndVol; //充电截止电压
uint8_t E2siChgEndCur; //充电截止电流
uint8_t bCHGEnd; //充电结束关充电MOS标记
uint8_t bCHGClosedFlg; //关闭充电标记
uint8_t curLimitFlag;
uint8_t curLimitCount;
uint16_t curLimitReleaseCount;
uint16_t curLimitCloseCount;
uint8_t DSGcount; //小电流放电计数
uint8_t DSGminiFlag; //小电流放电标志
uint8_t CHGcount;
uint8_t CHGminiFlag;
uint8_t ErrDSGcount; //放电MOS故障的延时计数
uint8_t ErrCHGcount; //充电MOS故障的延时计数
uint8_t ErrDSGRelaycount;//放电MOS故障恢复的延时计数
uint8_t ErrCHGRelaycount;//充电MOS故障恢复的延时计数
uint8_t nullCurrent_Flag; //此时1s内的电流采样值无效标志
uint8_t sc_OccurFlag; //浪涌短路出现过的标志
uint8_t tsc_OccurFlag; //真短路出现过的标志
uint8_t pchgFail_OccurFlag; //预充超时失败出现过的标志
uint8_t sc_RepeatFlag; //浪涌短路持续出现的标志
uint8_t sc_RepeatDelay; //等待浪涌短路倒计时,最大60s =>对应消失后60s内未再次出现,说明正常
uint8_t sc_RepeatCount; //浪涌短路重复的计数,最大5次 =>对应连续5次出现短路 =>会在第五次短路时,MCU接管将标志位置1,控制MOS持续关闭
uint8_t tsc_RepeatFlag; //真短路持续出现的标志
uint8_t tsc_RepeatDelay; //等待真短路倒计时,最大60s =>对应消失后60s内未再次出现,说明正常
uint8_t tsc_RepeatCount; //真短路重复的计数,最大5次 =>对应连续5次出现短路 =>会在第五次短路时,MCU接管将标志位置1,控制MOS持续关闭
uint8_t pchgFail_RepeatFlag; //预充超时失败持续出现的标志
uint8_t pchgFail_RepeatTime; //等待预充超时失败倒计时,最大60s =>对应消失后60s内未再次出现,说明正常
uint8_t pchgFail_RepeatCount; //预充超时失败重复的计数,最大5次 =>对应连续5次出现预充超时失败 =>会在第五次预充超时失败时,锁定不可恢复标志位,控制MOS持续关闭
uint8_t fcc4_count; //满充条件4的延时计数
uint8_t fcc4r_count; //满充条件4释放的延时计数
uint16_t CTRL_Order; //上位机[临时]控制MOS关闭指令
uint8_t OCC2_Flag;
uint16_t OCC2MoniCount;
uint8_t sc_Often_Flag; //浪涌短路连续发生,执行锁定的标志
uint16_t tsc_relaycount; //真短路5min自动解除的延时计数
uint8_t dsgCtrl; //放电MOS控制状态
uint8_t dsgCtrl_old;
int16_t cellVol[20]; //20串电压
int16_t cellVoltageMax;
int16_t cellVoltageMin;
uint8_t MOS_Close_Flg; //需要控制MOS全关的标志
uint8_t sc_close_flag; //控制浪涌短路保护关闭的标志
//写AFE的寄存器
uint8_t AFE_Write(uint8_t addr, uint8_t lenth, uint8_t *data)
{
uint8_t i;
uint8_t result;
result = 0;
for(i=0; i<lenth; i++)
{
result = AFE_WriteOneByte(addr, data);
if(result != 0)
{
delay_ms(1);
result = AFE_WriteOneByte(addr, data);
if(result != 0)
{
break;
}
}
addr++;
data++;
delay_ms(1);
}
return result;
}
//读AFE的寄存器
uint8_t AFE_Read(uint8_t addr, uint8_t lenth, uint8_t *data)
{
uint8_t result = 0;
result = AFE_ReadMulByte(addr, lenth, data);
if(result != 0)
{
//读失败,重新初始化SPI
SPI2_Error();
delay_ms(10);
result = AFE_ReadMulByte(addr, lenth, data);
if(result != 0)
{
//读失败,重新初始化SPI
SPI2_Error();
delay_ms(10);
return 1;
}
}
return 0;
}
//从Flash数据更新到AFE
//FLASH -> MCU RAM -> AFE
#define afeReg_num 14
uint8_t MEMORY_UpdateAFE(void)
{
uint8_t i;
uint8_t WrBuf[14];
uint8_t RdBuf[14];
uint8_t afe_mode;
//默认值
WrBuf[0] = 0x00; //SCONF4 [bit0~4:10000-16串]
WrBuf[1] = 0x08; //SCONF5 bit3:1-开启CADC电流采集
WrBuf[2] = 0x08; //SCONF6 bit3:1-开启短路保护
WrBuf[3] = 0x00; //SCONF7 bit6:0-负载检测上拉电流(暂时默认60uA)
WrBuf[4] = 0x00; //OWV/ALARMH
WrBuf[5] = 0x04; //ALARML bit2:1-短路保护Alarm发送低电平脉冲
WrBuf[6] = 0x00; //OVT/OVH
WrBuf[7] = 0x00; //OVL
WrBuf[8] = 0x00; //UVT/UVH
WrBuf[9] = 0x00; //UVL
WrBuf[10] = 0x00; //OCD1V/OCD1T
WrBuf[11] = 0x00; //OCD2V/OCD2T [bit0~3:放电过流2保护=2*10+10=30mV]
WrBuf[12] = 0x00; //SCV/SCT bit4~5:短路保护=2*VOCD2=60mV [bit0~3:延时0us]
WrBuf[13] = 0x00; //OCCV/OCCT
//电池串数:先看ee_sconf1是否在5~16,是则用SCONF1路径;否则用ee_sconf4
afe_mode = (paraMem.sc_mode >> 8) & 0xFF;
{
uint8_t cn1 = bmsMem.ee_sconf1 & 0x0F; //SCONF1低4位,5-15串,0表示16串
if((cn1 >= 5 && cn1 <= 15) || cn1 == 0) //5~15串 或 16串(cn=0)
{
bmsMem.ucCellNum = (cn1 == 0) ? 16 : cn1; //cn=0是16串(4位字段存不下16)
WrBuf[0] |= bmsMem.ucCellNum & 0x0F; //309/35XX通用4位cn
}
else if(afe_mode == 1) //SH36735XX,支持4/17~20串
{
bmsMem.ucCellNum = paraMem.ee_sconf4 & 0x1F; //SCONF4低5位,4-20串
if(bmsMem.ucCellNum < 4 || bmsMem.ucCellNum > 20)
{
bmsMem.ucCellNum = 20; // 越界默认20串
}
WrBuf[0] = bmsMem.ucCellNum & 0x1F; // 写入SCONF4
}
else //SH367309,不支持4/17~20串
{
bmsMem.ucCellNum = 16; // 越界默认16串
WrBuf[0] |= bmsMem.ucCellNum & 0x0F;
}
}
//短路电流=(OCD2V*10+10)*2
WrBuf[11] |= (bmsMem.ee_scv_sct >> 4) & 0x0F;
//短路延时
WrBuf[12] |= bmsMem.ee_scv_sct & 0x0F;
if(AFE_Write(REG_ADDR_SCONF4, 14, WrBuf) == 0)
{
if(AFE_Read(REG_ADDR_SCONF4, 14, RdBuf) == 0)
{
for(i=0;i<14;i++)
{
if(RdBuf[i] != WrBuf[i])
{
return 1; //写入有误
}
}
return 0;
}
else
{
return 2; //读取数据失败
}
}
else
{
AFE_Reset();
return 3; //写入数据失败
}
}
//电压获取
//main->while 1s
void AFE_VoltageProcess(void)
{
uint8_t i;
int16_t max,min,maxIndex,minIndex; //计算最高最低
int32_t temp; //计算总压
uint8_t afe_mode;
uint8_t rdLen;
//先确定串数和读取长度:先看ee_sconf1是否在5~16,是则用SCONF1路径;否则用ee_sconf4
afe_mode = (paraMem.sc_mode >> 8) & 0xFF;
{
uint8_t cn1 = bmsMem.ee_sconf1 & 0x0F; //SCONF1低4位,5-15串,0表示16串
if((cn1 >= 5 && cn1 <= 15) || cn1 == 0) //5~15串 或 16串(cn=0)
{
bmsMem.ucCellNum = (cn1 == 0) ? 16 : cn1; //cn=0是16串(4位字段存不下16)
rdLen = 32; //16串 × 2字节
}
else if(afe_mode == 1) //SH36735XX,支持4/17~20串
{
bmsMem.ucCellNum = paraMem.ee_sconf4 & 0x1F; //SCONF4低5位,4-20串
if(bmsMem.ucCellNum < 4 || bmsMem.ucCellNum > 20)
{
bmsMem.ucCellNum = 20; // 越界默认20串
}
rdLen = 40; //20串 × 2字节
}
else //SH367309,不支持4/17~20串
{
bmsMem.ucCellNum = 16; // 越界默认16串
rdLen = 32; //16串 × 2字节
}
}
if(AFE_Read(REG_ADDR_CELL1H, rdLen, &afeRam.cell1h) != 0)
{
return;
}
//采集电芯电压(显示给上位机)
bmsMem.vCell[0] = ((uint16_t)afeRam.cell1h <<8 | afeRam.cell1l ) *5 >> 5; //=cell1*5/32
bmsMem.vCell[1] = ((uint16_t)afeRam.cell2h <<8 | afeRam.cell2l ) *5 >> 5;
bmsMem.vCell[2] = ((uint16_t)afeRam.cell3h <<8 | afeRam.cell3l ) *5 >> 5;
bmsMem.vCell[3] = ((uint16_t)afeRam.cell4h <<8 | afeRam.cell4l ) *5 >> 5;
bmsMem.vCell[4] = ((uint16_t)afeRam.cell5h <<8 | afeRam.cell5l ) *5 >> 5;
bmsMem.vCell[5] = ((uint16_t)afeRam.cell6h <<8 | afeRam.cell6l ) *5 >> 5;
bmsMem.vCell[6] = ((uint16_t)afeRam.cell7h <<8 | afeRam.cell7l ) *5 >> 5;
bmsMem.vCell[7] = ((uint16_t)afeRam.cell8h <<8 | afeRam.cell8l ) *5 >> 5;
bmsMem.vCell[8] = ((uint16_t)afeRam.cell9h <<8 | afeRam.cell9l ) *5 >> 5;
bmsMem.vCell[9] = ((uint16_t)afeRam.cell10h <<8 | afeRam.cell10l) *5 >> 5;
bmsMem.vCell[10] = ((uint16_t)afeRam.cell11h <<8 | afeRam.cell11l) *5 >> 5;
bmsMem.vCell[11] = ((uint16_t)afeRam.cell12h <<8 | afeRam.cell12l) *5 >> 5;
bmsMem.vCell[12] = ((uint16_t)afeRam.cell13h <<8 | afeRam.cell13l) *5 >> 5;
bmsMem.vCell[13] = ((uint16_t)afeRam.cell14h <<8 | afeRam.cell14l) *5 >> 5;
bmsMem.vCell[14] = ((uint16_t)afeRam.cell15h <<8 | afeRam.cell15l) *5 >> 5;
bmsMem.vCell[15] = ((uint16_t)afeRam.cell16h <<8 | afeRam.cell16l) *5 >> 5;
if(afe_mode == 1)
{
bmsMem.vCell2[0] = ((uint16_t)afeRam.cell17h<<8 | afeRam.cell17l)*5>>5;
bmsMem.vCell2[1] = ((uint16_t)afeRam.cell18h<<8 | afeRam.cell18l)*5>>5;
bmsMem.vCell2[2] = ((uint16_t)afeRam.cell19h<<8 | afeRam.cell19l)*5>>5;
bmsMem.vCell2[3] = ((uint16_t)afeRam.cell20h<<8 | afeRam.cell20l)*5>>5;
}
//采集电芯电压(实际)
cellVol[0] = (int16_t)((uint16_t)afeRam.cell1h <<8 | afeRam.cell1l ) *5 >> 5; //=cell1*5/32
cellVol[1] = (int16_t)((uint16_t)afeRam.cell2h <<8 | afeRam.cell2l ) *5 >> 5;
cellVol[2] = (int16_t)((uint16_t)afeRam.cell3h <<8 | afeRam.cell3l ) *5 >> 5;
cellVol[3] = (int16_t)((uint16_t)afeRam.cell4h <<8 | afeRam.cell4l ) *5 >> 5;
cellVol[4] = (int16_t)((uint16_t)afeRam.cell5h <<8 | afeRam.cell5l ) *5 >> 5;
cellVol[5] = (int16_t)((uint16_t)afeRam.cell6h <<8 | afeRam.cell6l ) *5 >> 5;
cellVol[6] = (int16_t)((uint16_t)afeRam.cell7h <<8 | afeRam.cell7l ) *5 >> 5;
cellVol[7] = (int16_t)((uint16_t)afeRam.cell8h <<8 | afeRam.cell8l ) *5 >> 5;
cellVol[8] = (int16_t)((uint16_t)afeRam.cell9h <<8 | afeRam.cell9l ) *5 >> 5; //=cell1*5/32
cellVol[9] = (int16_t)((uint16_t)afeRam.cell10h <<8 | afeRam.cell10l) *5 >> 5;
cellVol[10] = (int16_t)((uint16_t)afeRam.cell11h <<8 | afeRam.cell11l) *5 >> 5;
cellVol[11] = (int16_t)((uint16_t)afeRam.cell12h <<8 | afeRam.cell12l) *5 >> 5;
cellVol[12] = (int16_t)((uint16_t)afeRam.cell13h <<8 | afeRam.cell13l) *5 >> 5;
cellVol[13] = (int16_t)((uint16_t)afeRam.cell14h <<8 | afeRam.cell14l) *5 >> 5;
cellVol[14] = (int16_t)((uint16_t)afeRam.cell15h <<8 | afeRam.cell15l) *5 >> 5;
cellVol[15] = (int16_t)((uint16_t)afeRam.cell16h <<8 | afeRam.cell16l) *5 >> 5;
if(afe_mode == 1)
{
cellVol[16] = (int16_t)((uint16_t)afeRam.cell17h <<8 | afeRam.cell17l) *5 >> 5;
cellVol[17] = (int16_t)((uint16_t)afeRam.cell18h <<8 | afeRam.cell18l) *5 >> 5;
cellVol[18] = (int16_t)((uint16_t)afeRam.cell19h <<8 | afeRam.cell19l) *5 >> 5;
cellVol[19] = (int16_t)((uint16_t)afeRam.cell20h <<8 | afeRam.cell20l) *5 >> 5;
}
//计算总电压
temp = 0;
for(i=0;i<bmsMem.ucCellNum;i++)
{
temp += (int32_t)cellVol[i];
}
bmsMem.packVoltage = (uint32_t)temp;
//计算电芯电压最大最小值
max = cellVol[0];
min = cellVol[0];
maxIndex = 0;
minIndex = 0;
for(i=0;i<bmsMem.ucCellNum;i++)
{
if(max<cellVol[i])
{
max = cellVol[i];
maxIndex = i;
}
if(min>cellVol[i])
{
min = cellVol[i];
minIndex = i;
}
}
cellVoltageMax = max;
cellVoltageMin = min;
if(maxIndex < 16)
{
bmsMem.cellVoltageMax = bmsMem.vCell[maxIndex];
}
else
{
bmsMem.cellVoltageMax = bmsMem.vCell2[maxIndex - 16];
}
if(minIndex < 16)
{
bmsMem.cellVoltageMin = bmsMem.vCell[minIndex];
}
else
{
bmsMem.cellVoltageMin = bmsMem.vCell2[minIndex - 16];
}
bmsMem.cellVoltageMaxIndex = maxIndex;
bmsMem.cellVoltageMinIndex = minIndex;
//sum of all packs
bmsMem.can_VolMax = bmsMem.cellVoltageMax;
bmsMem.can_VolMaxIndex = bmsMem.cellVoltageMaxIndex;
bmsMem.can_VolMin = bmsMem.cellVoltageMin;
bmsMem.can_VolMinIndex = bmsMem.cellVoltageMinIndex;
//过压相关报警和保护
Trigger_OVAlarm(); //报警
Release_OVAlarm(); //报警恢复
Trigger_OVProtect(); //保护
Release_OVProtect(); //保护恢复
//欠压相关
if((bmsMem.balanceStatus & 0x0020) == 0)
{
Trigger_UVAlarm(); //报警
Release_UVAlarm(); //报警恢复
Trigger_UVProtect(); //保护
Release_UVProtect(); //保护恢复
}
else
{
bmsMem.bStatus1 &= ~0x0202;
bmsMem.bStatus3 &= ~0x0A00;
}
}
//电流获取
//read 4 times and average
void AFE_CurrentProcess(void)
{
uint8_t temp[2];
int16_t avecur;
avecur = siCurBuf[ucCadcTimeCnt]; //4个CADC的值存放于数组中
if(AFE_Read(REG_ADDR_CADCDH, 2, temp) != 0)
{
siCurBuf[ucCadcTimeCnt] = avecur; //读失败了将上一组电流重赋值
}
else
{
avecur =(int16_t) (temp[0]<<8 | temp[1]); //读成功赋值
siCurBuf[ucCadcTimeCnt] = avecur;
}
if(++ucCadcTimeCnt >= 4) //计算1s内电流的平均值
{
ucCadcTimeCnt = 0;
avecur = ((int32_t)siCurBuf[0]+siCurBuf[1]+siCurBuf[2]+siCurBuf[3]) >> 2;
cali.tempCur = avecur - cali.cadcZero;
bmsMem.cadcAveVal = avecur; //显示cadc寄存器电流
//对当前电流执行校准,计算校准参数
if(cali.cmdZero != 0)
{
cali.flagWrZeroToEE = cali.cmdZero;
cali.cmdZero = 0;
cali.cadcZero = avecur;
bmsMem.cadcZero = cali.cadcZero;
}
else if(cali.cmdGain != 0)
{
cali.flagWrGainToEE = cali.cmdGain;
cali.cmdGain = 0;
if(cali.tempCur<0)
{
cali.cadcGain = -cali.current* 100 / cali.tempCur;
}
else if(cali.tempCur>0)
{
cali.cadcGain = cali.current* 100 / cali.tempCur;
}
bmsMem.cadcGain = cali.cadcGain;
}
//更新电流值
if(nullCurrent_Flag == 0)
{
bmsMem.packCurrent = (int32_t)cali.cadcGain * cali.tempCur /100;
}
else //这一秒的电流值无效,同时因为触发条件是写AFE芯片会关闭MOS,正常来说也是无电流的
{
bmsMem.packCurrent = 0;
nullCurrent_Flag = 0;
}
//sum of all packs
bmsMem.can_cur = (int16_t) (bmsMem.packCurrent/10); //统一数值单位0.01A
//小电流延迟显示
if((bmsMem.packCurrent > (-100)) && (bmsMem.packCurrent < 0)) //小电流放电
{
if(DSGminiFlag == 0)
{
DSGcount++;
if(DSGcount >= 3) //延迟3s显示
{
DSGminiFlag = 1;
DSGcount = 0;
}
else
{
bmsMem.packCurrent = 0;
}
}
}
else if((bmsMem.packCurrent > 0) && (bmsMem.packCurrent < 100)) //小电流充电
{
if(CHGminiFlag == 0)
{
CHGcount++;
if(CHGcount >= 3) //延迟3s显示
{
CHGminiFlag = 1;
CHGcount = 0;
}
else
{
bmsMem.packCurrent = 0;
}
}
}
else
{
DSGcount = 0;
CHGcount = 0;
DSGminiFlag = 0;
CHGminiFlag = 0;
}
//判断充放电状态
bDSGING = 0;
bCHGING = 0;
bSTANDBY = 0;
if(bmsMem.packCurrent <= (-100))
{
bDSGING = 1;
}
else if(bmsMem.packCurrent >= 100)
{
bCHGING = 1;
}
else
{
//待机状态时,电流值存在(上位机可看)
//待机状态时,不参与容量计算,但参与电流校准
bSTANDBY = 1;
}
if(curLimit_ctrlFlag == 1) //开启限流后,根据电流值立刻改动限流的占空比
{
//根据实时电流值调整占空比
CHG_LIMIT_PWM_Adjust();
}
}
//充放电状态赋值
bmsMem.bStatus3 &= 0xff3f;
if(bCHGING == 1)
{
bmsMem.bStatus3 |= 0x0080;
}
if(bDSGING == 1)
{
bmsMem.bStatus3 |= 0x0040;
}
//存在充电或放电,休眠起始点更新
if((bmsMem.packCurrent <= (-2000)) || (bmsMem.packCurrent >= 2000))
{
if(((paraMem.sleep_min_disable & 0x8000) == 0) || ((paraMem.sleep2_min_disable & 0x8000) == 0)) //任意一项休眠都更新
{
sleep_flag = 0;
SLEEP_Refresh();
SLEEP2_Refresh();
}
}
}
//电流校准后保存
void CALI_CurrentProcess(void)
{
//收到零点校准指令
if(cali.flagWrZeroToEE != 0)
{
if(scr_WrZero_Flg == 1)
{
scr_WrZero_Flg = 2; //表示完成
}
else if(cali.flagWrZeroToEE == 1) //上位机执行的校准需要回复,云平台是另外的
{
modbusFaaRxFlg = 1;
modbus1FaaRxFlg = 1;
}
cali.flagWrZeroToEE = 0;
cali.flagZeroCaliFail = EEPROM_CALI_WrZero(cali.cadcZero);
}
//收到增益校准指令
if(cali.flagWrGainToEE != 0)
{
if(scr_WrGain_Flg == 1)
{
scr_WrGain_Flg = 2; //表示完成
}
else if(cali.flagWrGainToEE == 1) //上位机执行的校准需要回复,云平台是另外的
{
modbusFbbRxFlg = 1;
modbus1FbbRxFlg = 1;
}
cali.flagWrGainToEE = 0;
cali.flagGainCaliFail = EEPROM_CALI_WrGain(cali.cadcGain);
}
}
//获取MOS温度和环境温度
//main->while 1s
void AFE_TemperaProcess(void)
{
//获取afe温度
if(AFE_Read(REG_ADDR_TEMP1H, 6, &afeRam.temp1h) != 0)
{
return;
}
afeFlg.temp1 = ((uint16_t)afeRam.temp1h <<8 | afeRam.temp1l);
afeFlg.temp2 = ((uint16_t)afeRam.temp2h <<8 | afeRam.temp2l);
afeFlg.temp3 = ((uint16_t)afeRam.temp3h <<8 | afeRam.temp3l);
bmsMem.afe_T1 = TEMP_Cal_CMFA(afeFlg.temp1 * 1000 /(32768-afeFlg.temp1));
bmsMem.afe_T2 = TEMP_Cal_CMFA(afeFlg.temp2 * 1000 /(32768-afeFlg.temp2));
bmsMem.afe_T3 = TEMP_Cal_CMFA(afeFlg.temp3 * 1000 /(32768-afeFlg.temp3));
//针对bmsMem.afe_T1+T2,进行MOS温度告警和告警释放
Trigger_afeTAlarm();
Release_afeTAlarm();
//针对bmsMem.afe_T1+T2,进行MOS温度保护和保护释放
Trigger_afeTProtect();
Release_afeTProtect();
//针对bmsMem.afe_T3,进行环境温度告警和告警释放
Trigger_amTAlarm();
Release_amTAlarm();
//针对bmsMem.afe_T3,进行环境温度保护和保护释放
Trigger_amTProtect();
Release_amTProtect();
}
//充电限流10A的控制标志位
void CHG_LIMIT_Ctrl(void)
{
//触发
if(curLimitFlag == 0)
{
//常规大电流限流保护
if(bmsMem.packCurrent >= (bmsMem.CHGLimit_Value * 1000))
{
curLimitCount++;
if(curLimitCount >= bmsMem.CHGLimit_Count)
{
curLimitCount = 0;
curLimitFlag = 1;
}
}
}
//延时释放
else
{
if(bCHGING == 1) //充电过程中,持续10min后释放
{
curLimitReleaseCount++;
if(curLimitReleaseCount >= bmsMem.CHGLimit_ReleaseCount)
{
curLimitReleaseCount = 0;
curLimitFlag = 0;
}
}
else
{
curLimitCloseCount++;
if(curLimitCloseCount >= 8)
{
curLimitCloseCount = 0;
curLimitFlag = 0;
}
}
}
//若之前有充电报警在,限流不能打开
//包括AFE的充电报警 //但去掉充电过流
if(((bmsMem.bStatus1 & 0x41) != 0) || ((bmsMem.bStatus2 & 0x0183) != 0) || ((bmsMem.bStatus3 & 0x0100) != 0) || ((bmsMem.temperaStatus & 0x05) != 0) || ((bmsMem.balanceStatus & 0x0500) != 0))
{
curLimitReleaseCount = 0;
curLimitFlag = 0;
}
//若正在放电,限流板应当关闭
if(bDSGING == 1)
{
curLimitReleaseCount = 0;
curLimitFlag = 0;
}
//进行充电MOS控制时,限流板也关闭
if(((CTRL_Order & 0x02) != 0) || ((paraMem.ctrl_disable & 0x02) != 0))
{
curLimitReleaseCount = 0;
curLimitFlag = 0;
}
//限流标志
if(curLimitFlag == 0)
{
bmsMem.balanceStatus &= 0xffef;
}
else
{
bmsMem.balanceStatus |= 0x0010;
}
}
//放电过流2的判断
void OCC2_TIM_Moni(void)
{
//放电过流2
if((bmsMem.bStatus1 & BIT10) ==0)
{
if(bmsMem.packCurrent < -paraMem.mcu_ocd2*1000)
{
OCC2MoniCount++;
if(OCC2MoniCount > paraMem.mcu_ocd2_t) //单位10ms
{
bmsMem.bStatus1 |= BIT10;
OCC2MoniCount = 0;
}
}
else
{
OCC2MoniCount = 0;
}
}
}
//因预充使用了CTTRL引脚,所以放电过流2只是用中断来写RAM关闭放电MOS
void OCC2_Ctrl(void)
{
uint8_t temp[1];
//触发后立刻关闭放电MOS
if((bmsMem.bStatus1 & BIT10) != 0)
{
//只在第一次执行
if(OCC2_Flag == 0)
{
if(AFE_Read(REG_ADDR_SCONF2,1,temp) == 0)
{
temp[0] &= ~0x02;
AFE_Write(REG_ADDR_SCONF2,1,&temp[0]);
OCC2_Flag = 1;
}
}
}
else
{
OCC2_Flag = 0;
}
}
//统一写MOS控制到RAM,并控制限流。限流和充放MOS要有时间间隔
void AFE_Ctrl(void)
{
//默认正常[充放MOS全由硬件控制]
uint8_t temp = 0x83;
//开放电MOS前开预充
if(PCHG_Flag == 1)
{
temp &= ~0x02; //保持关闭放电MOS
PCHG_Ctrl(); //走预充流程
}
/*控制限流关闭在前*/
if(curLimitFlag == 0)
{
CHG_LIMIT_Off();
}
//休眠模式[关闭放电MOS,不影响充电MOS和限流板状态]
if(sleep_flag == 1)
{
temp &= ~0x02;
}
//各种充电保护(不带afe的)+满充条件4[关闭充电MOS和限流板,不影响放电MOS状态]
if(((bmsMem.bStatus1 & 0x0901) != 0) || ((bmsMem.bStatus2 & 0x0083) != 0) || ((bmsMem.temperaStatus & 0x0515) != 0)) //关闭充电MOS
{
temp &= ~0x01;
if(((bmsMem.bStatus1 & 0x0901) != 0) || ((bmsMem.bStatus2 & 0x0083) != 0) || ((bmsMem.temperaStatus & 0x0505) != 0)) //除了充电过流外,会同步关闭限流
{
curLimitReleaseCount = 0;
curLimitFlag = 0;
}
}
//各种放电保护(带真短路和预充失败)[关闭放电MOS,不影响充电MOS和限流板状态]
if(((bmsMem.bStatus1 & 0x062E) != 0) || ((bmsMem.bStatus2 & 0x007C) != 0) || ((bmsMem.temperaStatus & 0x0A2A) != 0)) //关闭放电MOS
{
temp &= ~0x02;
}
//限流启用[关闭充电MOS,后续开启限流,不影响放电MOS状态]
if(curLimitFlag == 1)
{
temp &= ~0x01;
}
/*因上位机写入指令而控制*/
if(((CTRL_Order & 0x01) != 0) || ((paraMem.ctrl_disable & 0x01) != 0)) //强制关闭放电MOS
{
temp &= ~0x02;
}
if(((CTRL_Order & 0x02) != 0) || ((paraMem.ctrl_disable & 0x02) != 0)) //强制关闭充电MOS
{
temp &= ~0x01;
}
/*当放电MOS被关闭,将要被打开,执行预充而不打开放电MOS*/
if((temp & 0x02) != 0) //要开启放电MOS
{
dsgCtrl = 0xAA;
}
else //要关闭放电MOS
{
dsgCtrl = 0xBB;
}
if(dsgCtrl_old == 0) //初始值0不参与判断
{
dsgCtrl_old = dsgCtrl;
}
else
{
if((dsgCtrl == 0xAA) && (dsgCtrl_old != 0xAA)) //从关闭转变为打开
{
if(PCHG_Flag == 0)
{
temp &= ~0x02; //保持关闭
PCHG_Flag = 1;//启动预充
}
else if(PCHG_Flag == 2)
{
PCHG_Flag = 0;//下次可以继续启动预充
dsgCtrl_old = dsgCtrl;
}
}
else
{
dsgCtrl_old = dsgCtrl;
}
}
/*开关MOS控制*/
AFE_Write(REG_ADDR_SCONF2,1,&temp);
/*控制限流打开在后*/
if(curLimitFlag == 1)
{
CHG_LIMIT_On();
}
}
//MOS控制开
//预充流程结束/真短路检测结束/真短路释放
void CTRL_On(void)
{
//不需要控制,只要后续AFE_Ctrl正常控制
MOS_Close_Flg = 0;
}
//MOS控制关
void CTRL_Off(void)
{
uint8_t temp = 0x80;
AFE_Write(REG_ADDR_SCONF2,1,&temp);
//控制全关时,正常控制MOS处也要同步
MOS_Close_Flg = 1;
}
//获取AFE状态位
//main->while 1s
void AFE_ProtectProcess(void)
{
uint8_t temp[5];
//read flag1-3,bstatus1-2
if(AFE_Read(REG_ADDR_FLAG1,5,temp) == 0)
{
//短路保护
if((temp[0] & BIT4) != 0)
{
bmsMem.bStatus1 |= BIT5;
}
else
{
bmsMem.bStatus1 &= ~BIT5;
}
//充电MOS状态
if((temp[3] & BIT0) != 0)
{
bmsMem.bStatus3 |= BIT1;
}
else
{
bmsMem.bStatus3 &= ~BIT1;
}
//放电MOS状态
if((temp[3] & BIT1) != 0)
{
bmsMem.bStatus3 |= BIT0;
}
else
{
bmsMem.bStatus3 &= ~BIT0;
}
}
//浪涌短路保护的释放
if(sc_close_flag == 1)
{
uint8_t temp = 0x00;
if(AFE_Write(REG_ADDR_FLAG1,1,&temp) == 0) //清空AFE标志位
{
temp = 0x80;
if(AFE_Write(REG_ADDR_SCONF2,1,&temp) == 0) //继续允许MCU清零标志位
{
bmsMem.bStatus1 &= ~BIT5; //浪涌短路保护标志释放(只有2步都成功后才真正清除和释放)
sc_close_flag = 0;
}
}
}
//充放电MOS故障监测
if((bmsMem.bStatus3 & 0x01) == 0) //放电MOS是关闭状态
{
//当出现MOS故障,会主动关闭对应MOS,若此时还有电流,持续报警MOS故障
if((bmsMem.bStatus2 & 0x40) == 0) //还没出现放电MOS故障
{
if(bmsMem.packCurrent < (-2000)) //有放电电流
{
ErrDSGcount++;
if(ErrDSGcount >= 30)
{
bmsMem.bStatus2 |= BIT6; //说明放电MOS故障
}
}
else
{
ErrDSGcount = 0;
}
}
else //已经出现放电MOS故障
{
//当因MOS故障关闭MOS后电流消失,那就消去MOS故障
if(bmsMem.packCurrent > (-100)) //不再是放电电流
{
ErrDSGRelaycount++;
if(ErrDSGRelaycount >= 3)
{
bmsMem.bStatus2 &= ~BIT6; //说明放电MOS正常
}
}
else
{
ErrDSGRelaycount = 0;
}
}
}
else //放电MOS也是开启状态
{
ErrDSGcount = 0;
ErrDSGRelaycount = 0;
bmsMem.bStatus2 &= ~BIT6; //不考虑放电MOS是否故障
}
if(((bmsMem.bStatus3 & 0x02) == 0) && (curLimitFlag == 0)) //充电MOS是关闭状态 //11.7同时判断限流板没开启
{
if((bmsMem.bStatus2 & 0x80) == 0) //还没出现充电MOS故障
{
if(bmsMem.packCurrent > 2000) //有充电电流
{
ErrCHGcount++;
if(ErrCHGcount >= 30)
{
bmsMem.bStatus2 |= BIT7; //说明充电MOS故障
}
}
else
{
ErrCHGcount = 0;
}
}
else //已经出现放电MOS故障
{
if(bmsMem.packCurrent < 100) //不再是充电电流
{
ErrCHGRelaycount++;
if(ErrCHGRelaycount >= 3)
{
bmsMem.bStatus2 &= ~BIT7; //说明放电MOS正常
}
}
else
{
ErrCHGRelaycount = 0;
}
}
}
else
{
ErrCHGcount = 0;
ErrCHGRelaycount = 0;
bmsMem.bStatus2 &= ~BIT7; //说明充电MOS正常
}
//DO执行条件:出现MOS故障
if((bmsMem.bStatus2 & 0xC0) == 0)
{
DO_Off();
bmsMem.temperaStatus &= 0xff7f;
}
else
{
DO_On(); //开启继电器让外部控制
bmsMem.temperaStatus |= 0x0080;
}
/*浪涌短路保护连续出现的计算和锁定*/
//浪涌短路保护释放——无法释放,只能等待自恢复时间8s
//连续出现5次后,直接MCU接管标志位并控制MOS全关
//浪涌短路过程中检测是否真短路
if((bmsMem.balanceStatus & BIT6) != 0)
{
bmsMem.bStatus1 |= 0x0020;
CTRL_Off();
}
else
{
//浪涌短路出现
if((bmsMem.bStatus1 & BIT5) != 0)
{
//刚出现时
if(sc_OccurFlag == 0)
{
sc_OccurFlag = 1;
sc_RepeatDelay = 0;
//分析是否满足锁定条件
if(sc_RepeatFlag == 0) //此前60s内并未出现 (此时重复次数应=0)
{
sc_RepeatFlag = 1; //用于在消失后的计时判断
}
else
{
sc_RepeatCount++; //浪涌短路持续60s不出现的话,sc_OccurFlag会置0,所以这时候存在值1,说明是在60s内出现的,计数次数+1
if(sc_RepeatCount+1 >= paraMem.scWaitNum) //当计数达到4时(即连续发生了五次浪涌短路),直接锁定,"浪涌短路"持续显示,持续关闭MOS
{
sc_RepeatCount = 0;
bmsMem.balanceStatus |= BIT6; //浪涌短路锁定启用,只有重启可清零
}
}
}
}
//浪涌短路消失后
else
{
sc_OccurFlag = 0;
if(TSC_detectFlag != 0xAA)
{
TSC_detectFlag = 0;
}
//浪涌短路出现后又消失,若在60s内监测到浪涌短路不开启则计数恢复0,否则计数+1
if(sc_RepeatFlag == 1)
{
sc_RepeatDelay++;
if(sc_RepeatDelay > paraMem.scWait_T) //持续60s
{
sc_RepeatFlag = 0; //标志置0
sc_RepeatDelay = 0; //倒计时清零
sc_RepeatCount = 0; //连续出现计数清零
}
}
else
{
sc_RepeatDelay = 0;
}
}
}
/*真短路保护连续出现的计算和锁定,和未锁定时的自动释放*/
//真短路保护释放——5min自动解除
//连续出现5次后,直接MCU接管标志位并控制MOS
if((bmsMem.balanceStatus & BIT7) != 0)
{
bmsMem.bStatus2 |= 0x0010;
CTRL_Off();
}
else
{
//5min自动解除
if((bmsMem.bStatus2 & BIT4) != 0)
{
tsc_relaycount++;
if(tsc_relaycount > 300)
{
tsc_relaycount = 0;
TSC_Flag = 0;
TSC_detectFlag = 0;
bmsMem.bStatus2 &= ~BIT4;
CTRL_On(); //释放充放MOS
}
}
//真短路出现
if((bmsMem.bStatus2 & BIT4) != 0)
{
//刚出现时
if(tsc_OccurFlag == 0)
{
tsc_OccurFlag = 1;
tsc_RepeatDelay = 0;
//分析是否满足锁定条件
if(tsc_RepeatFlag == 0) //此前60s内并未出现 (此时重复次数应=0)
{
tsc_RepeatFlag = 1; //用于在消失后的计时判断
}
else
{
tsc_RepeatCount++; //真短路持续60s不出现的话,tsc_OccurFlag会置0,所以这时候存在值1,说明是在60s内出现的,计数次数+1
if(tsc_RepeatCount+1 >= paraMem.scWaitNum) //当计数达到4时(即连续发生了五次真短路),直接锁定,"真短路"持续显示,持续关闭MOS
{
tsc_RepeatCount = 0;
bmsMem.balanceStatus |= BIT7; //真短路锁定用[预充超时失败锁定]标志位启用,只有重启可清零
}
}
}
}
//真短路消失
else
{
tsc_OccurFlag = 0;
//真短路出现后又消失,若在60s内监测到真短路不开启则计数恢复0,否则计数+1
if(tsc_RepeatFlag == 1)
{
tsc_RepeatDelay++;
if(tsc_RepeatDelay > paraMem.scWait_T) //持续60s
{
tsc_RepeatFlag = 0; //标志置0
tsc_RepeatDelay = 0; //倒计时清零
tsc_RepeatCount = 0; //连续出现计数清零
}
}
else
{
tsc_RepeatDelay = 0;
}
}
}
//满充条件4满足后,停止充电
if((paraMem.soc100_methods & 0x08) != 0)
{
if((bmsMem.bStatus1 & 0x0800) == 0) //还没出现满充停充
{
if((bmsMem.packVoltage >= paraMem.soc100_vol*100) && (bmsMem.packCurrent <= paraMem.soc100_cur*100) && (bCHGING == 1))
{
fcc4_count++;
if(fcc4_count >= 3)
{
bmsMem.bStatus1 |= 0x0800; //置标志位,控制MOS关闭
}
}
else
{
fcc4_count = 0;
}
}
else //出现后如果任一对应条件消失,标志释放
{
if((bmsMem.packVoltage < paraMem.soc100_vol*100) || (bmsMem.soc < 96) || (bmsMem.packCurrent < -3000)) //特殊解除项:①SOC<96% ②放电电流>3A
{
fcc4r_count++;
if(fcc4r_count >= 3)
{
bmsMem.bStatus1 &= 0xf7ff; //标志位恢复
}
}
else
{
fcc4r_count = 0;
}
}
}
else
{
bmsMem.bStatus1 &= 0xf7ff;
}
//sum of all packs
bmsMem.can_status_byte1 = bmsMem.bStatus1;
bmsMem.can_status_byte2 = bmsMem.bStatus2;
bmsMem.can_status_byte3 = bmsMem.bStatus3;
bmsMem.can_status_byte4 = bmsMem.temperaStatus; //温度报警判断已在此之前执行
#if Key_PressLong
if((ON_confirm_flg != 0) && (RST_confirm_flg != 1) && (OFF_confirm_flg != 1))
#endif
{
//(过压单独讨论,其他的都在这)
//报警灯亮与报警跳转 //浪涌短路加回来
if(((bmsMem.bStatus1 & 0x067e) != 0) || ((bmsMem.bStatus2 & 0x001f) !=0) || ((bmsMem.bStatus3 & 0x0008) !=0) || ((bmsMem.temperaStatus & 0x0f3f) !=0))
{
if(sleep_flag == 0) LED_ALARM_On();
else LED_ALARM_Off();
}
//只亮报警灯
else if(((bmsMem.bStatus2 & 0x00e0) !=0) || ((bmsMem.temperaStatus & 0x0040) !=0) || ((bmsMem.balanceStatus & BIT6) != 0)) //BIT6.7-放电MOS故障、充电MOS故障、预充失败、急停 (不在屏幕上) //浪涌短路锁定亮灯
{
if(sleep_flag == 0) LED_ALARM_On();
else LED_ALARM_Off();
}
//报警灯灭
else
{
//若出现总体过压|单体过压,则不恢复原状,等待之后的判断
if((bmsMem.bStatus1 & 0x0101) == 0)
{
LED_ALARM_Off();
}
}
//主机屏幕报警页跳转判断(所有保护)
if(((bmsMem.bStatus1 & 0x077f) != 0) || ((bmsMem.bStatus2 & 0x001f) !=0) || ((bmsMem.bStatus3 & 0x0008) !=0) || ((bmsMem.temperaStatus & 0x0f3f) !=0))
{
bAlarmFlag = 1;
}
else
{
bAlarmFlag = 0;
bAlarmFlagOld = 0;
}
}
//soe记录判断
soe.bsNew[0] = bmsMem.bStatus1 & 0xff;
soe.bsNew[1] = bmsMem.bStatus2 & 0xff;
soe.bsNew[2] = bmsMem.bStatus3 & 0xff;
soe.bsNew[3] = bmsMem.temperaStatus & 0xff;
soe.bsNew[4] = bmsMem.balanceStatus & 0xff;
soe.bsNew[5] = ((bmsMem.bStatus1>>4) & 0xf0) | ((bmsMem.temperaStatus>>8) & 0x0f); //占用原packStatus位置,保存新增保护
//电压报警备份 //原来是正常状态 VS 已经出现报警
//单体过压
if((soe.bsOld[0] & 0x01) == 0)
{
if((soe.bsNew[0] & 0x01) != 0) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[0] & 0x01) == 0) //没有报警,上次清除
{
soe.bsOld[0] &= 0XFE; //~0X01
}
}
//单体欠压
if((soe.bsOld[0] & 0x02) == 0)
{
if((soe.bsNew[0] & 0x02) != 0) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[0] & 0x02) == 0) //没有报警,上次清除
{
soe.bsOld[0] &= 0XFD; //~0X02
}
}
//总体过压
if((soe.bsOld[5] & 0x10) == 0)
{
if((soe.bsNew[5] & 0x10) != 0) //报警触发
{
soe.bsOld[5] = soe.bsNew[5]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[5] & 0x10) == 0) //没有报警,上次清除
{
soe.bsOld[5] &= 0XEF; //~0X10
}
}
//总体欠压
if((soe.bsOld[5] & 0x20) == 0)
{
if((soe.bsNew[5] & 0x20) != 0) //报警触发
{
soe.bsOld[5] = soe.bsNew[5]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[5] & 0x20) == 0) //没有报警,上次清除
{
soe.bsOld[5] &= 0XDF; //~0X20
}
}
//异常高压
if((soe.bsOld[0] & 0x40) == 0)
{
if((soe.bsNew[0] & 0x40) != 0) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[0] & 0x40) == 0) //没有报警,上次清除
{
soe.bsOld[0] &= 0XBF; //~0X40
}
}
//低电压禁止充电
if((soe.bsOld[2] & 0x08) == 0)
{
if((soe.bsNew[2] & 0x08) != 0) //报警触发
{
soe.bsOld[2] = soe.bsNew[2]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[2] & 0x08) == 0) //没有报警,上次清除
{
soe.bsOld[2] &= 0XF7; //~0X08
}
}
//电流报警备份
//充电过流
if(((soe.bsOld[0] & 0x10) == 0) && ((soe.bsOld[3] & 0x10) == 0))
{
if(((soe.bsNew[0] & 0x10) != 0) || ((soe.bsNew[3] & 0x10) != 0)) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[0] & 0x10) == 0) && ((soe.bsNew[3] & 0x10) == 0)) //没有报警,上次清除
{
soe.bsOld[0] &= 0XEF; //~0X10
soe.bsOld[3] &= 0XEF; //~0X10
}
}
//放电过流1
if(((soe.bsOld[0] & 0x04) == 0) && ((soe.bsOld[3] & 0x20) == 0))
{
if(((soe.bsNew[0] & 0x04) != 0) || ((soe.bsNew[3] & 0x20) != 0)) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[0] & 0x04) == 0) && ((soe.bsNew[3] & 0x20) == 0)) //没有报警,上次清除
{
soe.bsOld[0] &= 0XFB; //~0x04
soe.bsOld[3] &= 0XDF; //~0x20
}
}
//放电过流2
if(((soe.bsOld[0] & 0x08) == 0) && ((soe.bsOld[5] & 0x40) == 0))
{
if(((soe.bsNew[0] & 0x08) != 0) || ((soe.bsNew[5] & 0x40) != 0)) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bsOld[5] = soe.bsNew[5];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[0] & 0x08) == 0) && ((soe.bsNew[5] & 0x40) == 0)) //没有报警,上次清除
{
soe.bsOld[0] &= 0XF7; //~0x08
soe.bsOld[5] &= 0XBF; //~0x40
}
}
//浪涌短路
if((soe.bsOld[0] & 0x20) == 0)
{
if((soe.bsNew[0] & 0x20) != 0) //报警触发
{
soe.bsOld[0] = soe.bsNew[0]; //如果已经执行记录,就不会再执行
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[0] & 0x20) == 0) //没有报警,上次清除
{
soe.bsOld[0] &= 0XDF; //~0X20
}
}
//真短路
if(((soe.bsOld[1] & 0x10) ==0))
{
if((soe.bsNew[1] & 0x10) != 0)
{
soe.bsOld[1] = soe.bsNew[1];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[1] & 0x10) == 0)
{
soe.bsOld[1] &= 0XEF; //~0X10
}
}
//温度报警备份
//充电高温
if(((soe.bsOld[1] & 0x02) == 0) && ((soe.bsOld[3] & 0x01) == 0) && ((soe.bsOld[5] & 0x01) == 0))
{
if(((soe.bsNew[1] & 0x02) !=0) || ((soe.bsNew[3] & 0x01) !=0) || ((soe.bsNew[5] & 0x01) !=0))
{
soe.bsOld[1] = soe.bsNew[1]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bsOld[5] = soe.bsNew[5];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[1] & 0x02) ==0) && ((soe.bsNew[3] & 0x01) ==0) && ((soe.bsNew[5] & 0x01) ==0))
{
soe.bsOld[1] &= 0XFD; //~0x02
soe.bsOld[3] &= 0XFE; //~0x01
soe.bsOld[5] &= 0XFE; //~0x01
}
}
//放电高温
if(((soe.bsOld[1] & 0x08) == 0) && ((soe.bsOld[3] & 0x02) == 0) && ((soe.bsOld[5] & 0x02) == 0))
{
if(((soe.bsNew[1] & 0x08) !=0) || ((soe.bsNew[3] & 0x02) !=0) || ((soe.bsNew[5] & 0x02) !=0))
{
soe.bsOld[1] = soe.bsNew[1]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bsOld[5] = soe.bsNew[5];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[1] & 0x08) ==0) && ((soe.bsNew[3] & 0x02) ==0) && ((soe.bsNew[5] & 0x02) ==0))
{
soe.bsOld[1] &= 0XF7; //~0x08
soe.bsOld[3] &= 0XFD; //~0x02
soe.bsOld[5] &= 0XFD; //~0x02
}
}
//充电低温
if(((soe.bsOld[1] & 0x01) == 0) && ((soe.bsOld[3] & 0x04) == 0) && ((soe.bsOld[5] & 0x04) == 0))
{
if(((soe.bsNew[1] & 0x01) !=0) || ((soe.bsNew[3] & 0x04) !=0) || ((soe.bsNew[5] & 0x04) !=0))
{
soe.bsOld[1] = soe.bsNew[1]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bsOld[5] = soe.bsNew[5];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if(((soe.bsNew[1] & 0x01) ==0) && ((soe.bsNew[3] & 0x04) ==0) && ((soe.bsNew[5] & 0x04) ==0))
{
soe.bsOld[1] &= 0XFE; //~0x01
soe.bsOld[3] &= 0XFB; //~0x04
soe.bsOld[5] &= 0XFB; //~0x04
}
}
//放电低温
if(((soe.bsOld[1] & 0x04) == 0) && ((soe.bsOld[3] & 0x08) == 0) && ((soe.bsOld[5] & 0x08) == 0))
{
if(((soe.bsNew[1] & 0x04) !=0) || ((soe.bsNew[3] & 0x08) !=0) || ((soe.bsNew[5] & 0x08) !=0))
{
soe.bsOld[1] = soe.bsNew[1]; //如果已经执行记录,就不会再执行
soe.bsOld[3] = soe.bsNew[3];
soe.bsOld[5] = soe.bsNew[5];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if( ((soe.bsNew[1] & 0x04) ==0) && ((soe.bsNew[3] & 0x08) ==0) && ((soe.bsNew[5] & 0x08) ==0))
{
soe.bsOld[1] &= 0XFB; //~0x04
soe.bsOld[3] &= 0XF7; //~0x08
soe.bsOld[5] &= 0XF7; //~0x08
}
}
//DI-急停
if( ((soe.bsOld[3] & 0x40) ==0) )
{
if((soe.bsNew[3] & 0x40) != 0)
{
soe.bsOld[3] = soe.bsNew[3];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[3] & 0x40) == 0)
{
soe.bsOld[3] &= 0XBF; //~0X40
}
}
//故障
//放电MOS故障
if( ((soe.bsOld[1] & 0x40) ==0) )
{
if((soe.bsNew[1] & 0x40) != 0)
{
soe.bsOld[1] = soe.bsNew[1];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[1] & 0x40) == 0)
{
soe.bsOld[1] &= 0XBF; //~0X40
}
}
//充电MOS故障
if( ((soe.bsOld[1] & 0x80) ==0) )
{
if((soe.bsNew[1] & 0x80) != 0)
{
soe.bsOld[1] = soe.bsNew[1];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[1] & 0x80) == 0)
{
soe.bsOld[1] &= 0X7F; //~0X80
}
}
//预充失败
if( ((soe.bsOld[1] & 0x20) ==0) )
{
if((soe.bsNew[1] & 0x20) != 0)
{
soe.bsOld[1] = soe.bsNew[1];
soe.bkType = BKTYPE_ALARM;
}
}
else
{
if((soe.bsNew[1] & 0x20) == 0)
{
soe.bsOld[1] &= 0XDF; //~0X20
}
}
if(soe.bkType !=0) //当出现情况,进行记录
{
SOE_BkData(soe.bkType); //函数内部清除BKTYPE标记
}
}