CW2015芯片电源模块读取

君正T31移植电源IC示例代码:

手写IIC起始信号和应答信号

DriverIIC_Sample.c
#include <reg51.h>

//****************************Micro*******************************/
#define	READ_CW2015				0xc5
#define	WRITE_CW2015			0xc4

#define I2C_DELAY		2

sbit SCL = P2^3;
sbit SDA = P2^2;

//***************************function*******************************/
                                                                
//==========================功能子函数===============================
void I2C_Delay10us(unsigned char us)
{
	unsigned char a, b;
	unsigned char i;
	for(i = 0; i < us; i++){
		for(b=1; b>0; b--)
		{
			for(a=2; a>0; a--);
		}
	}
}
#if 0
//-------------------------------------------------------------------
void iic_init(void)			//IIC总线初始化函数
{
	SDA = 1;				//释放IIC总线的数据线。
	SCL = 1;				//释放IIC总线的时钟线。
}
//-------------------------------------------------------------------
#endif
void start(void)			//IIC总线产生起始信号函数  
{
	SDA = 1;				//拉高数据线
	SCL = 1;				//拉高时钟线
	I2C_Delay10us(I2C_DELAY);
	SDA = 0;				//在时钟线为高电平时,拉低数据线,产生起始信号。
	I2C_Delay10us(I2C_DELAY);
	SCL = 0;				//拉低时钟线
}
//-------------------------------------------------------------------
void stop(void)				//IIC总线产生停止信号函数
{
	SDA = 0;				//拉低数据线
	I2C_Delay10us(I2C_DELAY);
	SCL = 1;				//拉高时钟线。
	I2C_Delay10us(I2C_DELAY);
	SDA = 1;				//时钟时线为高电平时,拉高数据线,产生停止信号。
	I2C_Delay10us(I2C_DELAY);
	//	SCL = 0;
	I2C_Delay10us(I2C_DELAY);
}
//-------------------------------------------------------------------
bit r_ack(void)				//接收应答信号函数
{
    bit ack;				//定义一个位变量,来暂存应答状态。

	SCL = 1;				//拉高时钟线。
	I2C_Delay10us(I2C_DELAY);
	ack = SDA;				//读取应答信号的状态。
	I2C_Delay10us(I2C_DELAY);
	SCL = 0;				//拉低时钟线。
	I2C_Delay10us(I2C_DELAY);
	return ack;				//返回应答信号的状态,0表示应答,1表示非应答。
}

bit wait_r_ack(void)
{
	bit ack;
	unsigned int i;	
	ack = 1;
	for(i = 0; i < 100; i++)
	{
		ack = r_ack();
		if(!ack)
		{
			break;
		}
		if(i == 99)
		{
			stop();
			return 1;
		}
	}
	return 0;
}
//---------------------------------------`----------------------------
void s_ack(void)				//发送应答信号函数
{
	SDA = 1;				//释放数据总线,准备接收应答信号。
	I2C_Delay10us(I2C_DELAY);
	SCL = 1;				//拉高时钟线。
	I2C_Delay10us(I2C_DELAY);
	SCL = 0;				//拉低时钟线。
	I2C_Delay10us(I2C_DELAY);

}

void sn_ack(void)				//Master发送准备连读指令
{
	SDA = 0;
	I2C_Delay10us(I2C_DELAY);
	SCL = 1;
	I2C_Delay10us(I2C_DELAY);
	SCL = 0;
	SDA = 1;
	I2C_Delay10us(I2C_DELAY);
}

