MAX17043锂电池电量测量芯片C51驱动

MAX17043/MAX17044为结构紧凑、低成本、主机侧电量计,用于手持及便携产品的锂离子(Li+)电池的电量计量。MAX17043配置为单节锂电池计量,MAX17044配置为两节2S电池组计量。
MAX17043/MAX17044采用成熟的Li+电池建模方案(称为ModelGauge™),在整个充/放电过程中连续跟踪电池的相对充电状态(SOC)。与传统的电量计不同,ModelGauge算法省去了电池的再学习过程以及外部检流电阻。器件提供温度补偿,使得µC与器件之间的交互操作降至最少。

需要注意的是,MAX17043仅支持单节锂电池计量或者锂电池的并联计量,常见的18650单节或者并联多节都是可以的。MAX17043不带电池保护功能,所以在18650锂电池的输出端需要先接锂电池保护板,再将保护板的输出接到MAX17043上。
18650锂电池的输出端需要先接锂电池保护板

max17043_iic.h
#ifndef __MAX17043_IIC_H_
#define __MAX17043_IIC_H_

#include <STC8.H>

#define MAX17043_SCL     P43
#define MAX17043_SDA     P44


void MAX17043_IIC_Start();
void MAX17043_IIC_Stop();
void MAX17043_IIC_WriteACK(unsigned char ack);
unsigned char MAX17043_IIC_WaitACK();
void MAX17043_IIC_WriteByte(unsigned char wdata);
unsigned char MAX17043_IIC_ReadByte();

#endif
max17043_iic.c
#include "max17043_iic.h"
#include "intrins.h"

static void MAX17043_Delay()
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 20;
	while(--i);
}

void MAX17043_IIC_Start()
{
	MAX17043_SDA = 1;
	MAX17043_SCL = 1;
	MAX17043_Delay();
	MAX17043_SDA = 0;
	MAX17043_Delay();
	MAX17043_SCL = 0;
}

void MAX17043_IIC_Stop()
{
	MAX17043_SDA = 0;
	MAX17043_SCL = 0;
	MAX17043_Delay();
	MAX17043_SCL = 1;
	MAX17043_Delay();
	MAX17043_SDA = 1;
	MAX17043_Delay();
}

void MAX17043_IIC_WriteACK(unsigned char ack)
{
	MAX17043_SDA = ack;
	MAX17043_Delay();
	MAX17043_SCL = 1;
	MAX17043_Delay();
	MAX17043_SCL = 0;
}

unsigned char MAX17043_IIC_WaitACK()
{  
	unsigned char errtime = 50;

	MAX17043_Delay(); /*读ACK*/
	MAX17043_SCL = 1;
	while(MAX17043_SDA)
	{  
		errtime--;
		if(!errtime) 
		{
			MAX17043_IIC_Stop();
			return 0;
		}
	}
	MAX17043_SCL = 0;
	MAX17043_Delay();
	
	return 1;
}

void MAX17043_IIC_WriteByte(unsigned char wdata)
{
	unsigned char i;
	
	for(i=0; i<8; i++)
	{
		MAX17043_SDA = wdata&0x80;
				
		wdata <<= 1;
		MAX17043_SCL = 1;
		MAX17043_Delay();
		MAX17043_SCL = 0;
	}   
}

unsigned char MAX17043_IIC_ReadByte()
{
	unsigned char i, bytedata;
	
	MAX17043_SDA = 1;
	for(i=0; i<8; i++)
	{
		MAX17043_SCL = 1; 
		bytedata <<= 1;
		bytedata |= MAX17043_SDA;
		MAX17043_SCL = 0;
		MAX17043_Delay();
	}
	return bytedata;
}
max17043.h
#ifndef __MAX17043_H_
#define __MAX17043_H_

#define MAX17043_WRITE_ADDR    0x6C
#define MAX17043_READ_ADDR     0x6D

#define MAX17043_VCELL_MSB     0x02
#define MAX17043_VCELL_LSB     0x03
#define MAX17043_SOC_MSB       0x04
#define MAX17043_SOC_LSB       0x05
#define MAX17043_MODE_MSB      0x06
#define MAX17043_MODE_LSB      0x07
#define MAX17043_VERSION_MSB   0x08
#define MAX17043_VERSION_LSB   0x09
#define MAX17043_CONFIG_MSB    0x0C
#define MAX17043_CONFIG_LSB    0x0D
#define MAX17043_COMMAND_MSB   0xFE
#define MAX17043_COMMAND_LSB   0xFF

#define MAX17043_ALT     P32
#define MAX17043_QST     P40


float MAX17043_GetBatteryPercent();
void MAX17043_QuickStart();
void MAX17043_EnterSleepMode();
void MAX17043_Restart();
void MAX17043_ClearAlert();
void MAX17043_SetAlertThreshold(unsigned char threshold);

