2019-05-12 10:58 AM
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?
2019-05-12 11:41 AM
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)
2019-05-12 05:01 PM
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