This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

I2C Compatability with SMBus protocol

Hi 

Good day!

We are working on the BQ24715 Digital Charge controller IC and it has got an SMBus communication port and tried to set up communication using the nRF52832 controller TWI protocol.

Problem: SMBus on BQ24XX is not responding with the TWI module on nRF52 DK (nrf52832).  I tried the TWI sensor example from the SDK. 

Question:  TWI protocol will this work with SMBus protocol on nrf52832? If yes, which example I should try out from the SDK?

IMO, it should at least work for the write transactions for 100kHz clock frequency using TWI protocol. But it did not work. 

The bq24715 uses the SMBus Read-Word and Write-Word protocols (Figure 7) to communicate with the smart battery. The bq24715 performs only as an SMBus slave device with address 0b00010010 (0x12H) and does not initiate communication on the bus.

For reference: http://www.ti.com/lit/ds/slusbd1b/slusbd1b.pdf


I would appreciate any help in this regard.

  • Hi,

    I have no experience with BQ24, but I don't remember any issues with I2C bus on TI power management chips.. An address 0x12 seems to include flag bit, so the right address to load into ADDRESS register will be 0x09 (maybe I'm wrong). A bus trace with logic analyzer (or at least ocsilloscope screenshot) would help much.

  • Hi Dmitry,

    Yes, I tried 0x09 into the address register with no response. I tried to debug the same with TWI sensor example. It never hits the twi_hanlder and it just gets stuck @ while (m_xfer_done == false), because it never reaches the twi_handler where this flag is updated. 

    We don't have a digital scope yet to analyze the SMBus signals.

  • Update: We had the SDA and SCL shorted to ground. Now it is working TWI and SMBus. 

    But there is a strange phenomenon when I tried to print out the read data on the terminal, I get all zero. But if I add nrf_delay_ms(1), then I am getting the right values printed. 

    Please share insights if someone worked on this kind of issue.

  • If you could post the code you use for printing the data, we may be able to help you figure out what is happening.

  • Sure,

    #include <stdio.h>
    #include "boards.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "slb_bq24715.h"
    
    /* TWI instance ID. */
    #define TWI_BQ24X_LM75BDP_ID     0
    #define TWI_TSM12_CAP_ID         1
    
    /* Common addresses definition for BQ24715 smart charger IC. */
    #define BQ24715_ADDR        (0x12U >>1) 
    
    
    uint8_t addr_array[7] = {0x12, 0x14, 0x15, 0x3F, 0x3E, 0xFE, 0xFF};
    #define CHARGE_OPTIONS       0x12U
    #define CHARGER_CURRENT      0x14U
    #define CHARGER_VOLTAGE      0x15U
    #define INPUT_CURRENT        0x3FU
    #define MINSYS_VOLTAGE       0x3EU
    #define CHARGE_OPTION        0x12U
    
    char addr_desr[][20] = {"CHARGE OPTIONS", "CHARGE CURRENT", "CHARGE VOLTAGE", "INPUT CURRENT", "MINSYS VOLTAGE", "DEVICE ID", "MANUFACTURER ID"};
    
    /**Read only device and manufacturer ID.**/
    #define BQ24_DEVICE_ID            0xFF  
    #define BQ24_MANUFACTURER_ID      0xFE
    
    /**16 bit's register data LSB and MSB parts.**/
    #define CHARGE_OPTIONS_DATA_LSB  0x54
    #define CHARGE_OPTIONS_DATA_MSB  0x66
    
    #define CHARGE_VOL_DATA_LSB 0x20
    #define CHARGE_VOL_DATA_MSB 0x22
    
    #define SYS_VOL_DATA_LSB 0x00
    #define SYS_VOL_DATA_MSB 0x20
    
    #define INPUT_CUR_DATA_LSB 0xC0
    #define INPUT_CUR_DATA_MSB 0x1F
    
    #define CHARGE_CUR_DATA_LSB 0x00
    #define CHARGE_CUR_DATA_MSB 0x01
    
    /* Indicates if operation on TWI has ended. */
    static volatile bool m_xfer_done = false;
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_BQ24X_LM75BDP_ID);
    
    /* Buffer for samples read from temperature sensor. */
    static uint8_t m_sample[2];
    
    /* Buffer for data to read from the BQ24715 sensor. */
    static uint16_t m_bq24715_dat;
    
    /**
     * @brief Function for setting active mode on MMA7660 accelerometer.
     */
    void BQ24715_set_mode(void)
    {
        ret_code_t err_code;
        /**Writing to BQ24715 Charge options register first @ 0x12H.**/
        /**Followed with 0x15H, 0x3EH, 0x3FH, 0x14H.**/
        
        uint8_t reg[3] = {CHARGE_OPTIONS, CHARGE_OPTIONS_DATA_LSB, CHARGE_OPTIONS_DATA_MSB };
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg, sizeof(reg), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
        //nrf_delay_ms(30);
    
        /* Writing to pointer byte. */
        uint8_t reg_1[3] ={CHARGER_VOLTAGE, CHARGE_VOL_DATA_LSB, CHARGE_VOL_DATA_MSB };
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg_1, sizeof(reg_1), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
         //nrf_delay_ms(30);
        
        uint8_t reg_2[3] ={MINSYS_VOLTAGE, SYS_VOL_DATA_LSB, SYS_VOL_DATA_MSB};
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg_2, sizeof(reg_2), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
         //nrf_delay_ms(30);
    
        uint8_t reg_3[3] ={INPUT_CURRENT, INPUT_CUR_DATA_LSB, INPUT_CUR_DATA_MSB};
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg_3, sizeof(reg_3), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
         //nrf_delay_ms(30);
    
        uint8_t reg_4[3] ={CHARGER_CURRENT, CHARGE_CUR_DATA_LSB, CHARGE_CUR_DATA_MSB};
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg_4, sizeof(reg_4), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
    }
    
    void BQ24_CHARG_VOLT(){
    
        ret_code_t err_code;
        uint8_t reg_1[3] ={CHARGER_VOLTAGE, CHARGE_VOL_DATA_LSB, CHARGE_VOL_DATA_MSB };
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg_1, sizeof(reg_1), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    }
    
    
    
    /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    __STATIC_INLINE void data_handler(uint8_t data)
    {
       printf("BQ24715 Device data \n", data);
    }
    
    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                    //data_handler(m_sample);
                }
                m_xfer_done = true;
                break;
            default:
                 break;
        }
    }
    
    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_lm75b_config = {
           .scl                = 31,
           .sda                = 30,
           .frequency          = NRF_DRV_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_twi_enable(&m_twi);
    }
    
    void read_BQ24715_mode(uint8_t data)
    {
        ret_code_t err_code;
        /**Writing to BQ24715 Charge options register first @ 0x12H.**/
        /**Followed with 0x15H, 0x3EH, 0x3FH, 0x14H.**/
        m_xfer_done = false;
        uint8_t reg[1] = {data};
        err_code = nrf_drv_twi_tx(&m_twi, BQ24715_ADDR, reg, sizeof(reg), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
        m_xfer_done = false;
        /* Read consecutive two bytes of data */
        err_code = nrf_drv_twi_rx(&m_twi, BQ24715_ADDR, m_sample, sizeof(m_sample));
        APP_ERROR_CHECK(err_code);
        }
    
    
    /**
     * @brief Function for reading data from temperature sensor.
     */
    static void read_BQ24715_data()
    {
        m_xfer_done = false;
    
        /* Read consecutive two bytes of data */
        ret_code_t err_code = nrf_drv_twi_rx(&m_twi, BQ24715_ADDR, m_sample, sizeof(m_sample));
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint8_t i;
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
        NRF_LOG_FLUSH();
        twi_init();
    //    read_BQ24715_mode();
    //    read_BQ24715_data();
        BQ24715_set_mode();
        //BQ24_CHARG_VOLT();
        for(i =0; i<sizeof(addr_array); i++){
            read_BQ24715_mode(addr_array[i]);
            nrf_delay_ms(1);
            uint16_t data = (m_sample[1]<<8)|(m_sample[0]);
            printf("BQ24715 Reg %s and Data: %X\n", addr_desr[i], data);
        
        }
        //nrf_delay_ms(1);
        //uint16_t data = (m_sample[1]<<8)|(m_sample[0]);
        //printf("BQ24715 Device ID: %X \n", data);
        //NRF_LOG_INFO("BQ24715 Device ID: %X \n", data);
    
    }

Related