cancel
Showing results for 
Search instead for 
Did you mean: 

How do I determine the memory address size parameter for HAL_I2C_Mem_Write/Read?

LocknutBushing
Associate

Hi, I am trying to establish I2C communication between my STM32 Nucleo 411RE and this EM7180 sensor fusion coprocessor using the HAL_I2C_Mem_Write()/Read() functions. However, I'm having trouble with the MemAddSize parameter.

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef * hi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size,uint32_t Timeout )

I don't know how to figure out the size of each internal memory address in the EM7180. I wasn't able to find any information in the datasheet, and the Arduino code as well as other libraries I've found use I2C functions that doesn't require this parameter.

So far, I have assumed all of the MemAddress values to be "1". But in the Arduino example code, as many as 16 bytes are read from a single register in some cases. So this is probably wrong. My code is not working.

Would anyone be able to point me in the right direction?

2 REPLIES 2
S.Ma
Principal

Hmm, I rewrote the function my way for more generic implementation.

Here, DevAddress is the slave I2C address

Consider the multibyte transfer is spil in 2:

0 to 2 bytes which is MemAddress (like accessing an I2C EEPROM memory, the MemAddress is the subaddress location within the EEPROM

0 to 64k bytes which is a byte block defined by pData and Size.

I guess for the read function the address is still a write, then restart as read to read the data block.

If your device like VL53L1X does not have specific sub address, then you use MemAddressSize = 0;

In practice, all I2C device comply with a unique function (works 4 me): (here implemented as bitbang as 500kHz is easy to do)

typedef struct {
  
  IO_Pin_t* SDA; // we need the pointer to the pin
  IO_Pin_t* SCL; // we need the pointer to the pin
 
  uint32_t WaitParam;
  
} I2C_MasterIO_t;
 
typedef struct {
 
  I2C_MasterIO_t* M;
  
  uint8_t SlaveAdr;
 
  uint8_t SubAdrByteCount;  // can be 0..4 bytes
  uint8_t SubAdrBytes[4]; // first byte is slave address, if any
  
  uint8_t *pWriteByte;
  uint16_t WriteByteCount; // 0 if no data bytes to write
  
  uint8_t *pReadByte;
  uint16_t ReadByteCount; // 0 if no data bytes to read
 
  uint8_t SlaveAdrWriteNack /*: 1*/;
  uint8_t SlaveAdrReadNack /*: 1*/;
  
  uint8_t WasDetected; // status for sweep and hot plug detection
  uint8_t IsDetected; // status for sweep and hot plug detection
  
} I2C_SlaveDevice_t;
 
 
uint32_t I2C_MasterIO_AccessDevice(I2C_SlaveDevice_t* pD); // I2C_SlaveDevice_t // I2C Generic transaction Write+Read cycle

With this function, you get the smallest granularity shall you put multiple threads on top of this (like a FIFO of slave device transactions)

Pavel A.
Evangelist III

The MemAddSize parameter is the number of bytes in MemAddress: 1 or 2.

If MemAddSize ==1 the function writes the low byte of MemAddress after the i2c device address. If MemAddSize ==2, it writes two bytes of MemAddress .

This and how many data bytes can be moved at once, should be in the documentation on the device. To address 64K space, it probably has 2-byte address.

If you cannot find the documentation, please try harder.

-- pa