This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] BQ27441EVM-G1A:块数据校验和始终为0

Guru**** 2322270 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/595316/bq27441evm-g1a-block-data-checksum-is-always-0

器件型号:BQ27441EVM-G1A

我正在尝试更新标称电池容量、一切正常、但当我请求地址0x60获取当前校验和时、我始终返回0。 (请注意、由于编程限制、我请求2个字节)。 如果没有此校验和、我将无法计算新的校验和、因此无法更新电池容量。  

出什么问题了? 我可以自己计算校验和吗?

我的代码如下。 我获取校验和的部分在第204行附近。

/*
FuelGaug.c
*
*创建日期:2017年1月6日
* 作者:amorg
*/

// BQ27441库
#include 
//电量监测计包括
#include 
//驱动程序库
#include 
//标准库包括
#include 
#include 

//全局变量
int NUM_OF_REC_Bytes = 0; //保留从电量监测
计 uint8_t RXData[maxNumOfRXBytes]接收的字节数; //从电量监测
计易失性 uint8_t rxFlag = 0接收到的无符号8位命令数组; //接收中断标记
静态易失性 uint32_t xferIndex; // RXData INDEX

// I2C 主配置参数
const eUSCI_I2C_MasterConfig i2cConfig =
{
EUSCI_B_I2C_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
80000、 // SMCLK = 8MHz
EUSCI_B_I2C_SET_DATA_RATE 100KBPS、 //所需的100kHz I2C 时钟
0、 //无字节计数器阈值
EUSCI_B_I2C_NO_AUTO_STOP //无自动停止
};

void FuelGauge_Setup()
{
//为 I2C 选择端口6 -将引脚4、5设置为输入主模块功能(UCB1SIMO/UCB1SDA、UCB1SOMI/UCB.S)。
#if SDApin =GPIO_PIN6 && I2Cport =GPIO_PORT_P6
MAP_GPIO_setPeripheralModuleFunctionInputPin (I2Cport、SDApin + SCLpin、GPIO_secondary 模块_function);
#else
MAP_GPIO_setPeripheralModuleFunctionInputPin (I2Cport、SDApin + SCLpin、GPIO_PRIMARY_MODULE_Function);
#endif
//以100kbs 的速率将 I2C 主设备初始化为 SMCLK,而不自动停止
MAP_I2C_initMaster (EUSCI_MODULE、&i2cConfig);

//指定从机地址
MAP_I2C_setSlaveAddress (EUSCI_MODULE、BQ27441_I2C_ADDRESS);

//将主机设置为发送模式
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Transmit 模式);

//启用 I2C 模块以启动操作
MAP_I2C_enableModule (EUSCI_MODULE);

//启用和清除中断标志,以便在定义页中产生发送中断
MAP_I2C_clearInterruptFlag (EUSCI_MODULE、EUSCI_B_I2C_Transmit INTERRUPT0 + EUSCI_B_I2C_Receive_INTERRUPT0);

//启用主机接收中断
MAP_Interrupt_enableInterrupt (EUSCI_moduleINT);
}

void getStatus(){
int REDO = 0;
//获取设备状态
//------ 发送---
执行{
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
REDO += MAP_I2C_masterSendMultiByteStartWithTimeout (EUSCI_MODULE、BQ27441_COMMAND_CONTROL、1000);
REDO += MAP_I2C_masterSendMultiByteNextWithTimeout (EUSCI_MODULE、BQ27441_CONTRAL_STATUS、1000);
REDO += MAP_I2C_masterSendMultiByteNextWithTimeout (EUSCI_MODULE、0x00、1000);
REDO += MAP_I2C_masterSendMultiByteStopWithTimeout (EUSCI_MODULE、1000);
}while (REDO!= 4);

//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
}

void getFlags(){
//获取电流标志寄存器
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_FLAGS); //发送要读取的字节(低字节)

//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
}

