cstm32cpu-registershaltexas-instruments

STM32 and BQ25713: it can not read / write to a register via I²C correctly


I am using the Texas Instruments BQ25713 charger. When we are programming BQ25713 via I²C, it cannot write/read a value to any register correctly.

E.g.; Not able to read ManufacturerID() 0x2E

Expected: 0x2E / 0x002E

Result: 0x2E41

I've also tried with DeviceID(), ChargeCurrent(), ChargeOption0(), MaxChargeVoltage(), and others, but I got wrong read and write again.

There is only one exception. That is CHRG_OK -> AC_STAT is working well. It can see input present / no present.

I2C_ADDRESS: 0xD6(6B). (I didn't find any problem about the I²C address)

From the datasheet;

*9.5 Programming The charger supports battery-charger commands that use either Write-Word or Read-Word protocols, as summarized in Section 9.5.1.

The I²C address is D6h. The ManufacturerID and DeviceID registers are assigned identify the charger device. The ManufacturerID register command always returns 40h.*

    #define BQ25713_REG_I2C_ADDRESS 0xD6 // I2C Address (R) Converted to 8 Bit from 6Bh
    #define BQ25713_REG_MANUFACTURER_ID 0x2E // MANUFACTURER ID (R) // I've also tried as 0x002E

    checkBitsAndControlLEDs(BQ25713_REG_MANUFACTURER_ID);

    uint16_t SetI2CData(uint16_t regAddress, uint16_t regValue) {
        HAL_StatusTypeDef status;
        uint8_t regValSet8[2];

        // Separation as LSB ve MSB
        regValSet8[0] = regValue & 0xFF;          // LSB
        regValSet8[1] = (regValue >> 8) & 0xFF;   // MSB

        // Is the device ready?
        status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            // Cihaz hazır değil, hata durumunu göster
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            HAL_Delay(300);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        }

        // Write LSB
        status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress, I2C_MEMADD_SIZE_16BIT, &regValSet8[0], 1, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            // Error LSB
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            HAL_Delay(300);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        }

        // Write MSB
        status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress + 1, I2C_MEMADD_SIZE_16BIT, &regValSet8[1], 1, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            // Error MSB
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            HAL_Delay(300);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        }

        return 0;
    }

    uint16_t ReadI2CData(uint16_t regAddress) {

        uint8_t readData[2];
        HAL_StatusTypeDef status;

        // Check device
        status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            // Error
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(300);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);

        }

        // Read data from Register
        status = HAL_I2C_Mem_Read(&hi2c1, BQ25713_REG_I2C_ADDRESS | 0x01, regAddress, I2C_MEMADD_SIZE_16BIT, readData, 2, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            // Error
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(10000);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_Delay(10000);
        }

        // Combine LSB and MSB
        uint16_t readI2CData = (readData[0] << 8) | readData[1];
        return readI2CData;
    }

// Check Bits via LED
void checkBitsAndControlLEDs(uint16_t check_register) {
    uint16_t regData = ReadI2CData(check_register);

    for (int i = 15; i >= 0; i--) {
        if ((regData >> i) & 1) {
            // If bit is 1, light on LED 2 (GREEN)
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            HAL_Delay(2500);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        } else {
            // If bit is 0, light on LED 1 (RED)
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(2500);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
        }
        HAL_Delay(1000);  // 1 second delay
    }
}

MCU: STM32F030
IDE: STM32CubeIDE (HAL, INIT, and I²C functions has been imported)

There isn't any error or warning when make debug and run process.


Solution

  • The BQ25713 datasheet shows the Reg Addr used in the I²C communication is 8-bits. E.g., see Figure 9-11. Multi Read.

    The code uses I2C_MEMADD_SIZE_16BIT in the calls to HAL_I2C_Mem_Write and HAL_I2C_Mem_Read. I.e., the code attempts to send a 16-bit register address to the BQ25713 rather than a 8-bit register address.

    Also, the datasheet shows the BQ25713 registers are 8-bits, yet the SetI2CData and ReadI2CData functions use uint16_t rather than uint8_t as the the data type for the registers.

    While the datasheet does show Multi Write and Multi Read I²C operations, which work on multiple 8-bit registers with consecutive register addresses, it might be clearer if the code was changed to write/read 8-bit registers.

    At a minimum, I suggest changing the code to use I2C_MEMADD_SIZE_8BIT instead of I2C_MEMADD_SIZE_16BIT.

    In summary, the code in the question seems to treat the BQ25713 registers as having 16-bit addresses and 16-bits of data, whereas the datasheet shows 8-bit register addresses with 8-bits of data.