STM32F103 I2C SLAVE problem! - Page 1
Forum section: electronics / general

author: DELTA67
author_rank: Regular Contributor
timestamp: September 25, 2023, 04:06:05 pm
content: Hi all,STM32F103 as an I2C master works as a charm.Now I want to use the STM32 @72MHz as an I2C slave connected to an AVR M328 as master. There's an SSD1306 in the circuit also. SCL freq = 100KHz. Systick interrupt occurs each 1ms.STM32 pseudo code:Initialize OLED and display a greetingWait forever:If a byte is received display itAT_M328 pseudo code:Init TWIDo forever:send start condition + slave addresssend 4 bytessend stop conditionFull code attached.Slave address = 0x30 in 7bit format.bytes to send: 0xC0, 0xC1, 0xC2, 0xC3If the NOSTRETCH bit in I2C-CR1 is cleared The STM32 ACKs the address but the M328 don't send any byte.If the NOSTRETCH is set The STM32 ACKs the address and the 1st byte so now the M328 can send one byte only.I verified this with a logic analyzer, SCL is kept LOW. It seems that the STM32 stretches SCL low (photos attached).Also the adress matching event or byte received interrupts never occur.Of course I've enabled the I2C event interrupt (IRQn = 31 )in the NVIC and written the corresponding handler.The event interrupt works. When I enable it after initializing the module the handler is executed.The M328 code is tested with an other slave and it works perfectly.I tried with no success:- Disabling the Systick interrupt.- Lowering SCL freq to 50KHz- Reseting the I2C module using RCC_APB1RSTR.- Drinking a beer !!How to configure SDA and SCL in slave mode? I used alternate function output open-drain @ 50MHz.Is pull-up resistors mandatory for the STM32's SCL and SDA? The circuit contains an SSD1306 which have pull-ups, also the M328 has it's internal pull-ups on PC4 and PC5 enabled.Please, What I'm missing??Thanks

author: wek
author_rank: Frequent Contributor
timestamp: September 25, 2023, 04:32:49 pm
content: Try polled implementation first, i.e. avoid interrupts, work just out of the status bits.Internal pullups are too weak, but may work at very low speeds.> Drinking a beer !!Good step, but repeating it usually won't help more.JW

author: DELTA67
author_rank: Regular Contributor
timestamp: September 25, 2023, 04:38:50 pm
content: Thanks wek for your proposition, I'll give it a try as soon as possible.

author: langwadt
author_rank: Super Contributor
timestamp: September 25, 2023, 04:44:04 pm
content: Quote from: wek on September 25, 2023, 04:32:49 pmhttps://xkcd.com/323/

author: DELTA67
author_rank: Regular Contributor
timestamp: September 25, 2023, 05:34:50 pm
content: I've tested the polling method:Code:for(;;){while(!(I2C1->SR1 & 1<<ADDR)); // wait for address maching// clear ADDR bit//(void)(I2C1 -> SR1);// read SR1(void)(I2C1->SR2);// read SR2// wait for STOP conditionwhile(!(I2C1->SR1 & 1<<STOPF)){if(I2C1->SR1 & 1<<RxNE){ // data available//(void)(I2C1 -> SR1);// read SR1data = I2C1 -> DR; // get the byte clearing RxNE meanwhileh2a(data); // print itSSD1306_UpdateScreen();}}// clear STOP bit//(void)(I2C1 -> SR1);// read SR1I2C1 -> CR1 |= 1<<PE;// dummy write}I recieve only the 1st byte!EDIT:This is only the polling part. See the full code attached in the 1st post.

author: DELTA67
author_rank: Regular Contributor
timestamp: September 25, 2023, 06:18:44 pm
content: Here's (in attachment) the logic analyzer result.By the way, how to insert an image into this text?After the start condition and the address 0x60= 0x30<<1 has been sent, the M328 sends the 4 bytes: 0xC0, 0xC1, 0xC2, 0xC3 and finally the STOP condition.Only now the STM32 prints the 1st byte the other 3 are lost.In the code the print is done before receiving the STOP.

author: DELTA67
author_rank: Regular Contributor
timestamp: September 25, 2023, 06:28:39 pm
content: Ok, perhaps the problem comes from the fact that the STM32 can't be slave and master in the same time!!slave of the M328master of the OLEDI'll try to collect the 4 bytes and print them after receiving the STOP condition.EDIT:YES, it works!!Now, for the interrupt method.As I said, the STM32 ACKs the address but the address matching event interrupt don't occure.

author: DavidAlfa
author_rank: Super Contributor
timestamp: September 25, 2023, 08:11:39 pm
content: Quote from: DELTA67 on September 25, 2023, 05:34:50 pmWhat do you expect with that code?You must check for the incoming data, reading DR to avoid overflow and ACKing to the master.You're missing basically everything about i2c protocol.Read theRM0008, starting at page 752.Go to github and search for i2c routines, you'll find tons of them.

author: DELTA67
author_rank: Regular Contributor
timestamp: September 26, 2023, 06:56:59 am
content: Thanks DavidAlfa for your reply,Quote from: DavidAlfa on September 25, 2023, 08:11:39 pmThis is only the "polling" part.- Wait until we are addressed then clear the ADDR flag- Wait until a STOP conditionMeanwhile: check the RxNE flag, if set read the received byte this clears the flag also.- Clear the STOPF flag.ACKing is done by the hardware.