bq26500是用于锂离子电池、锂聚合物电池充电、放电控制和监控的集成电路芯片。利用它能够准确提供电池充电、放电、电池温度、充放电电压、电池电量等相关数据。不须要外接微处理器參与电池充电、放电等相关数据的计算。
本文简单的读取了电池的电量百分比和电压。如要读取其它參数依照datasheet给出的寄存器一一读取就可以。
连接示意图:
引脚pack+ 和 pack-分别连接正极和负极用来冲放电,HDQ是数据交互引脚,用来读取电池的參数,一般用一个gpio连接就能够。
时序图:
看图可知。逻辑1和0并非简单的高低电平,而是依据高低电平占空比来推断是逻辑1还是0的。
基本通信过程:先发break 进入通信, 然后主机发送地址,电池返回数据。
寄存器列表:
读取电量百分比为0x0b寄存器。读取电压为0x09和0x08寄存器的值拼接的。
依据上诉信息编写读取电量的代码:
#define ADDR_PERCENT 0x0b
void bat_set_gpio(int en)
{
    if (en) {
        mt_set_gpio_mode(GPIO155, GPIO_MODE_00);
        mt_set_gpio_dir(GPIO155, GPIO_DIR_OUT);
        mt_set_gpio_out(GPIO155, GPIO_OUT_ONE);
    } else {
        mt_set_gpio_mode(GPIO155, GPIO_MODE_00);
        mt_set_gpio_dir(GPIO155, GPIO_DIR_OUT);
        mt_set_gpio_out(GPIO155, GPIO_OUT_ZERO);
    }
    return;
}
int bat_get_gpio(void)
{
    int ret = 0;
    mt_set_gpio_mode(GPIO155, GPIO_MODE_00);
    mt_set_gpio_dir(GPIO155, GPIO_DIR_IN);
    ret = mt_get_gpio_in(GPIO155);
    return ret;
}
static int send_addr_to_bq26500(unsigned int addr,int rw)
{
    int i;
    unsigned int  cmd = 0;
    cmd = addr | rw << 7;
    // break and break recovery timing
    bat_set_gpio(1);
    udelay(100);
    bat_set_gpio(0);
    udelay(190);//190us
    bat_set_gpio(1);
    udelay(40); //40us
    for (i=0;i<8;i++) {
        if(cmd >> i & 0x01) { //hw1
            bat_set_gpio(0);
            udelay(40); //40us
            bat_set_gpio(1);
            udelay(150); //150  
        } else {             //hw0
            bat_set_gpio(0);
            udelay(125); //125
            bat_set_gpio(1);
            udelay(65); //65        
        }
    }
    bat_get_gpio();
    return 0;
}
static unsigned char data_from_bq26500(void)
{
    volatile  unsigned char value = 0, low=0, temp = 0, temp_old = 0;
    int i, j;
    //wait response time
    for(i=0; i < 32; i++) { //320us
        udelay(10);
        temp = bat_get_gpio();
        if (temp == 0)
            break;
    }
    //read data
	//依据占空比推断是逻辑1还是逻辑0
    for (i=0; i < 8; i++) {
        for (j=0, low = 0; j < 26; j++) {//260us
            udelay(10);
            temp = bat_get_gpio();
            if (temp == 0) {
                low++;
            }
            if ((temp == 1) && (temp_old == 0)){
                break;
            }
            temp_old = temp;
        }
        if (low < 6 && low != 0){
            value = value | 1<< i;
        }
        temp = 1; 
        temp_old = 1; 
    }    
    
    return value;
}
static DEFINE_SPINLOCK(bq26500_spinlock);
// transmit address to bq26500
static unsigned char read_data_bq26500(unsigned int addr)
{
    volatile unsigned char value = 0, temp[3] = {0};    
    unsigned long flags;
    int i, j;
	//读取三次取中间值上报,假设平台频率低仅仅读取一次就可以。
    for (i=0; i < 3; i++) {
        spin_lock_irqsave(&bq26500_spinlock, flags);
        value = send_addr_to_bq26500(addr,0);
        temp[i] = data_from_bq26500();
        spin_unlock_irqrestore(&bq26500_spinlock, flags);
        usleep_range(10, 20); 
    }    
    for (i=0; i < 3; i++) {
        for (j=i; j < 3; j++) {
            if (temp[i] > temp[j]) {
                value = temp[i];
                temp[i] = temp[j];
                temp[j] = value;
            }    
        }    
    }    
    value = temp[1];
    return value;
} 
printk("Battery percent: %d\n", read_data_bq26500(0x0b))上诉代码是读取电量百分的,读取电压的方法例如以下:
    voltage_h = read_data_bq26500(0x09/*BATTERYH_VOLTAGE*/);
    voltage_l = read_data_bq26500(0x08/*BATTERYL_VOLTAGE*/);
    printk("Battery Vol:%d\n",voltage_l | voltage_h << 8);
原文:http://www.cnblogs.com/cynchanpin/p/7287270.html