void setUpdateMode(){
//设置配置更新模式
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、BQ27441_CONTRAL_SET_CFGUPDATE);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x00);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

//确保启用 CFGUPMODE。 可能最多需要1秒
while (1) //TODO 不良做法 //使用 flags()(0x06)轮询 Flags(Flags 寄存器,直到
{ // CFG_MODE 标志为高电平
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_FLAGS); //发送要读取的字节(低字节)

//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
if ((((RXData[0]& BQ27441_FLAG_CFGUPMODE)>> 4)=1) break; //检查 CFG 模式标志
}

}

void getDeviceType(){
//get 设备类型(0X0421)
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、BQ27441_CONTRAL_DEVICE_TYPE);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x00);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、0x00);

//------ 接收--- //******** 注释*********
num_of _REC_bytes = 2; // NUM_OF_REC_Bytes 只接受2或更大的值
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
}

//TODO 在出现故障时退出
FuelGauge_SetBatteryCap (uint16_t batCap)
{
////模块重置
// EUSCI_TXBuffer &= 0x00; //清除发送缓冲
器// map_I2C_masterSendMultiByteStart (eUSCI_MODULE、BQ27441_COMMAND_CONTROL);
// map_I2C_masterSendMultiByteNext (eUSCI_MODULE、BQ27441_CONTRAL_RESET);
// map_I2C_masterSendMultiByteNext (eUSCI_MODULE、 0x00);
// map_I2C_masterSendMultiByteStop (eUSCI_MODULE);


//------ 发送---
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、0x0A);
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;


getStatus();
getFlags();
setUpdateMode();


//启用块数据存储器控制(启用 RAM 访问)
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_extend_control);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x00);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

//访问状态子类
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_DELEDAND_DATACLASS);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x52);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

//设置要访问的数据锁
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_extend_DATABLOCK);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x00);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

//发送块校验和命令以检查校验和
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_extended_CHECKSUM);

//TODO 接收校验和、应为1个字节。 似乎没有收到这一信息。
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
uint8_t OLD_CSUM = RXData[1]; //存储用于计算的旧校验和值

//TODO 我们应该只读取2个字节而不是32个字节。 根据手册、我们只需从2获取电池数据、我们就不必读取整个块
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、0x4A);//BQ27441_DELOCKDATA); //命令返回一个32字节的内存块

//------ 接收---
num_of _REC_bytes = 2;//32; //设置为接收32个字节
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
uint8_t OLD_DESCap_MSB = RXData[0]; //存储旧电池容量最高有效字节值以进行计算
uint8_t OLD_DESCap_LSB = RXData[1];


///------------------------------
uint8_t batCap_msb = batCap >> 8; //将输入 batCap 向右移动8位以获取 MSByte
uint8_t batCap_LSB = batCap; //截断 batCap 以获取 LSByte

//设置新的电池电量
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、0x4A); //存储电池容量 MSByte 的存储器位置
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、batCap_MSB); //这样做实际上不会设置电池容量,只需将其设置为它的样子!!!! 用于 Bat 容量的新 MSByte
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、0x4B); //存储电池容量 LSByte 的存储器位置
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、batCap_LSB); //这样做实际上不会设置电池容量,只需将其设置为它的样子!!!! 用于 Bat 容量的新 LSByte
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

//计算新校验和
//too 您应该能够在不获取所有字节的情况下执行此操作、仅获取替换的字节。
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_extended_BLOCKDATA); //命令返回一个32字节的内存块

//------ 接收---
num_of _REC_bytes = 32; //设置为接收32个字节
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;

///------------------------------
uint8_t temp =(255 - old_CSUM - old_DESCap_MSB - old_DESCap_LSB)% 256; //计算新校验和
uint8_t new_CSUM = 255 -(temp + batCap_MSB + batCap_LSB)% 256);

//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_extended_CHECKSUM);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、NEW _CSUM);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