#endif
max17043.c
#include "max17043.h"
#include "max17043_iic.h"
#include "debug.h"
#include "intrins.h"

static void MAX17043_Delayms(unsigned int ms)		//@24.000MHz
{
	unsigned char i, j;

	while(ms)
	{
		_nop_();
		i = 32;
		j = 40;
		do
		{
			while (--j);
		} while (--i);
		
		ms--;
	}
}

// 写寄存器,MAX17043写入的时候地址会自动增,所以可以连续写
// addr:芯片寄存器起始地址
// buf:写数组值
// count:写的长度
// lastBitAck: 最后写的字节写完之后,主机是否发送应答
//
// 返回:0--写入失败,1--写入成功
static unsigned char MAX17043_WriteReg(unsigned char addr, unsigned char *buf, unsigned char count, unsigned char lastBitAck)
{
	unsigned char ret;
	unsigned char i;
	
	MAX17043_IIC_Start();
	MAX17043_IIC_WriteByte(MAX17043_WRITE_ADDR);
	ret = MAX17043_IIC_WaitACK();
	if(!ret)
	{
		Debug_UartSendStr("MAX17043: Write AddrCMD error, device not ack!\r\n");
		return 0;
	}
	
	MAX17043_IIC_WriteByte(addr);
	ret = MAX17043_IIC_WaitACK();
	if(!ret)
	{
		Debug_UartSendStr("MAX17043: Write Addr error, device not ack!\r\n");
		return 0;
	}
	
	for(i=0; i<count; i++)
	{
		MAX17043_IIC_WriteByte(buf[i]);   /*写数据*/
		
		if(i < count-1 || lastBitAck)
		{
			ret = MAX17043_IIC_WaitACK();
			if(!ret)
			{
				Debug_UartSendStr("MAX17043: Write data error, device not ack!\r\n");
				return 0;
			}
		}
	}
	
	MAX17043_IIC_Stop();
	return 1;
}

// 读寄存器,MAX17043读取的时候地址会自动增,所以可以连续读
// addr:芯片寄存器起始地址
// buf:读取存放数组
// count:读的长度
//
// 返回:0--读取失败,1--读取成功
static unsigned char MAX17043_ReadReg(unsigned char address, unsigned char * buf, unsigned char count) /*多字节*/
{ 
	unsigned char ret;
	unsigned char i;

	MAX17043_IIC_Start();
	MAX17043_IIC_WriteByte(MAX17043_WRITE_ADDR); //写命令
	ret = MAX17043_IIC_WaitACK();
	if(!ret)
	{
		Debug_UartSendStr("MAX17043: Write AddrCMD error, device not ack!\r\n");
		return 0;
	}
	
	MAX17043_IIC_WriteByte(address); //写地址
	ret = MAX17043_IIC_WaitACK();
	if(!ret)
	{
		Debug_UartSendStr("MAX17043: Write AddrCMD error, device not ack!\r\n");
		return 0;
	}
	
	MAX17043_IIC_Start();
	MAX17043_IIC_WriteByte(MAX17043_READ_ADDR); //读命令
	ret = MAX17043_IIC_WaitACK();
	if(!ret)
	{
		Debug_UartSendStr("MAX17043: Write ReadCMD error, device not ack!\r\n");
		return 0;
	}
	
	for(i=0; i<count; i++)
	{
		*buf++ = MAX17043_IIC_ReadByte();
		if(i < count-1)
		{
			MAX17043_IIC_WriteACK(0);
		}
		else
		{
			MAX17043_IIC_WriteACK(1);
		}
	}	
	MAX17043_IIC_Stop();
	return 1;
} 

// 获取百分比单位的电池剩余电量
float MAX17043_GetBatteryPercent()
{
	unsigned char buf[2] = {0};
	float percent = 0.0;
	
	MAX17043_ReadReg(MAX17043_SOC_MSB, buf, sizeof(buf));
	percent = buf[0] + buf[1]/256.0; // buf[0]是1%精度的剩余电量
									 // buf[1]是1/256%精度的剩余电量
	
	return percent;
}

// 快速启动
// 这里使用了硬件直接在QST引脚给上升沿的方式
// 也可以向MAX17043写寄存器的方式实现,参考数据手册
void MAX17043_QuickStart()
{
	MAX17043_QST = 0;
	MAX17043_Delayms(2);
	MAX17043_QST = 1;
	MAX17043_Delayms(2);
}

// 进入睡眠模式
// 这里将SCL和SDA拉低2.5s进入睡眠模式
// 同样也可以写寄存器使之进入睡眠模式
void MAX17043_EnterSleepMode()
{
	MAX17043_SCL = 0;
	MAX17043_SDA = 0;
	MAX17043_Delayms(2600);
}

