主题中讨论的其他器件: BQ76920、 BQ76930、 MSP430F247
您好!
我正在设计 BMS 板固件、使用 mspf247作为主 MCU、使用 bq76940作为 AFE 来监控电池。 这两个器件之间的通信接口是 I2C。
困扰我的是每个新 PCBA 板在首次上电时、都正确读取了串联电池电压、电池组电压。
运行一段时间后、读数将被打乱。 和后续调试显示数据读取不正确。
基本编程逻辑是配置 bq76940持续监控电池电压、定期电池组电压、警报信号将每250ms 触发一次中断、
在 ISR 例程中设置相应的标志。
在任务中、将读取电压和库仑。
下面 、我提出了一些代码供参考、
void I2C_Initialize()
{
UCB0CTL1 |= UCSSEL_2+UCSWRST;//启用软件复位,使用 SMCLK 作为 USCI 时钟源
//UCB0CTL1 |= UCSSEL_1+UCSWRST;//启用软件复位,使用 ACLK 作为 USCI 时钟源
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;//设置为 I2C 主控模式
UCB0BR0 = 10;// 92.16KHz @0.9216MHz 的 SCLK、确保 SCLK 不超过100KHz
UCB0BR1 = 0;
UCB0I2CIE = 0;//禁用 NACK、检测到停止条件、检测到启动条件、仲裁丢失中断
IE2 &=~(UCB0TXIE + UCB0RXIE);//禁用 Tx&Rx 中断
UCB0CTL1 &=~UCSWRST;//从复位状态释放
bqI2CError = false;//清除 i2c 故障错误标志
bqI2CStatusReadError = NO_ACTIVICE_INASIONY_STATUS_4;
}
// 76940初始化
空 BqInitializeqMaximo (空)
{
uint16_t count = 0;
bqCoulomb = 0;
bqTotalCoulomb = 0;
bqBalanceIndex = 0;
RAM_CELL_Balance=bqBalanceIndex;
//BQ76920/BQ76930/BQ76940从"发运至正常"转换至"首次读取操作"需要250ms/400ms/800ms、数据表、第21页。
///ALERT 将在船至正常转换后大约990ms 内设置。
//保持此处以设置警报。
while (true)
{
DELAY_1ms (1);
count++;
if (BqIsAlert()=true)
{
中断;
}
其他
{
if (计数>= 1200)
{
///MCU 已通电、但未设置 In 1s 警报...错误
中断;
}
}
}
//虚拟写入命令到 BQ
BqSetRegisterByte (SYS_STAT、0xff);//清除 ALERT
//t=BqGetRegisterByte (SYS_STAT);
//将 CC_CFG 设置为建议值0x19
//t=BqGetRegisterByte (CC_CFG);
BqSetRegisterByte (CC_CFG、0x19);
//t=BqGetRegisterByte (CC_CFG);
//读取 ADC 增益和偏移
bqAdcGain = BqGetAdcGain ();
bqAdcOffset = BqGetRegisterByte (ADCOFFSET);
//根据阈值设置和增益+偏移信息设置 OV_TRIP 和 UV_TRIP
OVPThreshold = logic.regbyte_ov_Trip;
BqSetRegisterByte (OV_TRIP、BqTripConversion (OVPThreshold、bqAdcGain、bqAdcOffset));
//t=BqGetRegisterByte (OV_TRIP);
UVPThreshold = logic.regbyte_uV_TRIP;
BqSetRegisterByte (UV_TRIP、BqTripConversion (UVPThreshold、bqAdcGain、bqAdcOffset));
//t=BqGetRegisterByte (uV_TRIP);
//设置保护
//SCD
regPROTECt1_t protect1;
protect1.Protect1BIT.scd_delay = SCDDelay;
protect1.Protect1BIT.SCD_THRESH = SCDThresh;
protect1.Protect1Bit.RSNS=1;
BqSetRegisterByte (PROTECT1、protect1.Protect1Byte);
//t=BqGetRegisterByte (PROTECT1);
//OCD
regPROTECT2_t protect2;
protect2.Protect2bit。ocd_delay = OCDDelay;
protect2.Protect2bit。ocd_thresh = OCDThresh;
BqSetRegisterByte (PROTECT2、protect2.Protect2Byte);
//t=BqGetRegisterByte (PROTECT2);
//OVDelay、UVDelay
regPROTECT3_t protect3;
protect3.Protect3Bit.OV_delay = OVDelay;
protect3.Protect3Bit.uV_delay = UVDelay;
BqSetRegisterByte (PROTECT3、protect3.Protect3Byte);
//t=BqGetRegisterByte (PROTECT3);
//设置系统控件
regSYS_CTRL1_t ctrl1;
ctrl1.SysCtrl1BIT.ADC_EN = logic.regbit_ADC_en;
ctrl1.SysCtrl1BIT.load_present = 0;//只读位
ctrl1.SysCtrl1BIT.shut_a = 0;//不要进入运输模式
ctrl1.SysCtrl1BIT.shut_B = 0;//不要进入运输模式
ctrl1.SysCtrl1BIT.TEMP_SEL = logic.regbit_temp_SEL;//External热 敏电阻;//0 =芯片温度;1 =热敏电阻温度
BqSetRegisterByte (SYS_CTRL1、ctrl1.SysCtrl1Byte);
//t=BqGetRegisterByte (SYS_CTRL1);
regSYS_CTRL2_t ctrl2;
ctrl2.SysCtrl2BIT.CC_EN = logic.regbyte_sys_ctrl2.SysCtrl2BIT.CC_EN;//0 =禁用连续读取;1 =启用
ctrl2.SysCtrl2Bit.CC_OneShot = 0;//0 =无操作;1 =触发单次读取
ctrl2.SysCtrl2bit。delay_DIS = 0;//0 =正常延迟;1 =无延迟(250ms)
ctrl2.SysCtrl2BIT.CHG_ON = 0;// 0 = CHG FET 关闭;1= CHG FET 打开
ctrl2.SysCtrl2BIT.DSG_ON = 0;//0 = DSG FET 关闭;1 = DSG FET 关闭
/ctrl2.SysCtrl2bit。WAKE_EN = 0;// BQ76930中不存在
/ctrl2.SysCtrl2BIT.WAKE_T =0;// BQ76930中不存在
BqSetRegisterByte (SYS_CTRL2、ctrl2.SysCtrl2Byte);//初始化时关闭 chg 和 DSG
//t=BqGetRegisterByte (SYS_CTRL2);
regSYS_STAT_t 状态;
STATUS.StatusByte = BqGetRegisterByte (SYS_STAT);
if (STATUS.STATUSByte 和 STAT_FLAGS)
{
//由于某种原因设置了设备状态标志,请将其清除。
BqSetRegisterByte (SYS_STAT、STAT_FLAGS);
}
}
#pragma vector=Port1_vector
_interrupt void ISR_PORT_1 (void)
{
中频(P1IFG 和 BIT5)
{
//读取 SYS_STAT 字节
bqI2CError = no_significance;
bqStatus.StatusByte = BqGetRegisterByte (SYS_STAT);
bqI2CStatusReadError = bqI2CError;
BqSetRegisterByte (SYS_STAT、STAT_CC_READY);
P1IFG &=~BIT4;//清除中断标志
}
}
void Taska (空)
{
uint8_t i;
静态 uint16_t TIME_OUT_COUNTER = 0;
TIME_OUT_COUNTER++;
if (bqI2CStatusReadError =false || TIME_OUT_COUNTER >100)
{
if (bqStatus.StatusBit.DEVICE_XREADY =true)
{
//此故障数据不可信任
FAULT.BQ.bit.XREADY = true;
}
其他
{
// 250ms 周期完成
if (bqStatus.StatusBit.CC_READY = true)
{
//读取库仑计数器
int32_t cur;
int16_t tmp;
tmp = BqGetCoulombCounter();
if (bqI2CError == false)
{
bqCoulomb =温度;
bqTotalCoulomb += bqCoulomb;
//此处计算电流,BQ 电流>0 -充电
CUR=(Int16_t)((bqCoulomb*8.44)/(Rsense));// 1uA 单元
CUR=(-cur/100000);//单位0.01A
RAM_Shunt_I=cur;
}
其他
{
//I2C 错误
FAULT.BQ.bit.i2c =真;
}
//读取电池电压
uint16_t min=65535、max=0;
for (i=0;<NUMBER_OF_CELLS;i++)
{
tmp = BqGetCellVoltage (I+1);
if (bqI2CError == false)
{
RAM_Vol_Cell[i]= tmp;
IF (RAM_Vol_Cell[i]<min)
{
MIN=RAM_VolT_Cell[i];
LowestCellIndex = I;
}
IF (RAM_Vol_Cell[I]>max)
Max=RAM_Vol_Cell[i];
}
其他
{
//I2C 错误
FAULT.BQ.bit.i2c =真;
}
}
RAM_HighestVol=最大值;
RAM_LowestVol=最小值;
IF (RAM_HighestVolt > RAM_MaxVolt)
{
RAM_MaxVolt = RAM_HighestVolt;
}
IF (RAM_LowestVolt < RAM_MinVolt)
{
RAM_MINVolt = RAM_LowestVolt;
}
如果(!(Flag_Work&Flag_After1rstReadVolt))
{
flag_work |=Flag_After1rstReadVolt;
SoC_FirstDataAvailable((U16*) RAM_Vol_Cell);
}
//读取电池组电压
tmp = BqGetPackVoltage();
if (bqI2CError == false)
{
bqPackVoltage = tmp;
RAM_SUM_Cells = tmp;
}