cancel
Showing results for 
Search instead for 
Did you mean: 

How is receiving of a i2c byte initiated?

enrico239955_st
Associate II
Posted on June 27, 2014 at 04:05

Hi, I would like te receive 3 Bytes. Therefore I am sending a start, the I2C address of the slave, the register address, a repeated start, the slaveaddress again, then I receive the 3 bytes and finish wish a stop. So far so good.

I can see code which is initiating the start condition (I2Cx->CR1 |= I2C_CR1_START;)

I can see code which sends bytes (I2Cx->DR = Address;)

In the manual I can see, that writing is automatically started when writing to the dr register.

but: how is receiving initiated? In which register do I have to write to in order to start the receiving of a byte?
8 REPLIES 8
stm322399
Senior
Posted on June 27, 2014 at 09:27

Reception automatically starts as soon as you read SR2 with MSL flag set.

The reception is controlled with ACK and POS bits of CR1. The RM states what's you have to do when you want to receive one or two bytes. For receiving more bytes (eg. 3) let ACK set and POS unset, receive incoming bytes, and when you are ready to receive the last two bytes, follow the RM recipe.

enrico239955_st
Associate II
Posted on June 27, 2014 at 14:29

Hm, ok, thats not very nice. In the event EV6 (I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) are read both registers SR1 and SR2 after sending the device read address. So the first byte is read immidiatly while checking EV6! Thats not good, because I want to control when the reading starts!

What I want is:

sending the device read address, checking for EV6, wait.

After a time x I want to start the reading of the first byte.

Is that possible?

enrico239955_st
Associate II
Posted on June 27, 2014 at 15:18

Next problem:

I am doing this now: sending the read device address, then executing the following code (stepping line after line)

while(((I2Cx->SR1)&0x0002) != 0x0002){
if (ErrorCount++ > 500) return 1;
}
// read sr2 for clearing addrflag
I2Cx->SR2;

but with the reading of SR2 the controller is sendig two! bytes (I saw it on the oscilloscope). Thats not good.
stm322399
Senior
Posted on June 27, 2014 at 15:39

The behaviour of the controller is perfectly clear (at least to me).

Do you want to delay data reception ? Then read SR2 only when you are ready to receive bytes.

As soon as you can observe MSL from SR2 read, the controller starts to clock bytes in. When the first byte is done, it is transferred to RX data register for the purpose of being read by you. The second byte is immediately clocked in to avoid leaving the bus idle.

If you collect received bytes regularly (soft or DMA) the scheme continues until you clear ACK. That's why clearing ACK must be done at the moment, you are waiting the last two bytes.

At the moment you clear ACK, the controller can nack the byte currently clocked in (case with POS=1) or the subsequent byte to be clocked in (case with POS=0).

In other words, you can control the data flow with ACK, POS, and SR2 reading as well.

enrico239955_st
Associate II
Posted on June 27, 2014 at 15:56

Thank you for your help. Now the behavior is a bit clearer to me, but where did you get those infos:

1. The second byte is immediately clocked in to avoid leaving the bus idle.

2. The byte is read immidiatly after reading SR2

?

You said for controlling the dataflow I have to use the nack flag. But if I reset the nack-flag, no Ack is sent by the master after reading a byte (and more bytes are following), which is not correct.

In other words, there is no possibility to receive one byte at a time even if I have to receive more than one byte?

stm322399
Senior
Posted on June 27, 2014 at 16:10

All I explained is based on my observation and my understanding of the documentation and digital design in general, and I might be wrong.

On the other side, I must admit that there is no simple way to receive bytes one by one. IMHO it is possible for any bytes except the first two bytes. I will bet that when you do not read from rx data register, the controller is stalled with the first byte in RX data register and the second one in the RX shift register. Once you read the first, the second is transferred into data register, and a third one start to be clocked into the shift register.

I wonder how comes you need to control the data flow by the master side. Normally I2C protocol is designed to allow the slave (data producer) to control data flow by keeping SCL line low when it is busy. A devilish trick can be to use a companion GPIO (open drain!) to maintain SCL low when it matters for your communication. For sure it is not a recommended design !

enrico239955_st
Associate II
Posted on June 27, 2014 at 16:48

My reason is the following: I2C is very slow, so I do not want to wait for the completion of the receiving. I am writing on a RTOS and my idea was to initiate the receiving of one byte, leave the task and do other things and after the receiving of the byte I can initiate the second byte for reading, leave the task and so on. Thats the reason why I have to control one byte after another.

But my datastrem is not that long (sometimes 3, sometimes 7 bytes) so I dont want to use the dma. maybe it costs me more time to initialize and handle the dma than receiving the bytes one by one.

So I decided to change the sensor from I2C to SPI. The SPI interface is faster, so I can read several bytes without the need to interrupt the task.

stm322399
Senior
Posted on June 27, 2014 at 17:09

OK. So where is the problem ? After reading SR2, the I2C controller is autonomous for receiving two bytes, let it do it's job and come back later. Coming later, you collect received bytes, which automatically releases the controller for subsequent byte reception. Return to your thread, and so on. All of this is based on my assumption that the I2C controller stalls when RX data register and shift register are full, that it does not overrun, this is how I understand this sentence of the reference manual of F4:

''If the RxNE bit is set and the data in the DR register is not read before the end of the last

data reception, the BTF bit is set by hardware and the interface waits until BTF is cleared by

a read in the DR register, stretching SCL low.''

By the way, the handling of I2C you described is not exactly the behavior I would expect from an RTOS. IMHO, it is better to use interrupts, at each interrupt you receive and store one byte,and decide if you want to continue or stop (setting ACK/POS). I think it is the best way to handle 'slow' devices.