This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Starterware/BQ2.7741万-G1:块数据寄存器的校验和读数无效

Guru**** 2367240 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/579348/starterware-bq27741-g1-invalid-checksum-reading-from-block-data-register

部件号:BQ2.7741万-G1

工具/软件:Starterware

您好,

AM读数无效校验和,无法获得预期读数。

我的代码:

#define BQ27441_ADDR 0x55       // taken from datasheet - page 13
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <math.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <time.h>
#include <sys/time.h>
#include <curses.h>
#include <wiringPi.h>
typedefunsigned charbyte;
intdeviceDescriptor;
/* This function initializes the I2C device*/
voidinit_i2c(char*DeviceName)
{  
        printf("Initialising i2c device \n");
        deviceDescriptor=open(DeviceName, O_RDWR);
        if(deviceDescriptor == -1) {
                printf("Error opening device '%s' \n",DeviceName);
                exit(-1);
        }
}
/* This function sends data to the I2C device*/
voidI2cSendData(byte addr,byte *data,intlen)
{
        if(ioctl(deviceDescriptor,I2C_SLAVE, addr))
                printf("I2cSendData_device : IOCTL Problem \n");
        write(deviceDescriptor,data,len);
}
/* This function reads data from the I2C device*/
voidI2cReadData(byte addr,byte *data,intlen)
{
        if(ioctl(deviceDescriptor,I2C_SLAVE, addr))
                printf("I2cReadData_device : IOCTL Problem \n");
        read(deviceDescriptor,data,len);
}
/* Convert the number to hexadecimal representation */
voidto_hex_16(char*output, unsigned n)
{
        staticconstcharhex_digits[] = "0123456789abcdef";
        output[0] = hex_digits[(n >> 12) & 0xF];
        output[1] = hex_digits[(n >> 8) & 0xF];
        output[2] = hex_digits[(n >> 4) & 0xF];
        output[3] = hex_digits[(n & 0xF)];
        output[4] = '\0';
}
/* Computes the checksum by adding the values in the register and then subtracting from 255 */
staticintchecksum(byte *check_data)
{
        intsum = 0;
        intii = 0;
        
        for(ii = 0; ii < 32; ii++)
            sum += check_data[ii+62];
            
        sum &= 0xFF;
        
        return0xFF - sum;
}
/* getliner() reads one line from standard input and copies it to line array
 * (but no more than max chars)
 * It does not place the terminating \n line array.
 * Returns line length, or 0 for empty line, or EOF for end-of-file.
 */
