Read data from 16bit register TWI on NRF52833.

Hi All, 

         I am trying to communicate with IC MAX17201 using I2C interface. I am able to detect the IC and communicate with it. 

When I read 8bit registers from the IC I don't have any issue. But when I am trying to read 16bit register from the IC, I am getting errors.The existing code from NRF SDK includes data to read and write 8 bit registers.

I have modified the code a bit in order to read 2bytes from register. I am not able to read 16bit registers. I tried to read NPACKCFG_REG but not able to read it properly. As well as while compiling I am getting warnings like this:-unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '437' to '181' [-

#define NPACKCFG_REG     0x1B5

#define MAX17201_ADDRESS_LEN  1         
#define MAX17201_ADDR     (0xD8>>1)  
#define MAX17201_WHO_AM_I     0x6BU     

bool i2c_register_write_max17211(uint16_t register_address, uint16_t value)
{

      ret_code_t err_code;
      uint8_t tx_data[4];

      tx_data[0] = ( (register_address >> 8)& 0xFF );
      tx_data[1] = register_address & 0xFF;
      tx_data[2] = ((value>>8)& 0xff);
      tx_data[3] = value & 0xFF;

      m_xfer_done = false;
    
      err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, tx_data, sizeof(tx_data), false);
  //Wait until the transmission of the data is finished
    while (m_xfer_done == false)
    {
      }

   // if there is no error then return true else return false
    if (NRF_SUCCESS != err_code)
    {
        NRF_LOG_INFO("FAILED");
        return false;
    }

    NRF_LOG_INFO("SUCCESS");

    return true;	

}

bool i2c_register_read_max17211(uint8_t register_address, uint8_t destination[2], uint8_t number_of_bytes)
{
    ret_code_t err_code;
    //uint8_t rx_buffer[2];

    //Set the flag to false to show the receiving is not yet completed
    m_xfer_done = false;
    
    // Send the Register address where we want to write the data
    err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, &register_address, 1, true);
	  
    //Wait for the transmission to get completed
    while (m_xfer_done == false){}
    //vTaskDelay(1000);

    // If transmission was not successful, exit the function with false as return value
    if (NRF_SUCCESS != err_code)
    {
        return false;
    }

    //set the flag again so that we can read data from the MPU6050's internal register
    m_xfer_done = false;
	  
    // Receive the data from the MPU6050
    //err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, destination, number_of_bytes);
    err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, &destination[0], sizeof(destination));
		
    //wait until the transmission is completed
    while (m_xfer_done == false){}
    //vTaskDelay(1000);


    // if data was successfully read, return true else return false
    if (NRF_SUCCESS != err_code)
    {
        return false;
    }
    
    //NRF_LOG_INFO("DATA IS %x",destination);
    return true;

}

Please help me on how to read multiple bytes from 16bit registers and how to write data into 16 bit registers.

  • Hi,

    Your code looks correct to me, given that the MAX17201 expects the 16-bit register address in this format. What is the problem when reading/writing this register? "not able to read it properly" does not provide much information about what goes wrong.

    Have you checked the TWI lines with a logic analyzer, to see if the expected register address is output, and it the sensor outputs any of the expected data?

    The warning is expected when assigning the value of a 16-bit variable into 8-bit variable without a cast. As long as this is the expected behavior, you can ignore the warning and/or cast the 16-bit variable to uint8_t when assigning.

    Best regards,
    Jørgen

  • yes we checked the lines, there was problem with the slave ID. Now I am able to communicate properly. The code which I shared above for reading register is for reading 8 bit register. How can I modify it to read 16bit registers??

    existing code is as follows:-

    bool i2c_register_read_max17211(uint8_t register_address, uint8_t destination[2], uint8_t number_of_bytes)
    {
        ret_code_t err_code;
        //uint8_t rx_buffer[2];
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, &register_address, 1, true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        //err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, destination, number_of_bytes);
        err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, &destination[0], sizeof(destination));
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
    
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    
    }

  • It should be very similar to your write function. Something like this will probably work (not tested):

    bool i2c_register_read_max17211(uint16_t register_address, uint16_t *value)
    {
        ret_code_t err_code;
        uint8_t tx_buffer[2];
    	uint8_t rx_buffer[2];
    	
    	tx_buffer[0] = ( (register_address >> 8) & 0xFF);
        tx_buffer[1] = register_address & 0xFF;
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, tx_buffer, sizeof(tx_buffer), true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        //err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, destination, number_of_bytes);
        err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, rx_buffer, sizeof(rx_buffer));
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
    
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    	*value = (rx_buffer[0] << 8);
        *value |= rx_buffer[1];
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    
    }

  • Hi, 

    Thank you so much. I am able to read 16bit registers now.Reading works properly now. But I am not able to write 16 bit registers. I tried to write a 16 bit register and then read its value. It shows me different value. which means the value was not written properly into the register. 

    Is anything wrong in the write code below?

    I am trying to write register  0x1B3 with value  0x348.

    After writing this value when I read the register again, I am getting value as 0x300. What might be the issue? 

    bool i2c_register_write_max17211(uint16_t register_address, uint16_t value)
    {
    
          ret_code_t err_code;
          uint8_t tx_data[4];
    
          tx_data[0] = ( (register_address >> 8)& 0xFF );
          tx_data[1] = register_address & 0xFF;
          tx_data[2] = ((value>>8)& 0xff);
          tx_data[3] = value & 0xFF;
    
          m_xfer_done = false;
        
          err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, tx_data, sizeof(tx_data), false);
      //Wait until the transmission of the data is finished
        while (m_xfer_done == false)
        {
          }
    
       // if there is no error then return true else return false
        if (NRF_SUCCESS != err_code)
        {
            NRF_LOG_INFO("FAILED");
            return false;
        }
    
        NRF_LOG_INFO("SUCCESS");
    
        return true;	
    
    }
    

  • Have you looked at the TWI lines with the logic analyzer, to see if 0x300 or 0x348 is output when writing the value, and what is returned by the slave when reading? The code looks correct to me.

Related