// 重启,效果和断电重启一样
void MAX17043_Restart()
{
	unsigned char buf[2] = {0x00, 0x54};
	
	// 最后一位写入的时候,MAX17043是不应答的,需要注意
	MAX17043_WriteReg(MAX17043_COMMAND_MSB, buf, sizeof(buf), 0);
}

// 设置电量警报阈值
// threshold:整数百分比单位的阈值,范围是32~1,也就是32%~1%之间
void MAX17043_SetAlertThreshold(unsigned char threshold)
{
	unsigned char buf[2] = {0x97, 0x1C};
	
	if(threshold > 0x1f)  // 如果阈值大于32%,那么限制成32%
	{
		threshold = 0x1f;
	}
	
	buf[1] = (0x1F - threshold) | 0x20;  // 设置成寄存器格式,并打开中断
	// 最后一位写入的时候,MAX17043会应答
	MAX17043_WriteReg(MAX17043_CONFIG_MSB, buf, sizeof(buf), 1);
}

// 清除阈值电量中断标志位
void MAX17043_ClearAlert()
{
	unsigned char buf[2] = {0x97, 0x1C};
	
	MAX17043_ReadReg(MAX17043_CONFIG_MSB, buf, sizeof(buf));
	buf[1] &= 0xDF;
	MAX17043_WriteReg(MAX17043_CONFIG_MSB, buf, sizeof(buf), 1);
}
  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 电池电量检测通常可以通过以下几种方式进行显示: 1. 电池图标显示:电池图标通常会出现在设备的状态栏中,如手机、平板电脑等设备。通过观察图标的颜色和形状,可以大致了解电池的电量情况。 2. 百分比显示:在一些设备中,可以通过设置来选择显示电池电量的百分比。这样可以更精确地知道电池还剩余多少电量。 3. LED灯显示:有些设备的电池上会有一个或多个LED灯,通过不同颜色的闪烁或亮灭来表示电池电量的情况。 4. 声音或震动提示:在一些设备中,电池电量低时会有声音或震动提示,提醒用户需要充电。 总之,不同设备和不同品牌的电池电量检测显示方式可能会有所不同,但通常都会提供多种方式来方便用户了解电池电量的情况。 ### 回答2: 电池电量检测是一种利用电池内部电荷状态来判断电池剩余容量的方法。目前常见的电池电量检测显示方法有三种:基于电压检测、基于电流检测和基于计算模型。 基于电压检测方法是根据电池输出的电压来反映电池电量的高低。一般来说,电池电量高时,输出电压会较高,电池电量低时,输出电压会较低。通过测量电池的输出电压,并与预设的电压阈值进行比较,可以判断出电池的电量是否足够。 基于电流检测方法是通过测量电池的充放电电流来判断电池电量。电池在充电时,电流会流入电池,而放电时,电流会流出电池。通过测量电流的大小和方向,可以推断出电池的充放电状态,从而判断电池的电量。 基于计算模型方法是根据电池在不同电荷状态下的电压-电荷曲线来建立数学模型,通过测量电池的电压,并与模型进行比较,可以推断出电池的电量。这种方法需要事先建立准确的模型,能够更加精确地预测电池的电量。 综上所述,电池电量检测的显示方法有基于电压检测、基于电流检测和基于计算模型三种。不同的方法适用于不同类型的电池和检测精度要求。在实际使用中,可以根据需求选择合适的方法来显示电池的电量。 ### 回答3: 电池电量检测是指判断电池目前的电量剩余量的方法。如今,智能手机、平板电脑、笔记本电脑等设备都内置了电池电量检测系统。 电池电量检测的显示方法有多种。通常,设备会在状态栏、锁屏界面或者相关设置中显示电池电量的图标。这个图标通常以一个绿色的电池形状为主,上面会有一个百分比数字,表示电池的剩余电量。当电池电量越高时,这个图标就会显示更多的电池形状,表示电量相对充足。 此外,一些设备还会提供更详细的电池电量显示方式。例如,在设置中,可以查看电池使用情况的统计数据,按照应用程序或功能的使用情况,显示电池消耗的时间和电量百分比。这有助于用户更直观地了解哪些应用程序或功能对电池消耗较大,从而做出相应的调整,延长电池的使用时间。 有些设备也可以通过通知中心或下拉菜单显示电池电量的百分比,以及还有多少剩余时间。这种方式更方便用户随时了解电池电量的情况,以便及时做出决策,如是否需要充电。 总的来说,电池电量检测的显示方法在不同设备上可能会有所不同,但通常都会提供一个电池图标和百分比数字来显示电池的剩余电量。另外,一些设备还提供更详细的电量统计数据和通知中心的显示方式,方便用户更好地管理和利用电池电量

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值