在传统无人机或机器人等设备的电池电量剩余预计中,一般都使用分压电阻的方法,采集大
比例电阻的电压从而推算出整体电池电压,用当前电压来粗略的代替当前电量,这里有个很
大的问题就是当主板电路系统中存在高功率器件,比如电机,舵机,继电器等瞬时功率很高
所需要的电流很大瞬间可以把电压拉低,导致电量预计存在很大误差,只有当设备静止时才能
勉强正常。
需要获取准确的电池剩余电量可以使用库仑计结合电池放电曲线来推算。
BQ28Z610适用于 1-2 节串联电池组并具有集成保护器的电池电量监测计。
采用专用主模式 I2C 接口实现自主电池充电控制。
采用内部旁路实现电芯均衡,优化电池运行状况。
高侧保护 N 沟道 FET 驱动器可在故障期间实现串行总线通信。
适用于电压、电流和温度的可编程保护等级。
具备两个独立 ADC 的模拟前端支持电流和电压同步采样。
高精度库伦计数器,输入失调电压误差 < 1µV(典型值)。
支持低至 1mΩ 的电流感应电阻器,同时支持 1mA 电流测量。
支持电池跳变点 (BTP) 功能,用于 Windows® 集成。
SHA-1 认证响应器,用于提高电池组安全性。
适用于高速编程和数据访问的 400kHz I2C 总线通信接口。
紧凑型 12 引脚 VSON 封装 (DRZ)。
stm32f2xx使用硬件i2c与BQ28Z610通信交互。
#ifndef __BQ28Z610_H__
#define __BQ28Z610_H__
#include "stm32f2xx_hal.h"
#include "core_cm3.h"
#include "comtypes.h"
extern __IO BOOLEAN is_i2c2_init;
extern I2C_HandleTypeDef g_mI2C2Handle;
/**BQ28是I2C主机模式广播和slave设备一样读取。
*/
int BQ_Init(void);
/**
返回剩余电量百分比
*/
int BQ_Get_ElectricQuantity(void);
#endif
#include "bq28z610.h"
#define READ_TIMOUT (300)
#define I2C_ADDRESS (0xAA)
#define Voltage (0x0809)
#define RemainingCapacity (0x1011)
#define FullChargeCapacity (0x1213)
#define LOCAL_DEBUG
#ifdef LOCAL_DEBUG
static I2C_HandleTypeDef I2CxHandle;
#define I2Cx I2C2
#define I2Cx_CLK_ENABLE() __HAL_RCC_I2C2_CLK_ENABLE()
#define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define I2Cx_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
/* Definition for I2Cx Pins */
#define I2Cx_SCL_PIN GPIO_PIN_10
#define I2Cx_SCL_GPIO_PORT GPIOB
#define I2Cx_SCL_AF GPIO_AF4_I2C2
#define I2Cx_SDA_PIN GPIO_PIN_11
#define I2Cx_SDA_GPIO_PORT GPIOB
#define I2Cx_SDA_AF GPIO_AF4_I2C2
static void BQ_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable GPIO Clocks #################################################*/
/* Enable GPIO TX/RX clock */
I2Cx_SCL_GPIO_CLK_ENABLE();
I2Cx_SDA_GPIO_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* I2C TX GPIO pin configuration */
GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = I2Cx_SCL_AF;
HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
/* I2C RX GPIO pin configuration */
GPIO_InitStruct.Pin = I2Cx_SDA_PIN;
GPIO_InitStruct.Alternate = I2Cx_SDA_AF;
HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
/*##-3- Enable I2C peripheral Clock ########################################*/
/* Enable I2C1 clock */
I2Cx_CLK_ENABLE();
}
#endif
int BQ_Init(void)
{
#ifdef LOCAL_DEBUG
BQ_I2C_MspInit(&I2CxHandle);
I2CxHandle.Instance = I2Cx;
I2CxHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2CxHandle.Init.ClockSpeed = 100000 >> 1;
I2CxHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2CxHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
I2CxHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2CxHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2CxHandle.Init.OwnAddress1 = I2C_ADDRESS;
I2CxHandle.Init.OwnAddress2 = 0;
if(HAL_I2C_Init(&I2CxHandle) != HAL_OK)
{
/* Initialization Error */
while(1);
}
#else
if(!is_i2c2_init) return -1;
#endif
return 0;
}
int BQ_Get_ElectricQuantity(void)
{
uint8_t ret;
uint8_t readval[2];
int full,remain;
#ifdef LOCAL_DEBUG
ret = HAL_I2C_Mem_Read( &I2CxHandle, (uint16_t)I2C_ADDRESS,FullChargeCapacity >> 8, I2C_MEMADD_SIZE_8BIT, readval, sizeof(readval), READ_TIMOUT );
if(ret != HAL_OK) return -1;
full = readval[1] << 8 | readval[0];
ret = HAL_I2C_Mem_Read( &I2CxHandle, (uint16_t)I2C_ADDRESS,RemainingCapacity >> 8, I2C_MEMADD_SIZE_8BIT, readval, sizeof(readval), READ_TIMOUT );
if(ret != HAL_OK) return -1;
#else
ret = HAL_I2C_Mem_Read( &g_mI2C2Handle, (uint16_t)I2C_ADDRESS,FullChargeCapacity >> 8, I2C_MEMADD_SIZE_8BIT, readval, sizeof(readval), READ_TIMOUT );
if(ret != HAL_OK) return -1;
full = readval[1] << 8 | readval[0];
ret = HAL_I2C_Mem_Read( &g_mI2C2Handle, (uint16_t)I2C_ADDRESS,RemainingCapacity >> 8, I2C_MEMADD_SIZE_8BIT, readval, sizeof(readval), READ_TIMOUT );
if(ret != HAL_OK) return -1;
#endif
remain = readval[1] << 8 | readval[0];
return remain * 100 / full;
}
/**
//test electric quantity
uint8_t datas[10];
uint8_t percent;
BQ_Init();
while(1)
{
percent = BQ_Get_ElectricQuantity();
memset(datas,0,sizeof(datas));
sprintf((char*)datas,"EQ=%d",percent);
USART1_SendBuf(datas,strlen((char*)datas));
HAL_Delay(100);
}
*/
//