cancel
Showing results for 
Search instead for 
Did you mean: 

I2C read/write proper way, to many options

Marius CO
Associate III

HAL_I2C_Mem_Read(I2C_HandleTypeDef, Address, REGUSTER, rsz, buff, bsz, tout);

If the device address is 0x77,

what is th proper way. I can find non consistent answers, though i cannot read. I get HAL_EROR

is it:

Anyway each option returns non consistent data... WHich way is the right way.

HAL_I2C_Mem_Read(I2C_HandleTypeDef, Address|1...

HAL_I2C_Mem_Read(I2C_HandleTypeDef, Address<<1,...

HAL_I2C_Mem_Read(I2C_HandleTypeDef, Address,...

HAL_I2C_Mem_Write(I2C_HandleTypeDef, Address

HAL_I2C_Mem_Write(I2C_HandleTypeDef, Address|1

HAL_I2C_Mem_Write(I2C_HandleTypeDef, Address<<1

2 REPLIES 2

The "right way", in this context, is to have the 7-bit address left justified in the 8-bit byte, so it looks like the timing diagram in the I2C parts data sheet. The STM32 adds the low order bit for read/write.

The I2C part will only ACK if it sees it's address on the bus. So if the device isn't on the bus, or the address is wrong, you can see it's not there.

There is a lot of inconsistency in how different vendor's APIs work, some expect a 7-bit right justified address be passed in. It's generally advisable to chase down the call tree in the source and double check, review the diagrams in the data sheet, a validate with a scope. If one doesn't have confidence in the SW or HW, you can also bit bang the SDA/SCL explicitly and build your own analyzer. If you can't get the part to ACK in those conditions, you need to start suspecting the part.

Remember drive OC, and have pull-ups, 4K7 being reasonable.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Marius CO
Associate III

Thank you.

That worked. Here are my r/w functions for reference:

typedef union I2cReg
{
	uint8_t		u8;
	uint16_t	u16;
	uint32_t	u32;
	uint8_t     b[4];
}I2cReg;
 
static I2cReg _i2c_read(int i2cnum, uint16_t address, uint16_t reg, uint16_t size)
{
	I2C_HandleTypeDef* ph = i2cnum==2 ? &hi2c2 : &hi2c3;
	HAL_StatusTypeDef sd;
	I2cReg ival;
 
	ival.u32 = 0x00;
	/// did not worked well sd=HAL_I2C_Mem_Read(ph, (address<<1), reg, size, ival.b, size, 8000);
	sd = HAL_I2C_Master_Transmit(ph, address<<1, &reg, 1, 2000);	/* select register to read form */
	if(sd==HAL_OK)
		sd = HAL_I2C_Master_Receive(ph, address<<1, ival.b, size, 4000);
	if(sd!=HAL_OK)	
		while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);
	return ival;
}
 
static bool _i2c_write(int i2cnum, uint16_t address, uint16_t reg, union I2cReg* val, uint16_t size)
{
	I2C_HandleTypeDef* ph = i2cnum==2 ? &hi2c2 : &hi2c3;
	HAL_StatusTypeDef sd;
 
	sd = HAL_I2C_Mem_Write(ph, ((address<<1)), reg, size==1?I2C_MEMADD_SIZE_8BIT:I2C_MEMADD_SIZE_16BIT, val->b, size, 1000);
	if(sd != HAL_OK)
	while (HAL_I2C_GetState(ph) != HAL_I2C_STATE_READY);
}