君正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, ®_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, ®_val);
if(ret)
{
return 1;
}
}
/* readback & check */
for(i = 0; i < SIZE_BATINFO; i++)
{
ret = cw_read(REG_BATINFO+i, ®_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, ®_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, ®_val);
if(ret)
{
return 1;
}
/* reset */
reset_val = MODE_NORMAL;
reg_val = MODE_RESTART;
ret = cw_write(REG_MODE, ®_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, ®_val);
if(ret)
{
return 1;
}
/* check ATHD if not right */
ret = cw_read(REG_CONFIG, ®_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, ®_val);
if(ret)
{
return 1;
}
}
/* check config_update_flag if not right */
ret = cw_read(REG_CONFIG, ®_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, ®_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, ®_val);
if (ret)
return 1;
else if (reg_val <= 100)
break;
}
if (i >=30){
reg_val = MODE_SLEEP;
ret = cw_write(REG_MODE, ®_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, ®_val);
if (ret) {
return -1;
}
alrt = reg_val & 0x80;
reg_val = reg_val & 0x7f;
ret = cw_write(REG_RRT_ALERT, ®_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, ®_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, ®_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, ®_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, ®_val);
if (ret)
return -1;
value16 = (unsigned int)reg_val;
ret = cw_read(REG_RRT_ALERT + 1, ®_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