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?

This discussion is locked. Please start a new topic to ask your question.
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