cancel
Showing results for 
Search instead for 
Did you mean: 

Generate i2c stop for a single byte read

EP.2
Associate III

I need to send a single address byte with write bit and read bit.

For the write, I'm using 

HAL_I2C_Master_Transmit_IT(&hi2c4, I2C_ADDRESS, (uint8_t*)i2c_buff, 0)

It works perfect, it sends a start, single address with write bit cleared, slave device ACK's and stop works fine.

I need the exact same thing, but with the read bit set.

I tried:

HAL_I2C_Master_Receive_IT(&hi2c4, I2C_ADDRESS, (uint8_t*)i2c_buff, 0)

It just sends the start, address, read bit set, slave device ACK's ok, but then MCU doesn't do the stop bit, gets stuck infinitely waiting. I've tried using the LL drivers too, and also played around with disabling AUTOEND and using SOFTEND to try to manually generate start, send addr and then stop, no go, just waits for the I2C_ISR_STOPF flag to be set, which never happens. On the scope, SCL goes high, but SDA stays low.

Any ideas? Using STM32U535, I2C4

6 REPLIES 6
Saket_Om
ST Employee

Hello @EP.2 

If you want to check your slave device it is better to use the API HAL_I2C_IsDeviceReady().

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
EP.2
Associate III

I don't have it connected at the moment to try again, but I think I've tried that, I think it works but it has the Read/Write bit as Write. I need the same thing but with the R/W bit set to Read.

It's not to check the slave device, the slave device uses the R/W bit to trigger two different measurements. So measurement A starts if R/W bit is R, measurement B starts if R/W bit is W. I can trigger measurement B fine, but I need to trigger measurement A, which can only be done with a stop bit after the R bit, but looks like i2c peripheral can't do it?

 

bmckenney
Associate III

What slave device are you talking to?

--------------

A zero-length transaction is called a "Quick Command" (SMBus term). It is suitable for slave devices that recognize Only Quick commands. [I'm told those exist, but I haven't seen one.]

As you've observed, a Tx (Master-transmitter) Quick Command works fine.

An Rx (Master-receiver) Quick Command is an I2C-level problem with a slave that is capable of (any) non-Quick commands. After the master sends the SLA byte, it hands over (at the Ack cycle) control of SDA to the slave, which retains control until the End (Ack cycle) of the first data byte it sends. But for a Quick command, the master won't provide any clocks to clock out that first data byte, so the protocol is stuck -- the slave can't send its byte, and the master can't issue a Stop since the slave owns SDA. [Strictly speaking, this is only a problem if the high-order bit of that first data byte is 0.]

That's why I2C scanners always use Tx Quick Commands.

[Edit: In case it needs to be said: The slave has no way of telling whether a command is Quick or not.]

bmckenney
Associate III

I missed one of the clues: If SDA is low, that suggests (a) the slave is not Quick-only so (b) it has a byte to send you.

So just read the byte (NBYTES=1,AUTOEND=1) and throw it away. Your master-side will NACK the byte, the slave will release the bus (SDA) and then the master can issue a Stop.

EP.2
Associate III

Thanks for the reply. Good pickup, I think SDA is low, because obviously it does have more bytes to send if it was a real read. But according to the datasheet I can't read a byte because it starts reading the data register instead of starting a measurement. How ***.

It's a ZSC31014.

bmckenney
Associate III

Data sheet (R1.65) Section 3.2.1 mentions that 'The I2C™ Read_MR function can also be accomplished using the I2C™ Read_DF2 or Read_DF3 command and ignoring the “stale” data that will be returned'. This is roughly what I was suggesting. Based on Figure 3.1 this would look like Read_DF/wait(per Tables 3.4/.5)/Read_DF.

The thing to note about Figure 3.6 is that in I2C terms the Read_DFn requests are all really the same request -- the only difference is when the master chooses to terminate the transaction (by NACK/Stop). You could choose to terminate the transaction after 1 (data) byte, even though that isn't in the Figure.

The master-receiver NACK is what causes the slave to release SDA. Read_MR is mostly the same request, but it lacks a mechanism for the master to issue a NACK, so it can't issue a Stop.

This (maybe) could work if Status bit 15 were always =1, but Table 2.9 doesn't guarantee this.

And if you operate in Update mode, this is all moot.