STM32 als I2C Slave

Gast #4661802
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
Angehängte Dateien:
(Firma: matzetronics)
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.
Gast
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?
Gast
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?
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.
Gast
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!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.