//-------------------------------------------------------------------
void write_byte(unsigned char w_data)		//向IIC总线写入一个字节的数据函数 
{
	unsigned char i;
	for(i = 0; i < 8; i++)				//有8位数据
	{
		SDA = w_data & 0x80;				//写最高位的数据
		I2C_Delay10us(I2C_DELAY);
		SCL = 1;						//拉高时钟线,将数写入到设备中。
		I2C_Delay10us(I2C_DELAY);
		SCL = 0;						//拉低时钟线,允许改变数据线的状态
		I2C_Delay10us(I2C_DELAY);
		w_data = w_data << 1;				//数据左移一位,把次高位放在最高位,为写入次高位做准备
    }
}
//-------------------------------------------------------------------
unsigned char read_byte(void)			//从IIC总线读取一个字节的数据函数
{
	unsigned char i;
	unsigned char r_data;					//定义一个缓冲寄存器。
	for(i = 0; i < 8; i++)				//有8位数据
	{
		SCL = 1;						//拉高时钟线,为读取下一位数据做准备。
		I2C_Delay10us(I2C_DELAY);
		r_data = r_data << 1;				//将缓冲字节的数据左移一位,准备读取数据。
		I2C_Delay10us(I2C_DELAY);
		if(SDA)							//如果数据线为高平电平。
		{
			r_data = r_data | 0x1;			//则给缓冲字节的最低位写1。
		}
		SCL = 0;						//拉低时钟线,为读取下一位数据做准备。
		I2C_Delay10us(I2C_DELAY);
	}	
	return r_data;						//返回读取的一个字节数据。
}

//------------------------IIC读写函数--------------------------------
bit cw_read(unsigned char point_reg,unsigned char *r_pdata)
{
	start();
	write_byte(WRITE_CW2015);
	if(wait_r_ack())
	{
		return 1;
	}
	write_byte(point_reg);
	if(wait_r_ack())
	{
		return 1;
	}
	start();
	write_byte(READ_CW2015);
	if(wait_r_ack())
	{
		return 1;
	}
	*r_pdata = read_byte();
	s_ack();
	stop();
	return 0;
}

bit cw_read_word(unsigned char point_reg,unsigned char *r_pdata, unsigned int length)
{
	unsigned char count;

	start();
	write_byte(WRITE_CW2015);
	if(wait_r_ack())
	{
		return 1;
	}
	write_byte(point_reg);
	if(wait_r_ack())
	{
		return 1;
	}
	start();
	write_byte(READ_CW2015);
	if(wait_r_ack())
	{
		return 1;
	}
	for(count = 0; count < length; count++ ){
		*r_pdata = read_byte();
		if(count + 1 < length){
			r_pdata++;
			sn_ack();
		}
	}
	s_ack();
	stop();
	return 0;
}

bit cw_write(unsigned char point_reg,unsigned char *w_pdata)
{
	start();
	write_byte(WRITE_CW2015);
	if(wait_r_ack())
	{
		return 1;
	}
	write_byte(point_reg);
	if(wait_r_ack())
	{
		return 1;
	}
	write_byte(*w_pdata);
	if(wait_r_ack())
	{
		return 1;
	}
	stop();
	return 0;
}
Cw2015_test.c
#include <reg51.h>
#include "Cellwise CW201x Driver for MCU.h"
extern STRUCT_CW_BATTERY   cw_bat;
unsigned char cw_bat_init(void);
void cw_bat_work();

unsigned char enter = '\n';
void UsartConfiguration();
void Delay10ms(unsigned int c);

void show_enter(){
  	SBUF = enter;
	while(!TI);
	TI=0;
}

void show_number(unsigned int ret){ 
	unsigned int one = 0;
	unsigned int yushu = 0;
	one = ret / 100000;
	yushu = ret % 100000;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	one = yushu / 10000;
	yushu = yushu % 10000;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	one = yushu / 1000;
	yushu = yushu % 1000;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	one = yushu / 100;
	yushu = yushu % 100;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	one = yushu / 10;
	yushu = yushu % 10;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	one = yushu / 1;
	yushu = yushu % 1;
	SBUF = one + '0';
	while(!TI);
	TI=0;
	show_enter();
}

int main(void)
{
	unsigned char ret;
	
	UsartConfiguration();
	ret = cw_bat_init();
	
	while(1)
	{
		Delay10ms(100); 
		cw_bat_work();
		show_enter();
		show_number(cw_bat.capacity);
		show_enter();
		show_number(cw_bat.voltage);
		show_enter();
		show_number(cw_bat.time_to_empty);
		show_enter();
	}

	return 0;
}

void UsartConfiguration()
{
	SCON=0X50;			//设置为工作方式1
	TMOD=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍
	TH1=0XF3;		    //计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
//	ES=1;						//打开接收中断
//	EA=1;						//打开总中断
	TR1=1;					    //打开计数器
}

