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.

BQ27427: 基于STM32的电量计驱动与SOC读取

Part Number: BQ27427
Other Parts Discussed in Thread: EV2400,

您好,我使用了I2C进行自制电路板上stm32与电量计芯片的通信,硬件电路是参考的技术手册电路图,指令、寄存器有正常的ack响应,初始化后循环读取SOC0x1c),发现只会出两种数值:没电的时候接上充电器开机可读出0,充一会电后就直接变成99,然后就一直是99,也到不了100,直到没电,我目前在初始化中配置了Design_Capacity, Design_Energy, Terminate_Voltage, Taper_Rate, Dsg_Current_Threshold, Chg_Current_Threshold, Quit_Current这些参数,并直接设置了ChemIDChem_B0x31)。目前还没购买ev2400,没进行充放电周期学习,电量读取可能不准,但正常应该也不会出现这样的现象。由于是第一次用,不太在行,麻烦大佬帮忙解答一下我会是哪个地方出错了呀?不胜感激。

代码如下:

#define BQ27427_ADDR (0x55 << 1)

#define BQ27427_ADDR_W 0xAA
#define BQ27427_ADDR_R 0xAB
#define CMD_CONTROL 0x00

#define UNSEAL_KEY 0x8000
#define SEAL_KEY 0x0020
#define SET_CFGUPDATE 0x0013
#define SOFT_RESET 0x0042
#define BAT_INSERT 0x000c
#define CHEM_ID 0x0008

#define Data_Block_Class 0x3E
#define Data_Block 0x3F

#define Dsg_Current_Threshold 0x40
#define Chg_Current_Threshold 0x42
#define Quit_Current 0x44

#define Design_Capacity 0x46
#define Design_Energy 0x48
#define Terminate_Voltage 0x4A
#define Taper_Rate 0x55
#define Block_Data_Checksum 0x60
#define Block_Data_Control 0x61


#define CMD_TEMPERATURE 0x02
#define CMD_VOLTAGE 0x04
#define CMD_FLAGS 0x06
#define NominalAvailableCapacity 0x08
#define FullAvailableCapacity 0x0A
#define CMD_STATE_OF_CHARGE 0x1C

#define CHEM_A 0x30
#define CHEM_B 0x31
#define CHEM_C 0x32

#define BQ27427_sendCmd(cmd) \
do { \
uint8_t _buf[2] = { (uint8_t)((cmd) & 0xFF), (uint8_t)(((cmd) >> 8) & 0xFF) }; \
BQ27427_Write(CMD_CONTROL, _buf, 2); \
} while (0)

uint16_t BQ27427_ReadSOC(void);
HAL_StatusTypeDef BQ27427_Set(uint8_t chem, uint16_t mAh, uint16_t NmV, uint16_t mV);
HAL_StatusTypeDef BQ27427_Chem(uint16_t chem);

 

static HAL_StatusTypeDef BQ27427_Write(uint8_t com, const uint8_t *data, uint8_t len) {

return HAL_I2C_Mem_Write(&hi2c1, BQ27427_ADDR, com, I2C_MEMADD_SIZE_8BIT, (uint8_t*)data, len, HAL_MAX_DELAY);


}

static uint16_t BQ27427_Read(uint16_t com) {

uint8_t data[2];
uint16_t receive;

if (HAL_I2C_Mem_Read(&hi2c1, BQ27427_ADDR, com, I2C_MEMADD_SIZE_8BIT, data, 2, HAL_MAX_DELAY) != HAL_OK) {
receive = 0xFFFF;
} else {
receive = (data[1] << 8) | data[0];
}
return receive;

}

static HAL_StatusTypeDef BQ27427_ReadInternal(uint8_t com, uint8_t *aTxBuffer, uint8_t len){
return HAL_I2C_Mem_Read(&hi2c1, BQ27427_ADDR, com, I2C_MEMADD_SIZE_8BIT, aTxBuffer, len, HAL_MAX_DELAY);
}

uint16_t BQ27427_ReadFlags() {
return BQ27427_Read(0x0706);
}

static HAL_StatusTypeDef BQ27427_selectDataBlock(uint8_t blockClass, uint8_t offset){
HAL_StatusTypeDef ret;
ret = BQ27427_Write(Block_Data_Control, (uint8_t[]){0x00}, 1);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Data_Block_Class, &blockClass, 1);
if (ret != HAL_OK) return ret;
return BQ27427_Write(Data_Block, &offset, 1);
}

