cancel
Showing results for 
Search instead for 
Did you mean: 

I2C passiv Mode possible?

Moritz1
Associate III

Hi,

I try to sniff a I2C communication between multiple devices with my STM32G473.

The controller should only listen passiv. Is this possible?

For sure, I can always set the NACK-Bit to prevent sending an ACK and disable the Clock-stretching.

And I can use the Adress-Masking feature to listen on all Addresses.

But if I understand correctly, the Controller will always send automatically an ACK if the Address matchs? Is this correct? I can not disable this.

So this ACK after Address match is the only point that prevents me from doing what I want to do.

Is there any possibility to listen 100% passively with the I2C periphery?

I tryed another way before: Generating interrupts on clock edges and reading the level of Data Line, and than getting the data Bit by Bit. This works fine for 250kHz, but unfortunately the Interrupt is too slow to sample an 1MHz I2C signal (Interrupt needs 440ns to be called and one clock pulse is just 500ns long, so I miss the databit). So I was thinking if it is mayby possible to use the I2C peripheral.

10 REPLIES 10
AScha.3
Chief

0693W00000aJKUmQAO.pngso - if slave adress valid -> ack , otherwise no reception.

i would try some "standard" serial , e.g. USART in synchronous slave mode (with 9 bits , for ack), nss soft.

clk can go up to 20MHz ... that should be enough. 🙂

and at 1Mbit you have about 9us in INT to save the data.

If you feel a post has answered your question, please click "Accept as Solution".
Moritz1
Associate III

This is a good Idea, but unfortunately this will not work because the I2C slaves have a 10 Bit Address, so I would need 10Bit Addr + R/W Bit + ACK Bit = 12 Bit length and the USART can handle only 7, 8 or 9 Bit wordlength.

AScha.3
Chief

so you could try the SPI , in slave mode, 12 bit data. (nss low), max 75Mbit here. 🙂

0693W00000aJLSIQA4.png

If you feel a post has answered your question, please click "Accept as Solution".
Moritz1
Associate III

I think the biggest challenge at this point is the start/stop detection to identify when the 10-bit address is being received and when to switch to 9-bit data reception.

AScha.3
Chief

maybe difficult when switching data size while receiving...but you should try it.

write in INT to spix_CR2 ...data size.

but when using 2 SPI in parallel , one 12bit mode, in int switch it off and on other SPI which is in 9bit mode -- this could be also possible

If you feel a post has answered your question, please click "Accept as Solution".
Moritz1
Associate III

I tryed it out with SPI.

For the beginning with 7Bit Address.

Setup: 9 Bit Datasize (7Bit Addr + R/W + ACK / 8 Bit Data + ACK), SPI captures data on rising clock edge.

So I do not need any data size switching for the first try.

Startcondition i detect by interrupt: Falling edge on SDA while SCL is High. This interrupt enables the SPI. Than, SPI is receiving address and some bytes of data, this works fine.

But the Problem is the stop condition at the end of transfer.

As you can see here:

https://cdn.sparkfun.com/assets/learn_tutorials/8/2/I2C_Basic_Address_and_Data_Frames.jpg

For stop condition the SCL line goes high and thereafter the SDA goes high. So I can detect the stop condition with my interrupt on rising SDA edge, while SCL is high.

But the SPI peripheral has already shifted the first bit into shift register.

So at the next Start condition the SPI starts with one bit shifted ofset.

Unfortunately, it is not possible to reset the internal shift register of SPI after i have detected the stop condition (even not by disabling the peripheral).

Oo - the stop condition is a problem .

the spi shift-counter should be reset, when spi is disabled.

try write to SPIxCR1 ->

0693W00000aJlITQA0.pngthere must be some way to reset the counter - otherwise you could never use spi again, if it got one spike on clk line or got one wrong sized word.

for detect stop condition spontaneously i only have this idea :

need hardware : a d-flip-flop , 74HC74 or so.

flipflop is clocked by rising SDA , Data in is SCL ; -> FF output will rise on "stop" .

-> goes to cpu pin with exti int.

If you feel a post has answered your question, please click "Accept as Solution".

In this case the problem will still be the interrupt runtime, as I mentioned in the initial post.

In my application, after the stop condition, there is immediately another start condition to communicate with another device.

So the problem will be: On the stop condition, the SPI shifts 1 bit into the shift register, then the EXTI interrupt is triggered by the stop condition. But until I reach the handler and be able to disable and enable the SPI, I have missed the first clock edge of the new transmission.

There is always something...

but the INT should be fast enough, to write direct to register Spixx->CR1 , disa. then enable , return. at 100MHz you have 10ns cycle, INT latency in CortexM4 is 12 cycles,

so after about 130ns you do the 2 instuctions, maybe 2x3 cycles, you done it in < 200ns.

(and you could clk even set higher...); with "HAL calls" no chance. 🙂

If you feel a post has answered your question, please click "Accept as Solution".