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);
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值