void Delay10ms(unsigned int c)   //误差 0us
{
    unsigned char a, b;

	//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
    for (;c>0;c--)
	{
		for (b=38;b>0;b--)
		{
			for (a=130;a>0;a--);
		}          
	}       
}

利用提供的HAL库去读取寄存器(不用手写IIC信号)

Cellwise CW201x Driver for MCU V2.2.1.c
#include "Cellwise CW201x Driver for MCU.h"

bit CHARGE = 0; //是否接充电器标志位,1为接充电器,0为拔出充电器
bit no_charger_full_jump =0;
unsigned int allow_no_charger_full =0;
unsigned int allow_charger_always_zero =0;
unsigned char if_quickstart =0;
unsigned char reset_loop =0;

/*定义一个全局变量,外部文件要使用时请先include Cellwise CW201x Driver for MCU.h文件,再用extern声明cw_bat*/
STRUCT_CW_BATTERY   cw_bat;


global function: 'cw_bat_work()'  and  'cw_bat_init()'                      
'cw_bat_work()'need be called by main.c in every second                     
'cw_bat_init()'need be called by main.c in system-init after power on reset 


//void delay_us(unsigned char us);	
bit cw_read(unsigned char PointReg,unsigned char *pData);
bit cw_write(unsigned char PointReg,unsigned char *pData);
bit cw_read_word(unsigned char point_reg,unsigned char *r_pdata, unsigned int length);

/**********************************************************************************/
/***************CW_Delay10ms() 与 CW_Delay10us() 函数是我根据51单******************/
/***************片机特性写的延迟函数,请根据自己的平台自行替换*********************/
/**********************************************************************************/
void CW_Delay10ms(unsigned int c) 
{
    unsigned char a, b;

	//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
    for (;c>0;c--)
	{
		for (b=38;b>0;b--)
		{
			for (a=130;a>0;a--);
		}          
	}       
}

void CW_Delay10us(unsigned char us)
{
	unsigned char a, b;
	unsigned char i;
	for(i = 0; i < us; i++){
		for(b=1; b>0; b--)
		{
			for(a=2; a>0; a--);
		}
	}
}