intgetliner(charline[], intmax)
{
        intnch = 0;
        intc;
        max = max - 1;          /* Leave room for '\0' */
        while((c = getchar()) != EOF) {
                if(c == '\n')
                        break;
                if(nch < max) {
                        line[nch] = c;
                        nch = nch + 1;
                }
        }
        if(c == EOF && nch == 0)
                returnEOF;
        line[nch] = '\0';
        returnnch;
}
intmain(intargc, char**argv)
{
        inti, voltage, design_capacity, new_design_capacity, new_design_cap_hex;
        intdes_cap[10], cksum = 0;
        byte data[100], writeData[100], unseal_data[10], cfgupdate_data[10], flag_data[10], flag_out[10];
        byte block_data_control[10], data_block_class[10], data_block[10], block_data_checksum[10];
        byte block_data_checksum_data[10], design_capacity_loc[10], design_capacity_data[10];
        byte soft_reset[10], seal_data[10];
        floatremaining_batt_cap = 0.0;
        floatfull_charge_cap = 0.0;
        floatsoc = 0.0;
        floattemp = 0.0;
        floatcurrent = 0.0;
        charnew_design_cap[7], a[10], b[10], tmp[10];
        
    printf("Inside main \n");
    
        init_i2c("/dev/i2c-1");
    
        writeData[0] = 0x00;
        writeData[1] = 0x04;
        
        unseal_data[0] = 0x00;
        unseal_data[1] = 0x00;
        unseal_data[2] = 0x80;
        cfgupdate_data[0] = 0x00;
        cfgupdate_data[1] = 0x13;
        cfgupdate_data[2] = 0x00;
        flag_data[0] = 0x06;
        block_data_control[0] = 0x61;
        block_data_control[1] = 0x00;
        data_block_class[0] = 0x3E;
        data_block_class[1] = 0x52;
        data_block[0] = 0x3F;
        data_block[1] = 0x00;
        block_data_checksum[0] = 0x60;
        design_capacity_loc[0] = 0x4A;
        soft_reset[0] = 0x00;
        soft_reset[1] = 0x42;
        soft_reset[2] = 0x00;
        seal_data[0] = 0x00;
        seal_data[1] = 0x20;
        seal_data[2] = 0x00;
        /* Unseal the gauge - Refer TRM - Pg-14 */
        I2cSendData(BQ27441_ADDR, unseal_data, 3);      // #1
        I2cSendData(BQ27441_ADDR, unseal_data, 3);         
        delay(5);
        printf("The gauge seems to be unsealed. \n");
        
        I2cSendData(BQ27441_ADDR, cfgupdate_data, 3);   // #2
        delay(1000);
        I2cSendData(BQ27441_ADDR, flag_data, 1);        // #3
        delay(5);
        I2cReadData(BQ27441_ADDR, flag_out, 1);
        
        printf("The flag_out is: %x \n", flag_out[0]);
        
        if(CHECK_BIT(flag_out[0], 4)) {
                printf("The gauge is ready to be configured \n");
                
                I2cSendData(BQ27441_ADDR, block_data_control, 2);       // #4
                delay(5);
                I2cSendData(BQ27441_ADDR, data_block_class, 2);         // #5  
                delay(5);
                I2cSendData(BQ27441_ADDR, data_block, 2);               // #6
                delay(5);
                I2cSendData(BQ27441_ADDR, block_data_checksum, 1);      // #7
                delay(5);
                I2cReadData(BQ27441_ADDR, block_data_checksum_data, 1);
                delay(5);
                
                printf("The checksum_data: %x \n", block_data_checksum_data[0]);
                
                if(block_data_checksum_data[0] == 0xE8) {
                        printf("The checksum is as expected. Config will proceed. \n");
                        
                        I2cSendData(BQ27441_ADDR, design_capacity_loc, 1);      // #8
                        delay(5);
                        I2cReadData(BQ27441_ADDR, design_capacity_data, 2);
                        delay(5);
                        
                        //printf("Design capacity data: %x and %x \n", design_capacity_data[0], design_capacity_data[1]);
                        
                        design_capacity = design_capacity_data[0]*16*16 + design_capacity_data[1];
                        delay(5);
                        
                        printf("The current design capacity is: %d mAh \n", design_capacity);
                        printf("Set new design capacity in mAh (ENTER to continue) ?");
                        getliner(new_design_cap, 7);
                        
                        if(new_design_cap != EOF && new_design_cap[0] != 0) {
                                printf("Trying to update the design capacity \n");
                                
                                new_design_capacity = atoi(new_design_cap);                                     // #9
                                printf("Trying to set new design capacity to: %d \n", new_design_capacity);
                                to_hex_16(tmp, new_design_capacity);
                                
                                for(i = 0; i <= 3; i++) {
                                        printf("Output at position %d has %c \n", i, tmp[i]);
                                }
                                
                                des_cap[0] = design_capacity_loc[0];
                                des_cap[1] = (tmp[0] - '0')*16 + (tmp[1] - '0');
                                des_cap[2] = (tmp[2] - '0')*16 + (tmp[3] - '0');
                                
                                printf("Des cap 0: %d ", des_cap[0]);
                                printf("Des cap 1: %d ", des_cap[1]);
                                printf("Des cap 2: %d ", des_cap[2]);
                                I2cSendData(BQ27441_ADDR, des_cap, 3);
                                delay(1000);
                               
                                cksum = checksum(data);                                                         // #10
                                delay(1000);
                                printf("New Checksum found is: %x ", cksum);
                                block_data_checksum[1] = cksum;                                                 // #11   
                                I2cSendData(BQ27441_ADDR, block_data_checksum, 2);
                                delay(5);
                                I2cSendData(BQ27441_ADDR, soft_reset, 3);                                       // #12
                                delay(1000);
                                //printf("Design Cap data 0: %x", data[72]);
                                //printf("Design Cap data :1 %x", data[73]);
                                //design_capacity = data[72]*16*16 + data[73];
                                
                                I2cSendData(BQ27441_ADDR, flag_data, 1);                                        // #13
                                delay(5);
                                I2cReadData(BQ27441_ADDR, flag_out, 1);
                                printf("The flag_out is: %x \n", flag_out[0]);
                                
                                if(!CHECK_BIT(flag_out[0], 4)) {
                                        printf("CFGUPDTE has been exited, configuration done. \n");
                                        I2cSendData(BQ27441_ADDR, seal_data, 1);                                // #14
                                        delay(5);
                                        printf("Gauge has been sealed and is ready for operation \n");
                                }
        
        
                                
                                //printf("New capacity set as: %d mAh \n", design_capacity);
                                
                        } else{
                                printf("Design capacity left unchanged. Now at %d mAh \n", design_capacity);
                        }
                } else{
                        printf("The checksum is not as expected. Config halt. \n");
                }
        } else{
                printf("Cannot proceed with configuration. \n");
                printf("The CFGUPDATE MODE has not been enabled yet. \n");
        }
        while(true) {
                /* Reading the device registers */
                        I2cSendData(BQ27441_ADDR, writeData, 2);
                        I2cReadData(BQ27441_ADDR, data, 100);
                        voltage = data[4]*16*16 + data[3];
                        remaining_batt_cap = data[12]*16*16 + data[11];
                        full_charge_cap = data[14]*16*16 + data[13];
                        soc = (remaining_batt_cap/full_charge_cap)*100;
                        temp = (data[2]*16*16 + data[1])/10.0 - 273.0;
                        current = data[16]*16*16 + data[15];
                        printf("Voltage: %d  mV\n", voltage);
                        printf("Current: %f  mA\n", current);
                        printf("Remaining Battery Capacity: %f  mAh\n", remaining_batt_cap);
                        printf("Full Charge Capacity: %f mAh\n", full_charge_cap);
                        printf("State of Charge: %f p.c. \n", soc);
                        printf("Temperature: %f  Deg C\n", temp);
                        delay(10000);
        }
        
        close(deviceDescriptor);
        endwin();
        return0;
}
控制台日志:
这里的标志是:10
校验和数据:ac