static uint8_t BQ27427_calcChecksum(uint8_t oldCsum, uint8_t old_msb_DC, uint8_t old_lsb_DC, uint8_t old_msb_CTTC, uint8_t old_lsb_CTTC, uint8_t old_msb_DCT, uint8_t old_lsb_DCT, uint8_t old_msb_CCT, uint8_t old_lsb_CCT, uint8_t old_msb_QC, uint8_t old_lsb_QC, uint8_t old_msb_mWh, uint8_t old_lsb_mWh, uint8_t old_msb_TV, uint8_t old_lsb_TV, uint8_t msb_DC, uint8_t lsb_DC, uint8_t msb_CTTC, uint8_t lsb_CTTC, uint8_t msb_DCT, uint8_t lsb_DCT, uint8_t msb_CCT, uint8_t lsb_CCT, uint8_t msb_QC, uint8_t lsb_QC, uint8_t msb_TV, uint8_t lsb_TV, uint8_t msb_mWh, uint8_t lsb_mWh){
uint8_t old_sum = (0xFF - oldCsum) & 0xFF;
uint8_t new_sum = (old_sum - old_msb_DC - old_lsb_DC - old_msb_CTTC - old_lsb_CTTC - old_msb_DCT - old_lsb_DCT - old_msb_CCT - old_lsb_CCT - old_msb_QC - old_lsb_mWh - old_msb_mWh - old_lsb_QC - old_msb_TV - old_lsb_TV + msb_DC + lsb_DC + msb_CTTC + lsb_CTTC + msb_DCT + lsb_DCT + msb_CCT + lsb_CCT + msb_QC + lsb_QC + msb_TV + lsb_TV + msb_mWh + lsb_mWh) & 0xFF;
uint8_t newCsum = (0xFF - new_sum) & 0xFF;

return newCsum;
}

 

uint16_t BQ27427_ReadSOC(void) {

return BQ27427_Read(0x1D1C);

}

 

HAL_StatusTypeDef BQ27427_Chem(uint16_t chem) {

HAL_StatusTypeDef ret;
uint16_t flags;
uint8_t cheim_id;


BQ27427_sendCmd(UNSEAL_KEY);
BQ27427_sendCmd(UNSEAL_KEY);

BQ27427_sendCmd(CHEM_ID);
HAL_Delay(100);
ret =BQ27427_ReadInternal(CMD_CONTROL, &cheim_id, 2);
if (ret != HAL_OK) return ret;

//
进入配置模式
BQ27427_sendCmd(SET_CFGUPDATE);
HAL_Delay(100);

do {
flags = BQ27427_ReadFlags();
} while (!(flags & (1U << 4)));

BQ27427_sendCmd(chem);
HAL_Delay(100);


//
保存配置
BQ27427_sendCmd(SOFT_RESET); // SOFT_RESET

do {
flags = BQ27427_ReadFlags();
} while ((flags & (1U << 4))!=0);


ret = BQ27427_ReadInternal(CMD_CONTROL, &cheim_id, 2);
if (ret != HAL_OK) return ret;

//
重新锁定设备
// BQ27427_Write(SEAL_KEY);

return HAL_OK;
}

HAL_StatusTypeDef BQ27427_Current(uint16_t mAh, uint16_t current) {

uint8_t old_csum, old_lsb_CCT, old_msb_CCT, old_lsb_DCT, old_msb_DCT, old_lsb_QC, old_msb_QC, newCsum, lsb_CCT, msb_CCT, lsb_DCT, msb_DCT, lsb_QC, msb_QC;

uint16_t chg_Current_Thr = mAh / (current*0.1); //
恒流充电电流100mA
lsb_CCT = chg_Current_Thr & 0xFF;
msb_CCT = (chg_Current_Thr >> 8) & 0xFF;
uint16_t dsg_Current_Thr = mAh / (current*0.14*0.1); //
放电电流阈值14mA
lsb_DCT = dsg_Current_Thr & 0xFF;
msb_DCT = (dsg_Current_Thr >> 8) & 0xFF;
uint16_t quit_current = mAh / (current*0.06*0.1); //
待机电流6mA
lsb_QC = quit_current & 0xFF;
msb_QC = (quit_current >> 8) & 0xFF;

HAL_StatusTypeDef ret;
uint16_t flags;
uint8_t cheim_id;


BQ27427_sendCmd(UNSEAL_KEY);
BQ27427_sendCmd(UNSEAL_KEY);

//
进入配置模式
BQ27427_sendCmd(SET_CFGUPDATE);
HAL_Delay(100);

do {
flags = BQ27427_ReadFlags();
} while (!(flags & (1U << 4)));

ret = BQ27427_selectDataBlock(0x51, 0);
if (ret != HAL_OK) return ret;

ret = BQ27427_ReadInternal(Block_Data_Checksum, &old_csum, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Dsg_Current_Threshold, &old_lsb_DCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Dsg_Current_Threshold+1, &old_msb_DCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Chg_Current_Threshold, &old_lsb_CCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Chg_Current_Threshold+1, &old_msb_CCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Quit_Current, &old_lsb_QC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Quit_Current+1, &old_msb_QC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);

ret = BQ27427_Write(Dsg_Current_Threshold, &lsb_DCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Dsg_Current_Threshold+1, &msb_DCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Chg_Current_Threshold, &lsb_CCT, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Chg_Current_Threshold+1, &msb_CCT, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Quit_Current, &lsb_QC, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Quit_Current+1, &msb_QC, 1);
HAL_Delay(100);

newCsum = BQ27427_calcChecksum(old_csum, 0, 0, 0, 0, old_msb_DCT, old_lsb_DCT, old_msb_CCT, old_lsb_CCT, old_msb_QC, old_lsb_QC, 0, 0, 0, 0, 0, 0, 0, 0, msb_DCT, lsb_DCT, msb_CCT, lsb_CCT, msb_QC, lsb_QC, 0, 0, 0, 0);
ret = BQ27427_Write(Block_Data_Checksum,&newCsum, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);

//
保存配置
BQ27427_sendCmd(SOFT_RESET); // SOFT_RESET

do {
flags = BQ27427_ReadFlags();
} while ((flags & (1U << 4))!=0);


ret = BQ27427_ReadInternal(CMD_CONTROL, &cheim_id, 2);
if (ret != HAL_OK) return ret;

//
重新锁定设备
// BQ27427_Write(SEAL_KEY);

return HAL_OK;
}

