Author Topic: STM32F103 I2C SLAVE problem!  (Read 2525 times)

0 Members and 1 Guest are viewing this topic.

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
STM32F103 I2C SLAVE problem!
« on: September 25, 2023, 04:06:05 pm »
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 greeting
Wait forever:
   If a byte is received display it

AT_M328 pseudo code:
Init TWI
Do forever:
   send start condition + slave address
   send 4 bytes
   send stop condition

Full code attached.

Slave address = 0x30 in 7bit format.
bytes to send:  0xC0, 0xC1, 0xC2, 0xC3

If 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
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 560
  • Country: sk
Re: STM32F103 I2C SLAVE problem!
« Reply #1 on: September 25, 2023, 04:32:49 pm »
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
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F103 I2C SLAVE problem!
« Reply #2 on: September 25, 2023, 04:38:50 pm »
Thanks wek for your proposition, I'll give it a try as soon as possible.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4986
  • Country: dk
Re: STM32F103 I2C SLAVE problem!
« Reply #3 on: September 25, 2023, 04:44:04 pm »
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

https://xkcd.com/323/
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F103 I2C SLAVE problem!
« Reply #4 on: September 25, 2023, 05:34:50 pm »
I've tested the polling method:

Code: [Select]
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 condition
while(!(I2C1->SR1 & 1<<STOPF)){
if(I2C1->SR1 & 1<<RxNE){      // data available
//(void)(I2C1 -> SR1); // read SR1
data = I2C1 -> DR;          // get the byte clearing RxNE meanwhile
h2a(data);                       // print it
SSD1306_UpdateScreen();
}
}
// clear STOP bit
//(void)(I2C1 -> SR1); // read SR1
I2C1 -> 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.
« Last Edit: September 27, 2023, 06:07:45 pm by DELTA67 »
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F103 I2C SLAVE problem!
« Reply #5 on: September 25, 2023, 06:18:44 pm »
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.
« Last Edit: September 25, 2023, 06:21:27 pm by DELTA67 »
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F103 I2C SLAVE problem!
« Reply #6 on: September 25, 2023, 06:28:39 pm »
Ok, perhaps the problem comes from the fact that the STM32 can't be slave and master in the same time!!
slave of the M328
master of the OLED
I'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.
« Last Edit: September 25, 2023, 06:58:05 pm by DELTA67 »
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: STM32F103 I2C SLAVE problem!
« Reply #7 on: September 25, 2023, 08:11:39 pm »
I've tested the polling method:

Code: [Select]
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 condition
while(!(I2C1->SR1 & 1<<STOPF)){
if(I2C1->SR1 & 1<<RxNE){      // data available
//(void)(I2C1 -> SR1); // read SR1
data = I2C1 -> DR;          // get the byte clearing RxNE meanwhile
h2a(data);                       // print it
SSD1306_UpdateScreen();
}
}
// clear STOP bit
//(void)(I2C1 -> SR1); // read SR1
I2C1 -> CR1 |= 1<<PE; // dummy write
}
I recieve only the 1st byte!


What 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 the RM0008, starting at page 752.

Go to github and search for i2c routines, you'll find tons of them.
« Last Edit: September 25, 2023, 08:13:34 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F103 I2C SLAVE problem!
« Reply #8 on: September 26, 2023, 06:56:59 am »
Thanks DavidAlfa for your reply,
What do you expect with that code?
This is only the "polling" part.
- Wait until we are addressed then clear the ADDR flag
- Wait until a STOP condition
  Meanwhile: 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.
« Last Edit: September 26, 2023, 09:55:18 am by DELTA67 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf