Skip to main content
John E KVAM
ST Employee
July 18, 2022
Question

I2C multi-byte read and write functions with i2C byte limit.

  • July 18, 2022
  • 1 reply
  • 3963 views

How can one adapt the WrMulti() and RdMulti() I2C functions for MCUs that have an I2C length limit? 

This is an oft-asked question.

This topic has been closed for replies.

1 reply

John E KVAM
ST Employee
July 18, 2022

The ST code was written based on an STM32, which has no I2C limit on the length. But other MCUs do have a limit.

Use the following code in your platform.c. All it really does is break the long I/O operations into several 'CHUNK_SIZE' operations.

The only trick is that one has to keep track of the addresses.

This code uses a 1K chunk size, but that was arbitrary.

#define VL53L5_COMMS_CHUNK_SIZE (1 * 1024)
 
uint8_t WrMulti(
 VL53L5CX_Platform *p_platform,
 uint16_t RegisterAdress,
 uint8_t *pdata,
 uint32_t size)
{
#if 0
 uint8_t status = HAL_I2C_Mem_Write(&hi2c1, p_platform->address, RegisterAdress,
 I2C_MEMADD_SIZE_16BIT, pdata, size, 65535);
#else
 
 int32_t status = 0;
 uint32_t position = 0;
 uint32_t data_size = 0;
 uint16_t i = 0;
 uint8_t data_write[VL53L5_COMMS_CHUNK_SIZE+2];
 
 for (position = 0; position < size; position += VL53L5_COMMS_CHUNK_SIZE)
 {
 if (size > VL53L5_COMMS_CHUNK_SIZE)
 {
 if ((position + VL53L5_COMMS_CHUNK_SIZE) > size)
 {
 data_size = size - position;
 }
 else
 {
 data_size = VL53L5_COMMS_CHUNK_SIZE;
 }
 }
 else
 {
 data_size = size;
 }
 
 
 /*
 * STM32 HAL API expects I2C bytes in this format:
 * First Register(EwokMZ registers are 16 bit addresses)
 * Then, I2C bytes
 */
 data_write[0] = (RegisterAdress+position) >> 8;
 data_write[1] = (RegisterAdress+position) & 0xFF;
 for (i=0; i<data_size; i++)
 {
 data_write[i+2] = pdata[position + i];
 }
 
 //STM32 I2C api
 status = HAL_I2C_Master_Transmit(&hi2c1,
 p_platform->address,
 data_write,
 data_size + 2,
 100*data_size);
 
 if (status != HAL_OK) {
 //printf("HAL_I2C_Master_Transmit error = %ld\n", status);
 return status;
 }
 }
#endif
 return status;
}
 
uint8_t RdMulti(
 VL53L5CX_Platform *p_platform,
 uint16_t RegisterAdress,
 uint8_t *pdata,
 uint32_t size)
{
 
#if 0
 uint8_t status;
 uint8_t data_write[2];
 data_write[0] = (RegisterAdress>>8) & 0xFF;
 data_write[1] = RegisterAdress & 0xFF;
 status = HAL_I2C_Master_Transmit(&hi2c1, p_platform->address, data_write, 2, 100);
 status += HAL_I2C_Master_Receive(&hi2c1, p_platform->address, pdata, size, 100);
 
 return status;
#else
 
 int32_t status = 0;
 uint32_t position = 0;
 uint32_t data_size = 0;
 uint8_t data_write[2];
 
 for (position = 0; position < size; position += VL53L5_COMMS_CHUNK_SIZE)
 {
 if (size > VL53L5_COMMS_CHUNK_SIZE)
 {
 if ((position + VL53L5_COMMS_CHUNK_SIZE) > size)
 {
 data_size = size - position;
 }
 else
 {
 data_size = VL53L5_COMMS_CHUNK_SIZE;
 }
 }
 else
 {
 data_size = size;
 }
 
 /*
 * STM32 HAL API expects I2C bytes in this format:
 * First Register(EwokMZ registers are 16 bit addresses)
 */
 data_write[0] = (RegisterAdress + position)>>8;
 data_write[1] = (RegisterAdress + position) & 0xFF;
 //Write the register to read from
 status = HAL_I2C_Master_Transmit(&hi2c1, p_platform->address, data_write, 2, 100);
 if (status != HAL_OK)
 {
 //printf("HAL_I2C_Master_Transmit error = %ld\n", status);
 return status;
 }
 //Read the register data
 status = HAL_I2C_Master_Receive(&hi2c1, p_platform->address, pdata + position, data_size, 100);
 if (status != HAL_OK)
 {
 //printf("HAL_I2C_Master_Transmit error = %ld\n", status);
 return status;
 }
 }
 return status;
#endif
}

If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.
Tesla DeLorean
Guru
July 18, 2022

Some of the Arduino drivers (AVR?) have a 32-byte limit, but I think that's a buffering one, and I think you can keep flushing that by sending a block without a STOP bit, and then continuing.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..