getStatus();
getFlags();

//软复位
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendMultiByteStart (EUSCI_MODULE、BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、BQ27441_CONTRAL_SOFT_RESET);
MAP_I2C_masterSendMultiByteNext (EUSCI_MODULE、0x00);
MAP_I2C_masterSendMultiByteStop (EUSCI_MODULE);

while (1) //使用 flags()(0x06)轮询 Flags(Flags 寄存器,直到
{ // CFG_MODE 标志为高电平
//------ 发送---
EUSCI_TXBuffer &= 0x00; //清除发送缓冲区
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_FLAGS);

//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;
if ((((RXData[0]& BQ27441_FLAG_CFGUPMODE)>> 4)=0) break; //检查 CFG 模式标志
}

getStatus();
getFlags();
}

int FuelGauge_GetBatteryCap (void)
{
//------ 发送---
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、0x08);
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;

//------ 发送---
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_FUL_Capacity);
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;

uint8_t batCap_LSB = RXData[0];
uint16_t batCap_MSB = RXData[1];
uint16_t out =(batCap_MSB << 8)| batCap_LSB;
返回;
}

int FuelGauge_GetStateOfCharge (void)
{
//------ 发送---
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_SOC);
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;

uint8_t CHARGE_LSB = RXData[0];
uint16_t CHARGE_MSB = RXData[1];
uint16_t out =(CHARGE_MSB << 8)| CHARGE_LSB;
返回;
}

int FuelGauge_GetVoltage (void)
{
//------ 发送---
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte (EUSCI_MODULE、BQ27441_COMMAND_VOLTAGE);
//------ 接收---
num_of _REC_bytes = 2;
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Receive_mode); //设置为接收模式
MAP_I2C_masterReceiveStart (EUSCI_MODULE); //开始接收
MAP_I2C_enableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //启用接收中断
xferIndex = 0; //将 RXData 索引设置为0
while (rxFlag!= 1); //等待接收到接收中断标志
rxFlag = 0;

uint8_t VOLTGE_LSB = RXData[0];
uint16_t VOLTGE_MSB = RXData[1];
uint16_t out =(VOLTGE_MSB << 8)| VOLTGE_LSB;
返回;
}

void EUSCIB3_Receive (void)
{
uint_fast16_t status; //标志状态

= MAP_I2C_getEnabledInterruptStatus (EUSCI_MODULE); //抓取触发
的任何标志 MAP_I2C_clearInterruptFlag (EUSCI_MODULE、STATUS); //清除被触发的中断标志

IF (STATUS & EUSCI_B_I2C_Receive_INTERRUPT0) //如果接收的中断标志已经被触发
{
if (NUM_OF_REC_Bytes > 1) //如果接收字节数设置为大于1的值
{
if (xferIndex = NUM_OF_REC_Bytes - 2) //当 xferIndex 位于第三个到最后一个字节上时
{
MAP_I2C_masterReceiveMultiByteStop (EUSCI_MODULE);
RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_MODULE); //接收字节并将字节存储到 RXData
}
否则、如果(xferIndex = NUM_OF_REC_Bytes - 1) //当 xferIndex 位于第二个到最后一个字节上时
{
RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_MODULE); //接收字节并将字节存储到 RXData 中
MAP_I2C_DisableInterrupt (EUSCI_MODULE、EUSCI_B_I2C_Receive_INTERRUPT0); //禁用接收中断
MAP_I2C_setMode (EUSCI_MODULE、EUSCI_B_I2C_Transmit 模式); //将 I2C 模式设置为发送
xferIndex = 0; //清除 RXData 索引
rxFlag = 1; //将接收中断标志置为高电平
num_of _REC_bytes = 0; //清除 NUM_OF_REC_Bytes
}
其他 //执行直到 xferIndex 在距 NUM_OF_REC_Bytes 长度2的范围内
{
RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_MODULE);
}
}



}