/*这个函数的作用是更新ic内的电池profile信息,一般只有在ic VDD掉电后再上电时才执行 
return 1 : i2c读写错, return 2 : 芯片处于sleep模式 return 3 : 写入的profile信息读出后与代码中的不一致*/
unsigned char cw_update_config_info(void)
{
	bit ret = 0;
	unsigned char i;
	unsigned char reset_val;
	unsigned char reg_val;
	/* make sure no in sleep mode */
	ret = cw_read(REG_MODE, &reg_val);
	if(ret)
	{
		return 1;
	}
	if((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP)
	{
		return 2;
	}
	/* update new battery info */
	for(i = 0; i < SIZE_BATINFO; i++)
	{
		reg_val = cw_bat_config_info[i];
		ret = cw_write(REG_BATINFO+i, &reg_val);
		if(ret)
		{
			return 1;
		}
	}

	/* readback & check */
	for(i = 0; i < SIZE_BATINFO; i++)
	{
		ret = cw_read(REG_BATINFO+i, &reg_val);
		if(ret)
		{
			return 1;
		}
		
		/* debug_log("[cw_update]: REG[%02X] = %02X", REG_BATINFO +i, reg_val); */
		if(reg_val != cw_bat_config_info[i])
		{
			return 3;
		}
	}
	/* set cw2015/cw2013 to use new battery info */
	ret = cw_read(REG_CONFIG, &reg_val);
	if(ret)
	{
		return 1;
	}
	reg_val |= CONFIG_UPDATE_FLG;   /* set UPDATE_FLAG */
	reg_val &= 0x07;                /* clear ATHD */
	reg_val |= ATHD;                /* set ATHD */
	ret = cw_write(REG_CONFIG, &reg_val);
	if(ret)
	{
		return 1;
	}
	/* reset */
	reset_val = MODE_NORMAL;
	reg_val = MODE_RESTART;
	ret = cw_write(REG_MODE, &reg_val);
	if(ret)
	{
		return 1;
	}
	CW_Delay10us(10);  //delay 100us      
	ret = cw_write(REG_MODE, &reset_val);
	if(ret)
	{
		return 1;
	}   
	return 0;
}

/*电量计初始化函数 每次开机后要执行
return 1 : i2c读写错, return 2 : 芯片处于sleep模式 return 3 : 写入的profile信息读出后与代码中的不一致 return 4 : 芯片启动后30s内读电量值一直异常*/
unsigned char cw_init(void)
{
	unsigned ret;
	unsigned char i;
	unsigned char reg_val = MODE_NORMAL;

	/* wake up cw2015/13 from sleep mode */
	ret = cw_write(REG_MODE, &reg_val);
	if(ret)
	{
		return 1;
	}

	/* check ATHD if not right */
	ret = cw_read(REG_CONFIG, &reg_val);
	if(ret)
	{
		return 1;
	}
	if((reg_val & 0xf8) != ATHD)
	{
		//"the new ATHD need set"
		reg_val &= 0x07;    /* clear ATHD */
		reg_val |= ATHD;    /* set ATHD */
		ret = cw_write(REG_CONFIG, &reg_val);
		if(ret)
		{
			return 1;
		}
	}
	
	/* check config_update_flag if not right */
	ret = cw_read(REG_CONFIG, &reg_val);
	if(ret)
	{
		return 1;
	}
	if(!(reg_val & CONFIG_UPDATE_FLG))
	{
		//"update flag for new battery info need set"
		ret = cw_update_config_info();
		if(ret)
		{
			return ret;
		}
	}
	else
	{
		for(i = 0; i < SIZE_BATINFO; i++)
		{ 
			ret = cw_read(REG_BATINFO +i, &reg_val);
			if(ret)
			{
				return 1;
			}
			
			/* debug_log("[cw_init]:REG[%02X] = %02X", REG_BATINFO +i, reg_val); */
			if(cw_bat_config_info[i] != reg_val)
			{
				break;
			}
		}
		if(i != SIZE_BATINFO)
		{
			//"update flag for new battery info need set"
			ret = cw_update_config_info();
			if(ret)
			{
				return ret;
			}
		}
	}
	/* check SOC if not eqaul 255 */
	for (i = 0; i < 30; i++) {
		CW_Delay10ms(10);//delay 100ms
		ret = cw_read(REG_SOC, &reg_val);
		if (ret)
			return 1;
		else if (reg_val <= 100) 
			break;		
    }
	
    if (i >=30){
        reg_val = MODE_SLEEP;
        ret = cw_write(REG_MODE, &reg_val);
        // "cw2015/cw2013 input unvalid power error_2\n";
        return 4;
    } 
	return 0;
}

#ifdef BAT_LOW_INTERRUPT
/*当一次alrt 事件到来时,cw2015 ic会拉低arlt pin产生中断,这时需要对06寄存器的最高bit位清0,才能让cw2015 ic释放alrt pin 下面函数的作用是释放alrt pin*/
unsigned char cw_release_alrt_pin(void)
{
        signed char ret = 0;
        unsigned int reg_val;
        unsigned char alrt;
        
		
        ret = cw_read(REG_RRT_ALERT, &reg_val);
        if (ret) {
            return -1;
		}
        alrt = reg_val & 0x80;
        
        reg_val = reg_val & 0x7f;
        ret = cw_write(REG_RRT_ALERT, &reg_val);
        if(ret) {
            return -1;
        }
        
        return alrt;
}

/*下面的函数是我写的一个例子,例子函数的作用是更新新的低电告警值为上次的 -1, 比如我们的代码开始的时候设定的低电告警值是10,那当电量降到10后*/
/*主控处理完中断后,我把新的低电告警值9写在了对应的寄存器中。 ATHD是08寄存器的前5个bit*/
bit cw_update_athd(){
	bit ret = 0;
	unsigned char reg_val;
	char new_athd = 0;
	
	ret = cw_read(REG_CONFIG, &reg_val);
	if(ret)
	{
		return -1;
	}
	new_athd = (reg_val >> 3) - 1;
	if(new_athd <= 0){
		new_athd = 0;
	}
	new_athd = new_athd << 3;

	//"the new ATHD need set"
	reg_val &= 0x07;    /* clear ATHD */
	reg_val |= new_athd;    /* set new ATHD */
	ret = cw_write(REG_CONFIG, &reg_val);
	if(ret)
	{
			return -1;
	}
	return 0;
}

static void ALRT_ISR()interrupt 
{
    /*User can do something when alrt */
	/*客户可以在这里加入当中断到来时想做的操作*/
    cw_release_alrt_pin();
	cw_update_athd();
    /*User can write new alrt to CONFIG resiger*/
}
#endif

bit cw_por(void)
{
	bit ret = 0;
	unsigned char reset_val = 0;
	reset_val = MODE_SLEEP;             
	ret = cw_write(REG_MODE, &reset_val);
	if (ret)
		return -1;
	CW_Delay10us(10); //delay 100us
	
	reset_val = MODE_NORMAL;
	ret = cw_write(REG_MODE, &reset_val);
	if (ret)
		return -1;
	CW_Delay10us(10); //delay 100us
	
	ret = cw_init();
	if (ret) 
		return ret;
	return 0;
}

int cw_get_capacity(void)
{
	bit ret = 0;
	unsigned char reg_val[2];
	unsigned char cw_capacity;
	unsigned int ui_100 = UI_FULL;
	unsigned int remainder = 0;
	unsigned int real_SOC = 0;
	unsigned int digit_SOC = 0;
	unsigned int UI_SOC = 0;

	ret = cw_read_word(REG_SOC, reg_val, 2);
	if(ret)
	{
		return -1;
	}

	real_SOC = reg_val[0];
	digit_SOC = reg_val[1];
	
	cw_capacity = real_SOC;
	
	/*假设ic出现问题,读取电量不在合理值范围内5次,重启ic。如果中间读到正确的值,那么5次的计数器清0,正确显示*/
	if ((cw_capacity < 0) || (cw_capacity > 100)) {
                // "get cw_capacity error; cw_capacity = %d\n"
        reset_loop++;
		if (reset_loop >5) { 
			ret = cw_por(); //por ic
			if(ret)
				return -1;
			reset_loop =0;               
		}                   
        return cw_bat.capacity;
    }else {
        reset_loop =0;
    }
	
	/*ic出错了,充了很久一直还是0%,一般我们用半个小时,那么重启下ic*/
	if((cw_bat.usb_online > 0) && (cw_capacity == 0))
	{		  
		allow_charger_always_zero++;
		if((allow_charger_always_zero >= BATTERY_DOWN_MIN_CHANGE_SLEEP) && (if_quickstart == 0))
		{
            ret = cw_por(); //por ic
			if(ret){
				return -1;
			}
			if_quickstart = 1;
			allow_charger_always_zero =0;
		}
	}
	else if((if_quickstart == 1)&&(cw_bat.usb_online == 0))
	{
		if_quickstart = 0;
	}

	UI_SOC = ((real_SOC * 256 + digit_SOC) * 100)/ (ui_100 * 256);
	remainder = (((real_SOC * 256 + digit_SOC) * 100 * 100) / (ui_100 * 256)) % 100;
	/* debug_log("real_SOC = %d digit_SOC = %d ui_100 = %d UI_SOC = %d remainder = %d\n",
		real_SOC, digit_SOC, ui_100, UI_SOC, remainder); */
	
	/*aviod swing*/
	if(UI_SOC >= 100){
		UI_SOC = 100;
	}else if ((0 == UI_SOC) && (10 >= remainder)){
		UI_SOC = 0;
	}else{
		if((remainder > 80 || remainder < 20) && (UI_SOC >= (cw_bat.capacity - 1)) && (UI_SOC <= (cw_bat.capacity + 1)))
		{
			UI_SOC = cw_bat.capacity;
		}
	}
	
	return UI_SOC;
}

unsigned int cw_get_vol(void)
{
	bit ret = 0;
	unsigned char get_ad_times = 0;
	unsigned char reg_val[2] = {0 , 0};
	unsigned long ad_value = 0;
	unsigned int ad_buff = 0;
	unsigned int ad_value_min = 0;
	unsigned int ad_value_max = 0;

	for(get_ad_times = 0; get_ad_times < 3; get_ad_times++)
	{
		ret = cw_read_word(REG_VCELL, &reg_val[0],2);
		if(ret)
		{
			return 1;
		}
		ad_buff = (reg_val[0] << 8) + reg_val[1];

		if(get_ad_times == 0)
		{
			ad_value_min = ad_buff;
			ad_value_max = ad_buff;
		}
		if(ad_buff < ad_value_min)
		{
			ad_value_min = ad_buff;
		}
		if(ad_buff > ad_value_max)
		{
			ad_value_max = ad_buff;
		}
		ad_value += ad_buff;
	}
	ad_value -= ad_value_min;
	ad_value -= ad_value_max;
	ad_value = ad_value  * 305 / 1000;
	return(ad_value);       //14位ADC转换值
}

#ifdef CW2015_GET_RRT
int cw_get_time_to_empty(void)
{
        signed char ret;
        unsigned char reg_val;
        unsigned int value16;

        ret = cw_read(REG_RRT_ALERT, &reg_val);
        if (ret)
                return -1;

        value16 = (unsigned int)reg_val;

        ret = cw_read(REG_RRT_ALERT + 1, &reg_val);
        if (ret)
                return -1;

        value16 = ((value16 << 8) + reg_val) & 0x1fff;
       
        return value16;
}
#endif

void update_capacity(void)
{
	int cw_capacity;
	cw_capacity = cw_get_capacity();
	if((cw_capacity >= 0) && (cw_capacity <= 100) && (cw_bat.capacity != cw_capacity))
	{       
		cw_bat.capacity = cw_capacity;
	}
}


void update_vol(void)
{
	unsigned int cw_voltage;
	cw_voltage = cw_get_vol();
	if(cw_voltage == 1){
		//read voltage error
		cw_bat.voltage = cw_bat.voltage;
	}else if(cw_bat.voltage != cw_voltage)
	{
		cw_bat.voltage = cw_voltage;
	}
}

#ifdef CW2015_GET_RRT
static void update_time_to_empty(void)
{
	unsigned int rrt;
	rrt = (unsigned int)cw_get_time_to_empty();
	if((rrt >= 0) && (cw_bat.time_to_empty != rrt))
	{
		cw_bat.time_to_empty = rrt;
	}
}
#endif
/*
static void update_alt(void)
{
	signed int alt;
	alt = cw_get_alt();
	if ((rrt >= 0) && (cw_bat.alt != alt))
	{
		cw_bat.alt = (unsigned int)alt;
	}       
}
*/

void update_usb_online(void)
{
	if(CHARGE == 1) 
	//这里请注意,这里是客户需要自己配置修改的地方
	//请修改代码保证DC插入时配置cw_bat.usb_online为 1,DC不在时配置cw_bat.usb_online为0
	{
		cw_bat.usb_online = 1;
	}else{
		cw_bat.usb_online = 0;
	}
}

MCU一秒调用一次//
void cw_bat_work(void)
{
	update_usb_online();
	update_capacity();
	update_vol();
#ifdef CW2015_GET_RRT
	update_time_to_empty();
#endif
	/* debug_log("[CW2015]capacity = %d voltage = %d\n", cw_bat.capacity, cw_bat.voltage); */
}

/*
static void cw_bat_gpio_init(void)
{
     
     usb_det_pin -- init
     alt_pin  -- init
 
     return 0;
}
*/

static int cw_init_data()
{
	unsigned char reg_SOC[2];
	int real_SOC = 0;
	int digit_SOC = 0;
	int ret;
	int UI_SOC = 0;

	ret = cw_read_word(REG_SOC, reg_SOC, 2);
    if (ret)
    	return -1;

	real_SOC = reg_SOC[0];
	digit_SOC = reg_SOC[1];
	UI_SOC = ((real_SOC * 256 + digit_SOC) * 100)/ (UI_FULL*256);
	/* debug_log("[cw_init_data]: real_SOC = %d  digit_SOC = %d\n", real_SOC, digit_SOC); */
	if(UI_SOC >= 100){
		UI_SOC = 100;
	}
	
	cw_bat.capacity = UI_SOC;	
	update_usb_online();
	update_vol();
#ifdef CW2015_GET_RRT
	update_time_to_empty();
#endif
	return 0;
}

///MCU开机初始化时调用.//
unsigned char cw_bat_init(void)
{
	unsigned char ret;
	unsigned char loop = 0;
	//cw_bat_gpio_init();
	
	ret = cw_init();
	while((loop++ < 5) && (ret != 0))
	{
		ret = cw_init();
	}
	
	cw_bat.alt = 0;
	cw_init_data();
	
	return ret;	
}
Cellwise CW201x Driver for MCU.h
#ifndef _cw2015_battery_H_
#define _cw2015_battery_H_
#define	READ_CW2015				0xc5
#define	WRITE_CW2015			0xc4

#define REG_VERSION             0x0
#define REG_VCELL               0x2
#define REG_SOC                 0x4
#define REG_RRT_ALERT           0x6
#define REG_CONFIG              0x8
#define REG_MODE                0xA
#define REG_BATINFO             0x10

#define MODE_SLEEP_MASK         (0x3<<6)
#define MODE_SLEEP              (0x3<<6)
#define MODE_NORMAL             (0x0<<6)
#define MODE_QUICK_START        (0x3<<4)
#define MODE_RESTART            (0xf<<0)

#define CONFIG_UPDATE_FLG       (0x1<<1)

#define ATHD                    (0x0<<3)        //ATHD = 0%
#define UI_FULL             100

#define SIZE_BATINFO        64

#define BATTERY_DOWN_MIN_CHANGE_SLEEP 1800      // the min time allow battery change quantity when run 30min
//#define BAT_LOW_INTERRUPT    1
//#define CW2015_GET_RRT

/*电池建模信息,客户拿到自己电池匹配的建模信息后请替换*/
static unsigned char cw_bat_config_info[SIZE_BATINFO] = {
0x15  ,0x4C  ,0x5D  ,0x5D  ,0x5A  ,0x59  ,0x55  ,
0x51  ,0x4E  ,0x48  ,0x46  ,0x41  ,0x3C  ,0x39  ,
0x33  ,0x2D  ,0x25  ,0x1E  ,0x19  ,0x19  ,0x1A  ,
0x2C  ,0x44  ,0x4A  ,0x43  ,0x40  ,0x0C  ,0xCD  ,
0x22  ,0x43  ,0x56  ,0x82  ,0x78  ,0x6F  ,0x62  ,
0x60  ,0x42  ,0x19  ,0x37  ,0x31  ,0x00  ,0x1D  ,
0x59  ,0x85  ,0x8F  ,0x91  ,0x91  ,0x18  ,0x58  ,
0x82  ,0x94  ,0xA5  ,0xFF  ,0xAF  ,0xE8  ,0xCB  ,
0x2F  ,0x7D  ,0x72  ,0xA5  ,0xB5  ,0xC1  ,0x46  ,
0xAE
};

//****************************struct*********************************/
typedef struct tagSTRUCT_CW_BATTERY {
	unsigned char usb_online;
	unsigned int capacity;
	unsigned int voltage;
#ifdef CW2015_GET_RRT
	unsigned int time_to_empty;
#endif
	unsigned char alt;
}STRUCT_CW_BATTERY;

#endif
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CW2015双电池改为单电池后,读取代码的步骤如下: 1.首先,我们需要了解CW2015双电池的原理和工作方式。CW2015是一种高精度电流监测集成电路,可同时监测两个电池的充放电状况。在双电池模式下,CW2015通过两组电流传感器来分别监测两个电池的电流。而在单电池模式下,只需使用其中一个电流传感器来监测单个电池的电流。 2.根据CW2015的数据手册,查找单电池模式的相关配置寄存器和位定义。这些寄存器和位定义用于配置CW2015工作在单电池模式下,并获取单电池的电流数据。 3.使用适当的编程语言,如C或Python,编写读取CW2015单电池模式下电流数据的代码。首先,需要初始化CW2015并将其配置为单电池模式,可以通过I2C或SPI接口与CW2015通信。然后,读取相应的寄存器来获取单电池的电流数据。 4.根据需要,可以对读取的电流数据进行进一步处理和分析,比如计算电池的电量或监测电池的健康状况。 5.最后,测试代码的正确性。连接一个电池到CW2015上,并运行编写的代码,确保能够成功读取到单电池模式下的电流数据。如果有必要,可以通过与实际电流测量仪器的比对,验证读取的数据的准确性。 总之,将CW2015双电池改为单电池后,读取单电池模式下的电流数据需要进行相应的配置和代码编写。通过正确的配置和通信协议,可以准确地获取到单个电池的电流数据。这样可以方便对电池的运行状态进行监测和分析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值