HAL_StatusTypeDef BQ27427_Set(uint8_t chem, uint16_t mAh, uint16_t NmV, uint16_t mV) //化学ID,设计容量,标称电压,截止电压
{
HAL_StatusTypeDef ret;
uint16_t current = 100; //
充电电流100mA
uint16_t flags;
uint8_t old_csum, old_msb_DC, old_lsb_DC, old_lsb_CTTC, old_msb_CTTC, old_msb_DCT, old_lsb_DCT, old_msb_CCT, old_lsb_CCT, old_msb_QC, old_lsb_QC, old_msb_mWh, old_lsb_mWh, old_msb_TV, old_lsb_TV, msb_DC, lsb_DC, msb_CTTC, lsb_CTTC, msb_DCT, lsb_DCT, msb_CCT, lsb_CCT, msb_QC, lsb_QC, msb_TV, lsb_TV, msb_mWh, lsb_mWh;
lsb_DC = (uint8_t)(mAh & 0xFF);
msb_DC = (uint8_t)((mAh >> 8) & 0xFF);
uint16_t taper_Rate = mAh / (current*0.12*0.1); //
充电结束电流阈值12mA
lsb_CTTC = taper_Rate & 0xFF;
msb_CTTC = (taper_Rate >> 8) & 0xFF;
lsb_TV = mV & 0xFF;
msb_TV = (mV >> 8) & 0xFF;
uint16_t mWh = mAh * NmV / 1000;
lsb_mWh = mWh & 0xFF;
msb_mWh = (mWh >> 8) & 0xFF;
uint8_t newCsum;

BQ27427_Chem(chem);

BQ27427_Current( mAh, current);

//
解锁设备
BQ27427_sendCmd(UNSEAL_KEY);
BQ27427_sendCmd(UNSEAL_KEY);

//
进入配置模式
BQ27427_sendCmd(SET_CFGUPDATE);
// HAL_Delay(1500);

do {
flags = BQ27427_ReadFlags();
} while (!(flags & (1U << 4)));

ret = BQ27427_selectDataBlock(0x52, 0);
if (ret != HAL_OK) return ret;

ret = BQ27427_ReadInternal(Block_Data_Checksum, &old_csum, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Design_Capacity, &old_lsb_DC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Design_Capacity+1, &old_msb_DC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Taper_Rate, &old_lsb_CTTC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Taper_Rate+1, &old_msb_CTTC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Design_Energy, &old_lsb_mWh, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Design_Energy+1, &old_msb_mWh, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Terminate_Voltage, &old_lsb_TV, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_ReadInternal(Terminate_Voltage+1, &old_msb_TV, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);

ret = BQ27427_Write(Design_Capacity, &lsb_DC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Design_Capacity+1, &msb_DC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Taper_Rate, &lsb_CTTC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Taper_Rate+1, &msb_CTTC, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);
ret = BQ27427_Write(Terminate_Voltage, &lsb_TV, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Terminate_Voltage+1, &msb_TV, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Design_Energy, &lsb_mWh, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
ret = BQ27427_Write(Design_Energy+1, &msb_mWh, 1);
HAL_Delay(100);
if (ret != HAL_OK) return ret;
HAL_Delay(100);

newCsum = BQ27427_calcChecksum(old_csum, old_msb_DC, old_lsb_DC, old_msb_CTTC, old_lsb_CTTC, 0, 0, 0, 0, 0, 0, old_msb_mWh, old_lsb_mWh, old_msb_TV, old_lsb_TV, msb_DC, lsb_DC, msb_CTTC, lsb_CTTC, 0, 0, 0, 0, 0, 0, msb_TV, lsb_TV, msb_mWh, lsb_mWh);
ret = BQ27427_Write(Block_Data_Checksum,&newCsum, 1);
if (ret != HAL_OK) return ret;
HAL_Delay(100);

BQ27427_sendCmd(SOFT_RESET);

do {
flags = BQ27427_ReadFlags();
} while ((flags & (1U << 4))!=0);


HAL_Delay(100);
return HAL_OK;

// //
重新锁定设备
// BQ27427_Write(SEAL_KEY);

}

 

uint16_t soc;

int main()

{

//(其他省略)

MX_I2C1_Init();

BQ27427_Set(CHEM_B, 200, 3700, 2700);

while (1)
{

soc = BQ27427_ReadSOC();

//(其他省略)

}

}