单片机基于BQ28Z610的电池电量计算

张开发
2026/4/16 19:51:28 15 分钟阅读

分享文章

单片机基于BQ28Z610的电池电量计算
在传统无人机或机器人等设备的电池电量剩余预计中一般都使用分压电阻的方法采集大比例电阻的电压从而推算出整体电池电压用当前电压来粗略的代替当前电量这里有个很大的问题就是当主板电路系统中存在高功率器件比如电机舵机继电器等瞬时功率很高所需要的电流很大瞬间可以把电压拉低导致电量预计存在很大误差只有当设备静止时才能勉强正常。需要获取准确的电池剩余电量可以使用库仑计结合电池放电曲线来推算。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); } */ //////////////////////////////////////////////////////////////////////////

更多文章