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.

Parents Reply Children
  • 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);
    
    }

  • You do not wait for the TWI RX operation to finish before you print the data, meaning you will print the empty buffer before it is filled. You need to add a wait-condition at the end of read_BQ24715_mode(), after the call to nrf_drv_twi_tx():

    while (m_xfer_done == false);
    m_xfer_done = false;

Related