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.

BQ76930: I2C Communication Problem

Part Number: BQ76930
Other Parts Discussed in Thread: BQ76920, , BQ76940, , BQ76952

Dear,

for my BMS under Development, I am using the bq7693007 to balance the 10 Cells.  So this BQ has an ID Address 0x18, as on the Datasheet page 3 (Product Folder Links: BQ76920 BQ76930 BQ76940)

I am using PIC32 to interface woth BQ through I2C that was set at 100kBit.  I then tried to interface with the BQ, no answer dispite the Address 0x18 is well shifted one bit to the left for Write (and shifter 1 bit left +1 for Read).  But the BQ does not answer.

Then I looked to the Website of the BQ76930 Component at TI.com and found that Example under BQ76930EVM then "SLUC583 — bq769x0 I2C Sample Code With CRC" that helps much.  So I adapted the Functions to Write Byte, Write Bytes, and ReadBytes from MSP430 µC to my PIC32 µC.

Under Function "int main(void)" found in file main.c I see that Function InitialisebqMaximo(); and Result = UpdateVoltageFromBqMaximo(); to read the VCell1, as in the File bqMaximo_Ctrl_G2553.h at line 801.

So I intialize my I2C (with the PIC32 Setting), I set BQMAXIMO = 0x18, I itialize my BQ with the Function InitialisebqMaximo(); and then I read VCell1 with the finction UpdateVoltageFromBqMaximo() in a loop.  In the loop I have this UpdateVoltageFromBqMaximo() only.

On the Oscilloscope, here attached the Graph, the I2C RigolDS31.pngdecoder seen Write:30 (which is 0x18 shifter left 1, correct) and Read:31 (which is 0x18 shifter left 1 +1, also correct).  But nothing was red?  I read nothing, and why?

Something wrong, I measure on pin 8. REGOUT of the BQ76930, 1.5V only but why not 3.3V.  Is BQ damaged?  Or because it is not connected to the Battery Cells?

Please help me with this, it is my last Problem with the BMS Board.

Thanks,

