Forum: Mikrocontroller und Digitale Elektronik STM32 als I2C Slave


von Johannes H. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche verzweifelt, einen STM32F100 als I2C Slave einzusetzen. Der 
Master ist auch ein STM32, der schon erfolgreich einen anderen Slave 
angesteuert hat.

Mein Problem ist, dass ich oft (in ~95% der Fälle) keinen Acknowledge 
vom Slave erhalte, obwohl das Acknowledge Enable Bit beim Slave gesetzt 
ist.

Anbei findet ihr auch die beschrifteten Oszibilder, einmal der weitaus 
häufigere Fall, in dem der Slave seine Adresse nicht mit Acknowledge 
quittiert, und einmal der Fall, in dem er es tut (sollte der Master 
nicht am Ende High als Nack senden?)

Hier der initialisierende Code vom Slave:
1
GPIO_InitTypeDef GPIO_InitStructure;
2
  NVIC_InitTypeDef NVIC_InitStructure;
3
  I2C_InitTypeDef I2C_InitStructure;
4
5
  SystemInit();
6
7
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
8
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
9
10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
  GPIO_Init(GPIOB, &GPIO_InitStructure);
14
15
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
16
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
17
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
18
  GPIO_Init(GPIOC, &GPIO_InitStructure);
19
20
  NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
21
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
22
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
23
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
24
  NVIC_Init(&NVIC_InitStructure);
25
26
  NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
27
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
28
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
29
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
30
  NVIC_Init(&NVIC_InitStructure);
31
32
  I2C_DeInit(I2C1);
33
34
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
35
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
36
  I2C_InitStructure.I2C_ClockSpeed = 100000;
37
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
38
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
39
  I2C_InitStructure.I2C_OwnAddress1 = I2C_OWN_ADRESS;
40
  I2C_Init(I2C1, &I2C_InitStructure);
41
42
  I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
43
  I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);
44
  I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
45
46
  I2C_Cmd(I2C1, ENABLE);



Anmerkungen:
1. Master mit 7-Bit-Slave-Adresse 0x15 soll das Datenbit 0x33 senden. 
(Sollte fehlerfrei funktionieren, wurde schon eigesetzt).
2. Slave mit der Adresse 0x15: Interrupt Routine noch nicht 
implementiert, soll zunächst nur seine Adresse mit ACK quittieren, 
funktioniert in etw. 5% aller Fälle.


Ich weiß echt nicht mehr weiter, ich hoffe Ihr könnt mir helfen!
Danke schon im Voraus,

Grüße
Johannes

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Johannes H. schrieb:
> adresse_kein_ack.png

Das sieht sehr unsauber aus. Die gleichzeitigen Einbrüche auf SDA und 
SCL vor der Startbedingung sind gut dazu geeignet, Slaves aus dem Tritt 
zu bringen.
Woher kommen die? Es muss dafür gesorgt sein, das da saubere Signale 
stehen, denn bei I²C ist jeder Fehlimpuls ein möglicher I2C Zustand, der 
vom Slave (fehl-)interpretiert wird.

von Johannes H. (Gast)


Lesenswert?

Danke für die schnelle Antwort!

Ich weiß nicht, woher die kommen, ich bilde mir ein, die waren immer 
schon da. Die Spannungsversorgung sollte stabil sein, es hängen keine 
Verbraucher an der Platine. Bis jetzt hat der Master wie gesagt 
wunderbar funktioniert...
Wo könnten die Spannungseinbrüche herkommen?
Kann es sein, dass das Problem noch wo anders liegt?

von Pogo (Gast)


Lesenswert?

Der 1. Einbruch sollte nicht relevant sein, da der Startzustand den 
Slave zurücksetzt. Der 2. Einbruch - während des Startzustands - könnte 
problematisch sein.

Wie sehen die Schaltpläne (Master, Slave) aus? PullUps installiert?

von Phantomix X. (phantomix)


Lesenswert?

Ich behaupte es liegt daran, dass du die Pins initialisierst bevor der 
I2C überhaupt eingeschalten wird. Der Mux steht also auf "AF" und der 
Treiber des GPIO kriegt erstmal ne "0", was dazu führt, dass er trotz 
OpenDrain-Konfiguration treibt.

Leider ist die interne Statusmaschine des I2C beim STM32 etwas hakelig, 
wenn die Pins erst zum Schluss initialisiert werden. Würd ich aber 
trotzdem mal probieren.

von Johannes H. (Gast)


Lesenswert?

Ja, es klappt!

Die Einbrüche waren das Problem und die Lösung war, den I2C zu enablen, 
bevor die PB6 und PB7 initialisiert werden.

Danke an alle Helfer, besonders an Phantomix Ximotnahp!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.