一、简介:
CW2217是一款高精度的锂电池电量计芯片,具有以下特点:
-
支持I2C接口通信
-
内置高精度ADC,可测量电池电压、电流和温度
-
支持库仑计功能,精确计算电池剩余容量
-
提供电池状态信息(充电/放电/充满/放空)
-
低功耗设计,适合便携式设备
二、硬件 接口:
CW2217 STM32L4XX ----------------------------- VDD (2.5-5.5V) -> 3.3V GND -> GND SCL -> PB6/I2C1_SCL SDA -> PB7/I2C1_SDA ALERT -> PA0 (可配置为中断输入)
三、头文件:
#ifndef __CW2217_H
#define __CW2217_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32l4xx_hal.h"
/* CW2217 I2C地址 */
#define CW2217_ADDRESS 0x64
/* CW2217寄存器定义 */
#define CW2217_REG_VCELL 0x02
#define CW2217_REG_SOC 0x04
#define CW2217_REG_MODE 0x0A
#define CW2217_REG_CONFIG 0x0B
#define CW2217_REG_ALERT 0x0C
#define CW2217_REG_VERSION 0x0E
/* 模式寄存器值 */
#define CW2217_MODE_SLEEP 0x00
#define CW2217_MODE_ACTIVE 0x30
/* 配置寄存器值 */
#define CW2217_CONFIG_UPDATE 0x00
#define CW2217_CONFIG_REFRESH 0x01
/* 错误代码 */
#define CW2217_OK 0
#define CW2217_ERROR 1
#define CW2217_I2C_ERROR 2
#define CW2217_NOT_DETECTED 3
typedef struct {
I2C_HandleTypeDef *hi2c;
uint8_t address;
float voltage;
uint8_t soc;
uint8_t version;
uint8_t initialized;
} CW2217_HandleTypeDef;
uint8_t CW2217_Init(CW2217_HandleTypeDef *hdev, I2C_HandleTypeDef *hi2c);
uint8_t CW2217_ReadVoltage(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_ReadSOC(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_ReadVersion(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_EnterSleepMode(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_ExitSleepMode(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_UpdateConfig(CW2217_HandleTypeDef *hdev);
uint8_t CW2217_RefreshConfig(CW2217_HandleTypeDef *hdev);
#ifdef __cplusplus
}
#endif
#endif /* __CW2217_H */
四、源文件:
#include "cw2217.h"
#include <string.h>
/**
* @brief 初始化CW2217
* @param hdev: CW2217句柄
* @param hi2c: I2C句柄
* @retval 状态
*/
uint8_t CW2217_Init(CW2217_HandleTypeDef *hdev, I2C_HandleTypeDef *hi2c)
{
uint8_t reg_data[2] = {0};
if(hdev == NULL || hi2c == NULL)
return CW2217_ERROR;
hdev->hi2c = hi2c;
hdev->address = CW2217_ADDRESS;
hdev->voltage = 0.0f;
hdev->soc = 0;
hdev->initialized = 0;
// 检查设备是否存在
if(HAL_I2C_Mem_Read(hdev->hi2c, hdev->address << 1, CW2217_REG_VERSION,
I2C_MEMADD_SIZE_8BIT, reg_data, 1, 100) != HAL_OK)
{
return CW2217_NOT_DETECTED;
}
hdev->version = reg_data[0];
// 退出睡眠模式
if(CW2217_ExitSleepMode(hdev) != CW2217_OK)
return CW2217_ERROR;
// 更新配置
if(CW2217_UpdateConfig(hdev) != CW2217_OK)
return CW2217_ERROR;
hdev->initialized = 1;
return CW2217_OK;
}
/**
* @brief 读取电池电压
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_ReadVoltage(CW2217_HandleTypeDef *hdev)
{
uint8_t reg_data[2] = {0};
if(hdev == NULL || hdev->initialized == 0)
return CW2217_ERROR;
if(HAL_I2C_Mem_Read(hdev->hi2c, hdev->address << 1, CW2217_REG_VCELL,
I2C_MEMADD_SIZE_8BIT, reg_data, 2, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
// 电压计算: VCELL = (reg_val * 1.25) / 1000 (V)
uint16_t vcell = (reg_data[0] << 8) | reg_data[1];
hdev->voltage = (float)vcell * 1.25f / 1000.0f;
return CW2217_OK;
}
/**
* @brief 读取电池剩余电量百分比
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_ReadSOC(CW2217_HandleTypeDef *hdev)
{
uint8_t reg_data = 0;
if(hdev == NULL || hdev->initialized == 0)
return CW2217_ERROR;
if(HAL_I2C_Mem_Read(hdev->hi2c, hdev->address << 1, CW2217_REG_SOC,
I2C_MEMADD_SIZE_8BIT, ®_data, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
hdev->soc = reg_data;
return CW2217_OK;
}
/**
* @brief 读取芯片版本
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_ReadVersion(CW2217_HandleTypeDef *hdev)
{
uint8_t reg_data = 0;
if(hdev == NULL)
return CW2217_ERROR;
if(HAL_I2C_Mem_Read(hdev->hi2c, hdev->address << 1, CW2217_REG_VERSION,
I2C_MEMADD_SIZE_8BIT, ®_data, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
hdev->version = reg_data;
return CW2217_OK;
}
/**
* @brief 进入睡眠模式
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_EnterSleepMode(CW2217_HandleTypeDef *hdev)
{
uint8_t mode = CW2217_MODE_SLEEP;
if(hdev == NULL)
return CW2217_ERROR;
if(HAL_I2C_Mem_Write(hdev->hi2c, hdev->address << 1, CW2217_REG_MODE,
I2C_MEMADD_SIZE_8BIT, &mode, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
return CW2217_OK;
}
/**
* @brief 退出睡眠模式
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_ExitSleepMode(CW2217_HandleTypeDef *hdev)
{
uint8_t mode = CW2217_MODE_ACTIVE;
if(hdev == NULL)
return CW2217_ERROR;
if(HAL_I2C_Mem_Write(hdev->hi2c, hdev->address << 1, CW2217_REG_MODE,
I2C_MEMADD_SIZE_8BIT, &mode, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
HAL_Delay(10); // 等待模式切换完成
return CW2217_OK;
}
/**
* @brief 更新配置
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_UpdateConfig(CW2217_HandleTypeDef *hdev)
{
uint8_t config = CW2217_CONFIG_UPDATE;
if(hdev == NULL)
return CW2217_ERROR;
if(HAL_I2C_Mem_Write(hdev->hi2c, hdev->address << 1, CW2217_REG_CONFIG,
I2C_MEMADD_SIZE_8BIT, &config, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
HAL_Delay(10); // 等待配置更新完成
return CW2217_OK;
}
/**
* @brief 刷新配置
* @param hdev: CW2217句柄
* @retval 状态
*/
uint8_t CW2217_RefreshConfig(CW2217_HandleTypeDef *hdev)
{
uint8_t config = CW2217_CONFIG_REFRESH;
if(hdev == NULL)
return CW2217_ERROR;
if(HAL_I2C_Mem_Write(hdev->hi2c, hdev->address << 1, CW2217_REG_CONFIG,
I2C_MEMADD_SIZE_8BIT, &config, 1, 100) != HAL_OK)
{
return CW2217_I2C_ERROR;
}
HAL_Delay(10); // 等待配置刷新完成
return CW2217_OK;
}
五、应用:
#include "main.h"
#include "i2c.h"
#include "cw2217.h"
CW2217_HandleTypeDef hcw2217;
void Battery_Monitor_Example(void)
{
uint8_t ret;
// 初始化CW2217
ret = CW2217_Init(&hcw2217, &hi2c1);
if(ret != CW2217_OK)
{
printf("CW2217 Init Failed: %d\r\n", ret);
return;
}
printf("CW2217 Detected, Version: 0x%02X\r\n", hcw2217.version);
while(1)
{
// 读取电压
if(CW2217_ReadVoltage(&hcw2217) == CW2217_OK)
{
printf("Battery Voltage: %.3fV\r\n", hcw2217.voltage);
}
// 读取电量百分比
if(CW2217_ReadSOC(&hcw2217) == CW2217_OK)
{
printf("Battery SOC: %d%%\r\n", hcw2217.soc);
}
HAL_Delay(5000); // 每5秒更新一次
}
}