Dr. Ayadi  

  • Hello Dr. Ayadi,

    The REGOUT powers assorted internal circuitry, including the communication buffers and coulomb counter which could explain why you are having communication issues. What specific BQ76930xx device do you have? Depending on the specific device, the REGOUT is expected to be either 2.5V or 3.3V. Does it have ~1uF capacitor on the pin? Is there any significant load on the REGOUT pin?

    Is the CAP1 pin reading 3.3V after booting up the part?

    Best Regards,
    Alexis

  • Hi Alexis,

    thanks for the replay I was worried about this issue.

    the used BQ ist bq7693007, that should make REGout 3.3V, but I measure 1.5V only.  I checked my measurement done on that Pin some weeks ago and it was 3.3V, and when I reset the BQ on Pin TS1 at 0V, REGout was gone to 0V too, very normal.

    Maybe this IC is brocken when I was prototyping on its I2C last week, so I will remplace it tomorrow.  

    On Pin REGOUT I put 4.7µF, no much load on the Path, I just power a logic OR with it.  I know it can deliver just 50mA max.

    I measure also 1V only on Pin7 CAP1, but it should be 3.3V, right?

    I still have one new BQ left, if it get burned too, I will need to buy 5 more from mouser.de and 20€ delivery cost, not good.

    Also, from that read function Result = UpdateVoltageFromBqMaximo();  

    I send the value of "Result" on my PC, I read -1V.  That is the Cell1 Voltage, but the BQ is not yet connected to the 10 Cells, an I don't understand why -1V if I2C does not show any replay from BQ. May be the Initial Value or what.

    I will connect the BMS tomorrow with this brocken BQ to the Cells to see if any fire errupts.  If every thing ok, then I can solder the new and last BQ.

    Also, looking to the Graph from the Osci. why it makes 2x Write and 1 x Read? strange really!

    Talk to you tomorrow hopefully with positive result,

    Kamel Ayadi

  • Hi Kamel,

    I hope you had better results.

    I measure also 1V only on Pin7 CAP1, but it should be 3.3V, right?

    That is correct. If it's not reading 3.3V or 0V (when device is in shutdown), there is a chance that the device is damaged. 

    I send the value of "Result" on my PC, I read -1V.  That is the Cell1 Voltage, but the BQ is not yet connected to the 10 Cells, an I don't understand why -1V if I2C does not show any replay from BQ. May be the Initial Value or what

    I'm a little confused from this comment. You tried to communicate with the device while it was powered off and read -1V? I would expect the device to have NAK'd since the device was not even powered on. Do you have any other devices on the same I2C bus line?

    I will connect the BMS tomorrow with this brocken BQ to the Cells to see if any fire errupts.  If every thing ok, then I can solder the new and last BQ.

    Please be careful. 

    Is there also a reason you are also using our BQ76930 device versus one of our newer devices such as the BQ76952? 

    Best Regards,
    Alexis

  • Hi Alexis,

    (could you make this conversation not visible to non-TI, because it is Product and we won't share our Technology with the others, thanks)

    Now, thanks for introducing me the latest BQ76952, I will read its Datasheet and I will replace the BQ76930 with this new one if it fits with the Lithium-Batteries, in the next Tape-out by next month.

    Please stay with me on this issue, I am in the way to solve the Problem, as many things are already explained and solved and the Device works now just fine, but I am strugguling with the Firmware for the Read and Write, as follow.

    I connected the BQ to the Battery Module of 10 Cells Serial and I measure REGOUT 3.3V and CAP1 3.3V, means the BQ is in full function, also the BQ answers tho my µC through I2C and with Bit Knowlage (NAK) at 1 in green on the Decode of the Osciloscope.

    Now struggling with the Firmware (FW) Alexis, you know TI has that FW Example "bq769x0 I2C cCode with CRC", here attached the TI Files (main.c and bqMaximo_Ctrl_G2553.h) to configure the BQ76930 and then in the loop it makes the Read of Cell1 Voltage and stores the Value in the integer "Result". 

    My Problem, is that I am not familiar with µCs from Texas Instruments, so I must adopt the Code with the Read and Write of PIC32, I am good with PIC32 but not MC.

    Then I integrated the two Files from the Example in my FW Project, and I must adjust the 3 Functions (Write one Byte, Write Bytes, Read Bytes) with my Write and Read Functions of Pic32.  With my effort on that, I compile and flash the Firmware and I have activated ones the BQ Configuration Function called InitialisebqMaximo(); and I observe on the Scope I2C.

    Attached is what I get on the Scope and I know my Write and Read are not fine in the Functions found in main.c and called:

    int I2CSendByte(...

    int I2CSendBytes(... 

    int I2CReadBytes(...

    Could you help me just for these three Functions, if I can show you how I integrated my Read and Write in them? they are here attached under app_i2c.c and app_i2c.h

    I need help just for the 3 mentioned Functions above and I am 99% sure the first one is fine, but Write and Read multiple Bytes is my Problem, thanks for the Support.

    Ones this P

    /*******************************************************************************
      MPLAB Harmony Application Source File
    
      Company:
        Microchip Technology Inc.
    
      File Name:
        app_i2c.c
    
      Summary:
        This file contains the source code for the MPLAB Harmony application.
    
      Description:
        This file contains the source code for the MPLAB Harmony application.  It
        implements the logic of the application's state machine and it may call
        API routines of other MPLAB Harmony modules in the system, such as drivers,
        system services, and middleware.  However, it does not call any of the
        system interfaces (such as the "Initialize" and "Tasks" functions) of any of
        the modules in the system or make any assumptions about when those functions
        are called.  That is the responsibility of the configuration-specific system
        files.
     *******************************************************************************/
    
    // *****************************************************************************
    // *****************************************************************************
    // Section: Included Files
    // *****************************************************************************
    // *****************************************************************************
    
    #include "app_i2c.h"
    #include "user.h"
    #include <string.h>
    //#include "bqMaximo_Ctrl_G2553.h"
    
    // *****************************************************************************
    // *****************************************************************************
    // Section: Global Data Definitions
    // *****************************************************************************
    // *****************************************************************************
    
    /* Size of the string written to BQ must be less than or equal to the BQ Register */
    static uint8_t  txBQ[2];
    static uint8_t  rxBQ[2];
    
    #define txBQ_SIZE               (sizeof(txBQ))
    #define rxBQ_SIZE               (sizeof(rxBQ))
    
    //uint8_t WR_BQ_ADDR = (APP_I2C_BQ_ADDR << 1);
    //uint8_t RD_BQ_ADDR = (APP_I2C_BQ_ADDR << 1) | 0x01; 
    
    //#define APP_I2C_BQ_RX_BUFFER_SIZE               2  //APP_I2C_BQ_TEST_DATA_SIZE
    //#define APP_I2C_BQ_TX_BUFFER_SIZE               3  //(APP_I2C_BQ_TEST_DATA_SIZE + APP_I2C_BQ_NUM_ADDR_BYTES)
    
    #define APP_I2C_BQ_NUM_ADDR_BYTES               1
    
    // *****************************************************************************
    /* Application Data
    
      Summary:
        Holds application data
    
      Description:
        This structure holds the application's data.
    
      Remarks:
        This structure should be initialized by the APP_Initialize function.
        Application strings and buffers are be defined outside this structure.
    */
    
    //APP_I2C_DATA app_i2cData;
    
    //static uint8_t testTxData[APP_I2C_BQ_TX_BUFFER_SIZE] = {0};
    //static uint8_t testRxData[APP_I2C_BQ_RX_BUFFER_SIZE] = {0};
    
    
    APP_STATES state;
    volatile APP_TRANSFER_STATUS transferStatus;
    uint8_t ackData = 0;
    
    // *****************************************************************************
    // *****************************************************************************
    // Section: Application Callback Functions
    // *****************************************************************************
    // *****************************************************************************
    
    void APP_I2CCallback(uintptr_t context )
    {
        APP_TRANSFER_STATUS* transferStatus = (APP_TRANSFER_STATUS*)context;
    
        if(I2C2_ErrorGet() == I2C_ERROR_NONE)
        {
            if (transferStatus)
            {
                *transferStatus = APP_TRANSFER_STATUS_SUCCESS;
            }
        }
        else
        {
            if (transferStatus)
            {
                *transferStatus = APP_TRANSFER_STATUS_ERROR;
            }
        }
    }
    
    // *****************************************************************************
    // *****************************************************************************
    // Section: Application Initialization and State Machine Functions
    // *****************************************************************************
    // *****************************************************************************
    
    void APP_I2C_Initialize( void )
    {
        state = APP_STATE_EEPROM_STATUS_VERIFY;
        transferStatus = APP_TRANSFER_STATUS_ERROR;
        ackData = 0;
        
        txBQ[0] = 0x00;
        txBQ[1] = 0x00;
        APP_I2C_Tasks();
    }
    
    // *****************************************************************************
    // *****************************************************************************
    // Section: Application  APP_Tasks of State Machine Functions
    // *****************************************************************************
    // *****************************************************************************
    
    void APP_I2C_Tasks( void )
    {
        /* Check the application's current state. */
     
        switch (state)
        {
            case APP_STATE_EEPROM_STATUS_VERIFY:
    
                /* Register the TWIHS Callback with transfer status as context */
                I2C2_CallbackRegister( APP_I2CCallback, (uintptr_t)&transferStatus );
    
               /* Verify if EEPROM is ready to accept new requests */
                transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                I2C2_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);
    
                state = APP_STATE_EEPROM_WRITE;
                break;
    
            case APP_STATE_EEPROM_WRITE:
    
                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    /* Write data to EEPROM */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C2_Write(APP_AT24MAC_DEVICE_ADDR, &testTxData, APP_TRANSMIT_DATA_LENGTH);
                    state = APP_STATE_EEPROM_WAIT_WRITE_COMPLETE;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    /* EEPROM is not ready to accept new requests */
                    state = APP_STATE_XFER_ERROR;
                }
                break;
    
            case APP_STATE_EEPROM_WAIT_WRITE_COMPLETE:
    
                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    /* Read the status of internal write cycle */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C2_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);
                    state = APP_STATE_EEPROM_CHECK_INTERNAL_WRITE_STATUS;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    state = APP_STATE_XFER_ERROR;
                }
                break;
    
             case APP_STATE_EEPROM_CHECK_INTERNAL_WRITE_STATUS:
    
                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                   // state = APP_STATE_EEPROM_READ;
                    state = APP_STATE_XFER_SUCCESSFUL;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    /* EEPROM's internal write cycle is not complete. Keep checking. */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C2_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);
                }
                break;
    
            case APP_STATE_EEPROM_READ:
    
                transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                /* Read the data from the page written earlier */
                I2C2_WriteRead(APP_AT24MAC_DEVICE_ADDR, &testTxData, APP_RECEIVE_DUMMY_WRITE_LENGTH,  &testRxData, APP_RECEIVE_DATA_LENGTH);
    
                state = APP_STATE_EEPROM_WAIT_READ_COMPLETE;
    
                break;
    
            case APP_STATE_EEPROM_WAIT_READ_COMPLETE:
    
                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    //state = APP_STATE_VERIFY;
                    state = APP_STATE_XFER_SUCCESSFUL;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    state = APP_STATE_XFER_ERROR;
                }
                break;
    
            case APP_STATE_VERIFY:
    
                if (memcmp(&testTxData[2], &testRxData[0], APP_RECEIVE_DATA_LENGTH) != 0)
                {
                    /* It means received data is not same as transmitted data */
                    state = APP_STATE_XFER_ERROR;
                }
                else
                {
                    /* It means received data is same as transmitted data */
                    state = APP_STATE_XFER_SUCCESSFUL;
                }
                break;
    
            case APP_STATE_XFER_SUCCESSFUL:
            {
                break;
            }
            case APP_STATE_XFER_ERROR:
            {
                break;
            }
            default:
                break;
        }
    }
    
    // *****************************************************************************
    //
    // Section: Application Initialization and State Machine Functions
    // Follow are BQ7693007 Functions
    //
    // *****************************************************************************
    
    #include <stdbool.h>
    //#include <bqMaximo_Ctrl_G2553.h>
    #include <math.h>
    #include <float.h>
    #include <stdlib.h>
    //#include <plib_i2c2_master.h>
    
    /* Disable the I2C Master interrupt */
    //  IEC2CLR = _IEC2_I2C2MIE_MASK;
    
    RegisterGroup Registers;
    
    const unsigned int OVPThreshold = 4300;
    const unsigned int UVPThreshold = 2500;
    const unsigned char SCDDelay = SCD_DELAY_100us;
    const unsigned char SCDThresh = SCD_THRESH_89mV_44mV;
    const unsigned char OCDDelay = OCD_DELAY_320ms;
    const unsigned char OCDThresh = OCD_THRESH_22mV_11mV;
    const unsigned char OVDelay = OV_DELAY_2s;
    const unsigned char UVDelay = UV_DELAY_8s;
    
    unsigned int CellVoltage[15];
    float Gain = 0;
    int iGain = 0;
    
    int I2CSendByte(unsigned char I2CSlaveAddress, unsigned char data)
    {
        APP_AT24MAC_DEVICE_ADDR = I2CSlaveAddress;
        testTxData[0] = data;
        APP_ACK_DATA_LENGTH = 1;
        
        state = APP_STATE_EEPROM_WRITE;
        APP_I2C_Tasks();
          
        return 0;
        
    }
    
    int I2CSendBytes(unsigned char I2CSlaveAddress, unsigned char *DataBuffer, unsigned int ByteCount, unsigned int *SentByte)
    {
        unsigned int NumberOfBytesSent = 0;
        unsigned char *DataPointer;
    //I2C2_Write(APP_AT24MAC_DEVICE_ADDR, &testTxData, APP_TRANSMIT_DATA_LENGTH);
    
        APP_AT24MAC_DEVICE_ADDR = I2CSlaveAddress;
    #define    APP_TRANSMIT_DATA_LENGTH  ByteCount
        DataPointer = DataBuffer;
    
        for(NumberOfBytesSent = 0; NumberOfBytesSent < ByteCount; NumberOfBytesSent++)
        {
           // UCB0TXBUF= *DataPointer;  // send data
            testTxData[NumberOfBytesSent] = *DataPointer;
            *SentByte = NumberOfBytesSent;
            //UCB0CTL1 |= UCTXSTP;				//send stop condition
            state = APP_STATE_EEPROM_WRITE;
            APP_I2C_Tasks();
        }
    
        *SentByte =  NumberOfBytesSent;
        
        return 0; 
    
    }
    
    int I2CWriteRegisterByte(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char Data)
    {
        unsigned char DataBuffer[2];
        unsigned int SentByte = 0;
    
    
        DataBuffer[0] = Register;
        DataBuffer[1] = Data;
    
        return(I2CSendBytes(I2CSlaveAddress, DataBuffer, 2, &SentByte));
    }
    
    int I2CWriteRegisterByteWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char Data)
    {
        unsigned char DataBuffer[4];
        unsigned int SentByte = 0;
    
        DataBuffer[0] = I2CSlaveAddress << 1;
        DataBuffer[1] = Register;
        DataBuffer[2] = Data;
        DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);
    
        return(I2CSendBytes(I2CSlaveAddress, DataBuffer + 1, 3, &SentByte));
    }
    
    int I2CWriteRegisterWordWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int Data)
    {
        unsigned char DataBuffer[6];
        unsigned int SentByte = 0;
    
        DataBuffer[0] = I2CSlaveAddress << 1;
        DataBuffer[1] = Register;
        DataBuffer[2] = LOW_BYTE(Data);
        DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);
        DataBuffer[4] = HIGH_BYTE(Data);
        DataBuffer[5] = CRC8(DataBuffer + 4, 1, CRC_KEY);
    
        return(I2CSendBytes(I2CSlaveAddress, DataBuffer + 1, 5, &SentByte));
    }
    
    int I2CWriteBlockWithCRC(unsigned char I2CSlaveAddress, unsigned char StartAddress, unsigned char *Buffer, unsigned char Length)
    {
        unsigned char *BufferCRC, *Pointer;
        int i;
        unsigned int SentByte = 0;
        int result;
    
        BufferCRC = (unsigned char*)malloc(2*Length + 2);
        if (NULL == BufferCRC)
                return -1;
    
        Pointer = BufferCRC;
        *Pointer = I2CSlaveAddress << 1;
        Pointer++;
        *Pointer = StartAddress;
        Pointer++;
        *Pointer = *Buffer;
        Pointer++;
        *Pointer = CRC8(BufferCRC, 3, CRC_KEY);
    
        for(i = 1; i < Length; i++)
        {
        Pointer++;
        Buffer++;
        *Pointer = *Buffer;
                *(Pointer + 1) = CRC8(Pointer, 1, CRC_KEY);
                Pointer++;
        }
    
        result = I2CSendBytes(I2CSlaveAddress, BufferCRC + 1, 2*Length + 1, &SentByte);
    
        free(BufferCRC);
        BufferCRC = NULL;
    
        return result;
    }
    
    int I2CWriteRegisterWord(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int Data)
    {
        unsigned char DataBuffer[3];
        unsigned int SentByte = 0;
    
        DataBuffer[0] = Register;
        DataBuffer[1] = LOWBYTE(Data);
        DataBuffer[2] = HIGHBYTE(Data);
    
        return(I2CSendBytes(I2CSlaveAddress, DataBuffer, 3, &SentByte));
    }
    
    int I2CReadBytes(unsigned char I2CSlaveAddress, unsigned char *DataBuffer, unsigned int ExpectedByteNumber, unsigned int *NumberOfReceivedBytes)
    {
        unsigned char *DataPointer;
        unsigned int *NumberOfReceivedBytesPointer;
    
    //I2C2_WriteRead(APP_AT24MAC_DEVICE_ADDR, &testTxData, APP_RECEIVE_DUMMY_WRITE_LENGTH,  &testRxData, APP_RECEIVE_DATA_LENGTH);
     #define   APP_RECEIVE_DUMMY_WRITE_LENGTH  0
        NumberOfReceivedBytesPointer = NumberOfReceivedBytes;
        *NumberOfReceivedBytesPointer = 0;
    
    
        DataPointer = DataBuffer;
        APP_AT24MAC_DEVICE_ADDR = I2CSlaveAddress;
    
        for(*NumberOfReceivedBytesPointer = 0; *NumberOfReceivedBytesPointer < ExpectedByteNumber; (*NumberOfReceivedBytesPointer)++)
        {
            state = APP_STATE_EEPROM_READ;
            APP_I2C_Tasks();      
            *DataPointer = testRxData;
            DataPointer++;
        }   
        return 0;
    
    }
    
    int I2CReadRegisterByte(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Data)
    {
        unsigned char TargetRegister = Register;
        unsigned int SentByte = 0;
        unsigned int ReadDataCount = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
        WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
        ReadStatus = I2CReadBytes(I2CSlaveAddress, Data, 1, &ReadDataCount);
    
        if (ReadStatus != 0 || WriteStatus != 0)
        {
                return -1;
        }
    
        return 0;
    }
    
    int I2CReadBlock(unsigned char I2CSlaveAddress, unsigned char StartRegisterAddress, unsigned char *Buffer, unsigned int BlockSize, unsigned int *NumberOfBytes)
    {
        unsigned char TargetRegister = StartRegisterAddress;
        unsigned int SentByte = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
        WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
        ReadStatus = I2CReadBytes(I2CSlaveAddress, Buffer, BlockSize, NumberOfBytes);
    
        if(ReadStatus != 0 || WriteStatus != 0)
        {
                return -1;
        }
    
        return 0;
    }
    
    unsigned char CRC8(unsigned char *ptr, unsigned char len,unsigned char key)
    {
        unsigned char i;
        unsigned char crc=0;
        while(len--!=0)
        {
            for(i=0x80; i!=0; i/=2)
            {
                if((crc & 0x80) != 0)
                {
                        crc *= 2;
                        crc ^= key;
                }
                else
                        crc *= 2;
    
                if((*ptr & i)!=0)
                        crc ^= key;
            }
            ptr++;
        }
        return(crc);
    }
    
    int I2CReadRegisterByteWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Data)
    {
        unsigned char TargetRegister = Register;
        unsigned int SentByte = 0;
        unsigned char ReadData[2];
        unsigned int ReadDataCount = 0;
        unsigned char CRCInput[2];
        unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
        WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
        ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 2, &ReadDataCount);
    
        if (ReadStatus != 0 || WriteStatus != 0)
        {
            return -1;
        }
    
        CRCInput[0] = (I2CSlaveAddress << 1) + 1;
        CRCInput[1] = ReadData[0];
    
        CRC = CRC8(CRCInput, 2, CRC_KEY);
    
        if (CRC != ReadData[1])
            return -1;
    
        *Data = ReadData[0];
        return 0;
    }
    
    int I2CReadRegisterWordWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int *Data)
    {
        unsigned char TargetRegister = Register;
        unsigned int SentByte = 0;
        unsigned char ReadData[4];
        unsigned int ReadDataCount = 0;
        unsigned char CRCInput[2];
        unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
        WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
        ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 4, &ReadDataCount);
    
        if (ReadStatus != 0 || WriteStatus != 0)
        {
            return -1;
        }
    
        CRCInput[0] = (I2CSlaveAddress << 1) + 1;
        CRCInput[1] = ReadData[0];
    
        CRC = CRC8(CRCInput, 2, CRC_KEY);
    
        if (CRC != ReadData[1])
            return -1;
    
        CRC = CRC8(ReadData + 2, 1, CRC_KEY);
    
        if (CRC != ReadData[3])
            return -1;
    
        *Data = ReadData[0];
    
        *Data = (*Data << 8) + ReadData[2];
    
        return 0;
    }
    
    int I2CReadBlockWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Buffer, unsigned char Length)
    {
        unsigned char TargetRegister = Register;
        unsigned int SentByte = 0;
        unsigned char *ReadData = NULL, *StartData = NULL;
        unsigned int ReadDataCount = 0;
        unsigned char CRCInput[2];
        unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
        int i;
    
        StartData = (unsigned char *)malloc(2 * Length);
    
        if (NULL == StartData)
        	return -1;
    
        ReadData = StartData;
    
        WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
        ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 2 * Length, &ReadDataCount);
    
        if (ReadStatus != 0 || WriteStatus != 0)
        {
            free(StartData);
            StartData = NULL;
    
            return -1;
        }
    
        CRCInput[0] = (I2CSlaveAddress << 1) + 1;
        CRCInput[1] = *ReadData;
    
        CRC = CRC8(CRCInput, 2, CRC_KEY);
    
        ReadData++;
        if (CRC != *ReadData)
        {
            free(StartData);
            StartData = NULL;
            return -1;
        }
        else
            *Buffer = *(ReadData - 1);
    
        for(i = 1; i < Length; i++)
        {
            ReadData++;
            CRC = CRC8(ReadData, 1, CRC_KEY);
            ReadData++;
            Buffer++;
    
            if (CRC != *ReadData)
            {
                free(StartData);
                StartData = NULL;
    
                return -1;
            }
            else
                *Buffer = *(ReadData - 1);
        }
    
        free(StartData);
        StartData = NULL;
    
        return 0;
    }
    
    int GetADCGainOffset()
    {
        int result;
    
        result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCGAIN1, &(Registers.ADCGain1.ADCGain1Byte));
        result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCGAIN2, &(Registers.ADCGain2.ADCGain2Byte));
        result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCOFFSET, &(Registers.ADCOffset));
    
        return result;
    }
    
    int ConfigureBqMaximo()
    {
        int result = 0;
        unsigned char bqMaximoProtectionConfig[5];
    
        result = I2CWriteBlockWithCRC(BQMAXIMO, PROTECT1, &(Registers.Protect1.Protect1Byte), 5);
    
        result = I2CReadBlockWithCRC(BQMAXIMO, PROTECT1, bqMaximoProtectionConfig, 5);
    
        if(bqMaximoProtectionConfig[0] != Registers.Protect1.Protect1Byte
                        || bqMaximoProtectionConfig[1] != Registers.Protect2.Protect2Byte
                        || bqMaximoProtectionConfig[2] != Registers.Protect3.Protect3Byte
                        || bqMaximoProtectionConfig[3] != Registers.OVTrip
                        || bqMaximoProtectionConfig[4] != Registers.UVTrip)
        {
            result = -1;
        }
    
        return result;
    }
    
    int InitialisebqMaximo()
    {
        int result = 0;
    
        Registers.Protect1.Protect1Bit.SCD_DELAY = SCDDelay;
        Registers.Protect1.Protect1Bit.SCD_THRESH = SCDThresh;
        Registers.Protect2.Protect2Bit.OCD_DELAY = OCDDelay;
        Registers.Protect2.Protect2Bit.OCD_THRESH = OCDThresh;
        Registers.Protect3.Protect3Bit.OV_DELAY = OVDelay;
        Registers.Protect3.Protect3Bit.UV_DELAY = UVDelay;
    
        result = GetADCGainOffset();
    
        Gain = (365 + ((Registers.ADCGain1.ADCGain1Byte & 0x0C) << 1) + ((Registers.ADCGain2.ADCGain2Byte & 0xE0)>> 5)) / 1000.0;
        iGain = 365 + ((Registers.ADCGain1.ADCGain1Byte & 0x0C) << 1) + ((Registers.ADCGain2.ADCGain2Byte & 0xE0)>> 5);
    
        Registers.OVTrip = (unsigned char)((((unsigned short)((OVPThreshold - Registers.ADCOffset)/Gain + 0.5) - OV_THRESH_BASE) >> 4) & 0xFF);
        Registers.UVTrip = (unsigned char)((((unsigned short)((UVPThreshold - Registers.ADCOffset)/Gain + 0.5) - UV_THRESH_BASE) >> 4) & 0xFF);
    
        result = ConfigureBqMaximo();
    
        return result;
    }
    
    int UpdateVoltageFromBqMaximo()
    {
        int Result = 0, i = 0;
        unsigned char *pRawADCData = NULL;
        unsigned int iTemp = 0;
        unsigned long lTemp = 0;
    
        Result = I2CReadBlockWithCRC(BQMAXIMO, \
                        VC1_HI_BYTE, \
                        &(Registers.VCell1.VCell1Byte.VC1_HI), \
                        30);
        
        /* Result = I2CReadBlockWithCRC(BQMAXIMO, \
                        VC1_HI_BYTE, \
                        &(Registers.VCell2.VCell2Byte.VC2_HI), \
                        30);*/
        
        pRawADCData = &Registers.VCell1.VCell1Byte.VC1_HI;
        for (i = 0; i < 15; i++)
        {
            iTemp = (unsigned int)(*pRawADCData << 8) + *(pRawADCData + 1);
            lTemp = ((unsigned long)iTemp * iGain)/1000;
            lTemp += Registers.ADCOffset;
            CellVoltage[i] = lTemp;
            pRawADCData += 2;
        }
    
        return Result;
    }
    
    int Read_BQ(void)
    {
        int Result;
    
       // WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
        //DISABLE_INT;
    
       // ClockInitialise();
    
       // I2CInitialise();
    
        //InitialisebqMaximo();
    
       // while(1)
        {
        	Result = UpdateVoltageFromBqMaximo();
        }
       // Result=0x02e2;
        printf("BQ          : Cell Nr.1 = %d.%02d V \r\n", (int)Result, (int)((Result - (int)Result)*100.0));
        printf("\n");
        
        return Result;
    }
    
    
    
    /*******************************************************************************
     End of File
     */
    
    app_i2c.hroblem with the 3 Functions are solved, I can continue finishing the development of my BMS.

    /*
     * main.c
     *
     * This module demonstrates operation of CRC with the bq769x0 family
     * AFE devices using a MSP430G2553 
     *
     * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 
     * 
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    */
    
    #include <msp430.h> 
    #include <stdbool.h>
    #include <bqMaximo_Ctrl_G2553.h>
    #include <math.h>
    #include <float.h>
    #include <stdlib.h>
    /*
     * main.c
     */
    
    RegisterGroup Registers;
    
    const unsigned int OVPThreshold = 4300;
    const unsigned int UVPThreshold = 2500;
    const unsigned char SCDDelay = SCD_DELAY_100us;
    const unsigned char SCDThresh = SCD_THRESH_89mV_44mV;
    const unsigned char OCDDelay = OCD_DELAY_320ms;
    const unsigned char OCDThresh = OCD_THRESH_22mV_11mV;
    const unsigned char OVDelay = OV_DELAY_2s;
    const unsigned char UVDelay = UV_DELAY_8s;
    
    unsigned int CellVoltage[15];
    float Gain = 0;
    int iGain = 0;
    
    void ClockInitialise()
    {
    	DCOCTL = 0xE0;	//DCO = 7, MOD = 0
    
    	BCSCTL1 &= 0x8F;  //RSEL = 0, DCOR = 0, 20MHz Clock
    
    	BCSCTL2 = 0x0;
    
    	BCSCTL3 = 0;
    }
    
    void TimerAInit()
    {
    	TA0CTL |= TASSEL1;
    	TA0CTL &= ~TASSEL0;
    
    	TA0CTL |= MC1;
    	TA0CTL &= ~MC0;
    
    	TA0CTL &= ~TAIE;
    
    }
    
    void I2CInitialise()
    {
    	P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0, P1.6 for SCL and P1.7 for SDA
    	P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0, P1.6 for SCL and P1.7 for SDA
    
    	ADC10AE0 &= 0x3F;
    	CAPD &= 0x3F;
    
    	UCB0CTL1 |= UCSWRST;                      // Enable SW reset, hold USCI logic in reset state
    	UCB0CTL0 = UCMODE_3 + UCSYNC;			//set to I2C mode, sync=1
    	UCB0BR0 = 20;
    	UCB0BR1 = 0;
    
    	UCB0I2CIE = 0;
        IE2 &= ~(UCB0TXIE + UCB0RXIE);	//disable interrupts
    
        UCB0CTL1 |= UCSSEL_2;
        UCB0CTL1 &= ~UCSWRST;
    }
    
    int I2CSendByte(unsigned char I2CSlaveAddress, unsigned char data)
    {
    	unsigned long int DelayCounter = 0;
    
    	UCB0CTL0 |= UCMST;
    	UCB0I2CSA = I2CSlaveAddress;
    
    	 UCB0CTL1 |= UCTR; //data in transmit direction
    	 UCB0CTL1 |= UCTXSTT; //Generate Start Condition
    	 	 	 	 	 	  //Send Start Byte
    
    	 while(!(IFG2 & UCB0TXIFG))  //if UCB0TXIFG != 0, wait here
    	 {
    		 DelayCounter ++;
    		 if (DelayCounter >= DELAY_LIMIT)
    			 break;
    	 }
    
    	 if (DelayCounter >= DELAY_LIMIT)
    		 return -1;
    
    	 UCB0TXBUF = data;				// send the data
    
    	 DelayCounter = 0;
    
    	 while(DelayCounter < DELAY_LIMIT && !(IFG2 & UCB0TXIFG))
    	 {
    		 DelayCounter++;
    	 }
    
    	 if (DelayCounter >= DELAY_LIMIT)
    		 return -1;
    
    	 UCB0CTL1 |= UCTXSTP;			//send stop bit
    
    	 DelayCounter = 0;
    
    	 while(DelayCounter < DELAY_LIMIT && (UCB0CTL1 & UCTXSTP))
    	 {
    		 DelayCounter++;
    	 }
    
    	 if (DelayCounter >= DELAY_LIMIT)	//check if NACK condition occurred
    		 return -1;
    	 else
    		 return 0;
    
    }
    
    int I2CSendBytes(unsigned char I2CSlaveAddress, unsigned char *DataBuffer, unsigned int ByteCount, unsigned int *SentByte)
    {
    	unsigned long int DelayCounter = 0;
        unsigned int NumberOfBytesSent = 0;
        unsigned char *DataPointer;
    
    	UCB0CTL0 |= UCMST;
    	UCB0I2CSA = I2CSlaveAddress;
    
         DataPointer = DataBuffer;
    
    	 UCB0CTL1 |= UCTR; //data in transmit direction
    	 UCB0CTL1 |= UCTXSTT; //Generate Start Condition
    	 	 	 	 	 	  //Send Start Byte
    
    	 while(!(IFG2 & UCB0TXIFG))  //if UCTXSTT != 0, wait here
    	 {
    		 DelayCounter ++;
    		 if (DelayCounter > DELAY_LIMIT)
    			 break;
    	 }
    
    	 if (DelayCounter >= DELAY_LIMIT)   //check if NACK condition occurred
    	 {
    		 *SentByte = NumberOfBytesSent;
    		 UCB0CTL1 |= UCTXSTP;
    		 return -1;
    	 }
    
    	 for(NumberOfBytesSent = 0; NumberOfBytesSent < ByteCount; NumberOfBytesSent++)
    	 {
    		 UCB0TXBUF= *DataPointer;
    
    		 DelayCounter = 0;
    
    		 while(DelayCounter < DELAY_LIMIT && (!(IFG2 & UCB0TXIFG) || (UCB0CTL1 & UCTXSTT)))	//check if the byte has been sent
    		 {
    			 DelayCounter++;
    		 }
    
    		 if (DelayCounter >= DELAY_LIMIT)	//check if NACK condition occurred
    		 {
    			 *SentByte = NumberOfBytesSent;
    			 UCB0CTL1 |= UCTXSTP;				//send stop condition
    			 return -1;
    		 }
    
    		 DataPointer++;
    	 }
    
    	 IFG2 &= ~UCB0TXIFG;
    	 UCB0CTL1 |= UCTXSTP;		//send stop bit
    
    	 DelayCounter = 0;
    
    	 while(DelayCounter < DELAY_LIMIT && ((UCB0CTL1 & UCTXSTP)))
    	 {
    		 DelayCounter++;
    	 }
    
    	 *SentByte =  NumberOfBytesSent;
    
    	 if (DelayCounter >= DELAY_LIMIT)	//check if NACK condition occurred
    	 {
    		 UCB0CTL1 |= UCSWRST;
    		 return -1;
    	 }
    	 else
    		 return 0;
    }
    
    int I2CWriteRegisterByte(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char Data)
    {
    	unsigned char DataBuffer[2];
    	unsigned int SentByte = 0;
    
    
    	DataBuffer[0] = Register;
    	DataBuffer[1] = Data;
    
    	return(I2CSendBytes(I2CSlaveAddress, DataBuffer, 2, &SentByte));
    }
    
    int I2CWriteRegisterByteWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char Data)
    {
    	unsigned char DataBuffer[4];
    	unsigned int SentByte = 0;
    
        DataBuffer[0] = I2CSlaveAddress << 1;
    	DataBuffer[1] = Register;
    	DataBuffer[2] = Data;
    	DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);
    
    	return(I2CSendBytes(I2CSlaveAddress, DataBuffer + 1, 3, &SentByte));
    }
    
    int I2CWriteRegisterWordWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int Data)
    {
    	unsigned char DataBuffer[6];
    	unsigned int SentByte = 0;
    
        DataBuffer[0] = I2CSlaveAddress << 1;
    	DataBuffer[1] = Register;
    	DataBuffer[2] = LOW_BYTE(Data);
    	DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);
    	DataBuffer[4] = HIGH_BYTE(Data);
    	DataBuffer[5] = CRC8(DataBuffer + 4, 1, CRC_KEY);
    
    	return(I2CSendBytes(I2CSlaveAddress, DataBuffer + 1, 5, &SentByte));
    }
    
    int I2CWriteBlockWithCRC(unsigned char I2CSlaveAddress, unsigned char StartAddress, unsigned char *Buffer, unsigned char Length)
    {
    	unsigned char *BufferCRC, *Pointer;
    	int i;
    	unsigned int SentByte = 0;
    	int result;
    
    	BufferCRC = (unsigned char*)malloc(2*Length + 2);
    	if (NULL == BufferCRC)
    		return -1;
    
    	Pointer = BufferCRC;
    	*Pointer = I2CSlaveAddress << 1;
    	Pointer++;
    	*Pointer = StartAddress;
    	Pointer++;
    	*Pointer = *Buffer;
    	Pointer++;
    	*Pointer = CRC8(BufferCRC, 3, CRC_KEY);
    
    	for(i = 1; i < Length; i++)
    	{
            Pointer++;
            Buffer++;
            *Pointer = *Buffer;
    		*(Pointer + 1) = CRC8(Pointer, 1, CRC_KEY);
    		Pointer++;
    	}
    
    	result = I2CSendBytes(I2CSlaveAddress, BufferCRC + 1, 2*Length + 1, &SentByte);
    
    	free(BufferCRC);
    	BufferCRC = NULL;
    
    	return result;
    }
    
    int I2CWriteRegisterWord(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int Data)
    {
    	unsigned char DataBuffer[3];
    	unsigned int SentByte = 0;
    
    	DataBuffer[0] = Register;
    	DataBuffer[1] = LOWBYTE(Data);
    	DataBuffer[2] = HIGHBYTE(Data);
    
    	return(I2CSendBytes(I2CSlaveAddress, DataBuffer, 3, &SentByte));
    }
    
    int I2CReadBytes(unsigned char I2CSlaveAddress, unsigned char *DataBuffer, unsigned int ExpectedByteNumber, unsigned int *NumberOfReceivedBytes)
    {
    	unsigned long int DelayCounter = 0;
        unsigned char *DataPointer;
        unsigned int *NumberOfReceivedBytesPointer;
    
        NumberOfReceivedBytesPointer = NumberOfReceivedBytes;
        *NumberOfReceivedBytesPointer = 0;
    
        UCB0CTL0 |= UCMST;
        DataPointer = DataBuffer;
    	UCB0I2CSA = I2CSlaveAddress;
    
    	UCB0CTL1 &= ~(UCTR); //data in receive direction
    
    	UCB0CTL1 |= UCTXSTT; //Generate Start Condition
    
    	 while((UCB0CTL1 & UCTXSTT)
    			 )  //if UCTXSTT != 0, wait here
    	 {
    		 DelayCounter ++;
    		 if (DelayCounter >= DELAY_LIMIT)
    			 break;
    	 }
    
    	 if (DelayCounter >= DELAY_LIMIT || UCB0STAT & UCNACKIFG)   //check if NACK condition occurred
    		 return -1;
    
    	 for(*NumberOfReceivedBytesPointer = 0; *NumberOfReceivedBytesPointer < ExpectedByteNumber; (*NumberOfReceivedBytesPointer)++)
    	 {
    		 if(*NumberOfReceivedBytesPointer + 1 == ExpectedByteNumber)
    			 UCB0CTL1 |= UCTXSTP;
    
    		 DelayCounter = 0;
    
    		 while(DelayCounter < DELAY_LIMIT && !(IFG2 & UCB0RXIFG))
    		 {
    			 DelayCounter++;
    		 }
    
    		 if(DelayCounter == DELAY_LIMIT)
    		 {
    			 UCB0CTL1 |= UCSWRST;   //if I2C overtime condition occurred, reset I2C engine
    			 return -1;
    		 }
    
    		 *DataPointer = UCB0RXBUF;
    
    		 DataPointer++;
    	 }
    
    	 DelayCounter = 0;
    	 while(DelayCounter < DELAY_LIMIT && (UCB0CTL1 & UCTXSTP))
    	 {
    		 DelayCounter++;
    	 }
    
    	 if(DelayCounter >= DELAY_LIMIT)
    	 {
    		 UCB0CTL1 |= UCSWRST;
    		 return -1;
    	 }
    
    	 return 0;
    
    }
    
    int I2CReadRegisterByte(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Data)
    {
    	unsigned char TargetRegister = Register;
    	unsigned int SentByte = 0;
    	unsigned int ReadDataCount = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
    	WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
    	ReadStatus = I2CReadBytes(I2CSlaveAddress, Data, 1, &ReadDataCount);
    
    	if (ReadStatus != 0 || WriteStatus != 0)
    	{
    		return -1;
    	}
    
    	return 0;
    }
    
    int I2CReadBlock(unsigned char I2CSlaveAddress, unsigned char StartRegisterAddress, unsigned char *Buffer, unsigned int BlockSize, unsigned int *NumberOfBytes)
    {
    	unsigned char TargetRegister = StartRegisterAddress;
    	unsigned int SentByte = 0;
    	int ReadStatus = 0;
    	int WriteStatus = 0;
    
    	WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
    	ReadStatus = I2CReadBytes(I2CSlaveAddress, Buffer, BlockSize, NumberOfBytes);
    
    	if(ReadStatus != 0 || WriteStatus != 0)
    	{
    		return -1;
    	}
    
    	return 0;
    }
    
    unsigned char CRC8(unsigned char *ptr, unsigned char len,unsigned char key)
    {
    	unsigned char i;
    	unsigned char crc=0;
    	while(len--!=0)
    	{
    		for(i=0x80; i!=0; i/=2)
    		{
    			if((crc & 0x80) != 0)
    			{
    				crc *= 2;
    				crc ^= key;
    			}
    			else
    				crc *= 2;
    
    			if((*ptr & i)!=0)
    				crc ^= key;
    		}
    		ptr++;
    	}
    	return(crc);
    }
    
    int I2CReadRegisterByteWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Data)
    {
    	unsigned char TargetRegister = Register;
    	unsigned int SentByte = 0;
    	unsigned char ReadData[2];
    	unsigned int ReadDataCount = 0;
    	unsigned char CRCInput[2];
    	unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
    	WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
    	ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 2, &ReadDataCount);
    
    	if (ReadStatus != 0 || WriteStatus != 0)
    	{
    		return -1;
    	}
    
    	CRCInput[0] = (I2CSlaveAddress << 1) + 1;
    	CRCInput[1] = ReadData[0];
    
    	CRC = CRC8(CRCInput, 2, CRC_KEY);
    
    	if (CRC != ReadData[1])
    		return -1;
    
    	*Data = ReadData[0];
    	return 0;
    }
    
    int I2CReadRegisterWordWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned int *Data)
    {
    	unsigned char TargetRegister = Register;
    	unsigned int SentByte = 0;
    	unsigned char ReadData[4];
    	unsigned int ReadDataCount = 0;
    	unsigned char CRCInput[2];
    	unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
    
    	WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
    	ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 4, &ReadDataCount);
    
    	if (ReadStatus != 0 || WriteStatus != 0)
    	{
    		return -1;
    	}
    
    	CRCInput[0] = (I2CSlaveAddress << 1) + 1;
    	CRCInput[1] = ReadData[0];
    
    	CRC = CRC8(CRCInput, 2, CRC_KEY);
    
    	if (CRC != ReadData[1])
    		return -1;
    
    	CRC = CRC8(ReadData + 2, 1, CRC_KEY);
    
    	if (CRC != ReadData[3])
    		return -1;
    
    	*Data = ReadData[0];
    
    	*Data = (*Data << 8) + ReadData[2];
    
    	return 0;
    }
    
    int I2CReadBlockWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Buffer, unsigned char Length)
    {
    	unsigned char TargetRegister = Register;
    	unsigned int SentByte = 0;
    	unsigned char *ReadData = NULL, *StartData = NULL;
    	unsigned int ReadDataCount = 0;
    	unsigned char CRCInput[2];
    	unsigned char CRC = 0;
        int ReadStatus = 0;
        int WriteStatus = 0;
        int i;
    
        StartData = (unsigned char *)malloc(2 * Length);
    
        if (NULL == StartData)
        	return -1;
    
        ReadData = StartData;
    
    	WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    
    	ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 2 * Length, &ReadDataCount);
    
    	if (ReadStatus != 0 || WriteStatus != 0)
    	{
    		free(StartData);
    		StartData = NULL;
    
    		return -1;
    	}
    
    	CRCInput[0] = (I2CSlaveAddress << 1) + 1;
    	CRCInput[1] = *ReadData;
    
    	CRC = CRC8(CRCInput, 2, CRC_KEY);
    
    	ReadData++;
    	if (CRC != *ReadData)
    	{
    		free(StartData);
    		StartData = NULL;
    		return -1;
    	}
    	else
    		*Buffer = *(ReadData - 1);
    
    	for(i = 1; i < Length; i++)
    	{
    		ReadData++;
    		CRC = CRC8(ReadData, 1, CRC_KEY);
    		ReadData++;
    		Buffer++;
    
    		if (CRC != *ReadData)
    		{
    			free(StartData);
    			StartData = NULL;
    
    			return -1;
    		}
    		else
    			*Buffer = *(ReadData - 1);
    	}
    
    	free(StartData);
    	StartData = NULL;
    
    	return 0;
    }
    
    int GetADCGainOffset()
    {
    	int result;
    
    	result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCGAIN1, &(Registers.ADCGain1.ADCGain1Byte));
    	result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCGAIN2, &(Registers.ADCGain2.ADCGain2Byte));
    	result = I2CReadRegisterByteWithCRC(BQMAXIMO, ADCOFFSET, &(Registers.ADCOffset));
    
    	return result;
    }
    
    int ConfigureBqMaximo()
    {
    	int result = 0;
    	unsigned char bqMaximoProtectionConfig[5];
    
    	result = I2CWriteBlockWithCRC(BQMAXIMO, PROTECT1, &(Registers.Protect1.Protect1Byte), 5);
    
    	result = I2CReadBlockWithCRC(BQMAXIMO, PROTECT1, bqMaximoProtectionConfig, 5);
    
    	if(bqMaximoProtectionConfig[0] != Registers.Protect1.Protect1Byte
    			|| bqMaximoProtectionConfig[1] != Registers.Protect2.Protect2Byte
    			|| bqMaximoProtectionConfig[2] != Registers.Protect3.Protect3Byte
    			|| bqMaximoProtectionConfig[3] != Registers.OVTrip
    			|| bqMaximoProtectionConfig[4] != Registers.UVTrip)
    	{
    		result = -1;
    	}
    
    	return result;
    }
    
    int InitialisebqMaximo()
    {
    	int result = 0;
    
    	Registers.Protect1.Protect1Bit.SCD_DELAY = SCDDelay;
    	Registers.Protect1.Protect1Bit.SCD_THRESH = SCDThresh;
    	Registers.Protect2.Protect2Bit.OCD_DELAY = OCDDelay;
    	Registers.Protect2.Protect2Bit.OCD_THRESH = OCDThresh;
    	Registers.Protect3.Protect3Bit.OV_DELAY = OVDelay;
    	Registers.Protect3.Protect3Bit.UV_DELAY = UVDelay;
    
    	result = GetADCGainOffset();
    
    	Gain = (365 + ((Registers.ADCGain1.ADCGain1Byte & 0x0C) << 1) + ((Registers.ADCGain2.ADCGain2Byte & 0xE0)>> 5)) / 1000.0;
    	iGain = 365 + ((Registers.ADCGain1.ADCGain1Byte & 0x0C) << 1) + ((Registers.ADCGain2.ADCGain2Byte & 0xE0)>> 5);
    
        Registers.OVTrip = (unsigned char)((((unsigned short)((OVPThreshold - Registers.ADCOffset)/Gain + 0.5) - OV_THRESH_BASE) >> 4) & 0xFF);
        Registers.UVTrip = (unsigned char)((((unsigned short)((UVPThreshold - Registers.ADCOffset)/Gain + 0.5) - UV_THRESH_BASE) >> 4) & 0xFF);
    
        result = ConfigureBqMaximo();
    
        return result;
    }
    
    int UpdateVoltageFromBqMaximo()
    {
    	int Result = 0, i = 0;
    	unsigned char *pRawADCData = NULL;
    	unsigned int iTemp = 0;
    	unsigned long lTemp = 0;
    
    	Result = I2CReadBlockWithCRC(BQMAXIMO, \
    			VC1_HI_BYTE, \
    			&(Registers.VCell1.VCell1Byte.VC1_HI), \
    			30);
    
    	pRawADCData = &Registers.VCell1.VCell1Byte.VC1_HI;
    	for (i = 0; i < 15; i++)
    	{
    		iTemp = (unsigned int)(*pRawADCData << 8) + *(pRawADCData + 1);
    		lTemp = ((unsigned long)iTemp * iGain)/1000;
    		lTemp += Registers.ADCOffset;
    		CellVoltage[i] = lTemp;
    		pRawADCData += 2;
    	}
    
    	return Result;
    }
    
    int main(void)
    {
    	int Result;
    
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
        DISABLE_INT;
    
        ClockInitialise();
    
        I2CInitialise();
    
        InitialisebqMaximo();
    
        while(1)
        {
        	Result = UpdateVoltageFromBqMaximo();
        }
    
    	return Result;
    }
    
    bqMaximo_Ctrl_G2553.h

    Now when reading from this following Function in a loop: 
    Result = UpdateVoltageFromBqMaximo();

    I get these Graphs and the last Byte of the Read is changing.
    I don't have a reference, like the correct Pattern of Pulse of the Read.  If I have, I could fix myself the Read and Write of Bytes Functions and make this Read correct.

    I don't know, what the Patterns of Pulses should be, please support me with this, I won't work by guessing!

  • Hi Kamel,

    Please give me some time to review what you have shared and capture some waveforms on my end.

    Best Regards,
    Alexis