STM32F415 seltsames I2C-Verhalten

Ich verwende einen STM32F415RGT6, der in das 1Bitsy-Board eingebettet ist. Ich möchte das I2C-Peripheriegerät einrichten, um einige Daten von einem Sensor zu lesen. Ich verwende die Standard-Peripheriebibliothek stm32f4.

Mein Beispielcode:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 

GPIO_InitTypeDef gpioInit;

GPIO_StructInit(&gpioInit);

gpioInit.GPIO_Mode = GPIO_Mode_AF;

gpioInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

gpioInit.GPIO_PuPd = GPIO_PuPd_UP;

gpioInit.GPIO_Speed = GPIO_Speed_25MHz; 

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); 

GPIO_Init(GPIOB, &gpioInit); 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 

I2C_DeInit(I2C1);

I2C_InitTypeDef I2C_InitStructure;

I2C_StructInit(&I2C_InitStructure);


/* I2C configuration */

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_ClockSpeed = 100000;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0x01;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C1, &I2C_InitStructure);

I2C_Cmd(I2C1, ENABLE);


while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));


/* Generate Start, send the address and wait for ACK */

I2C_GenerateSTART(I2C1, ENABLE);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

I2C_Send7bitAddress(I2C1, 0xE0, I2C_Direction_Transmitter);


while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

Danach will ich ein 0x00 schreiben, aber der Code hängt immer in der letzten Zeile, anscheinend liest der Master die Acknowledge nie. Die I2C-Statusregister lesen immer:

I2C1 -> SR1 = 1024

I2C1 -> SR2 = 3

Das bedeutet, dass das Acknowledge-Failure-Bit immer gesetzt ist. Wenn ich es mit meinem Saleae analysiere, erhalte ich Folgendes:

STM32F415 Logikanalysator

Der Slave sendet die ACK, aber der STM32F415 kann sie nicht lesen.

Das Seltsame: Wenn ich den gleichen Code auf meinem F407 - Disco versuche (nur mit auf 400 kHz eingestelltem Takt, aber es ist das gleiche Verhalten auf beiden MCUs, unabhängig von Speed), funktioniert es einwandfrei:

STM32F407-DISCO Logikanalysator

Alle anderen Peripheriegeräte funktionieren einwandfrei. Ich habe bereits mehrere Problemumgehungen ausprobiert, aber das AF-Bit ist immer gesetzt, unabhängig von der Methode. Ich hoffe ihr könnt mir helfen.

PS: Ich habe es mit und ohne zusätzliche Pullups versucht und die I2C-Slave-Adresse ist in Ordnung, weil sie mit STM32F0, STM32F4-DISCO und Atmel Mcus funktioniert.

Beste Grüße und Danke im Voraus!

gpioInit.GPIO_PuPd = GPIO_PuPd_UP;sollte gpioInit.GPIO_PuPd = GPIO_OType_OD; mit Klimmzügen sein.
ja in der Tat, aber leider habe ich es getan, ich weiß nicht, warum es beim Kopieren des Codes von Eclipse hierher gerutscht ist. Sorry für die Verwirrung
Ich würde sagen, die Slave-Adresse ist nicht korrekt, wenn die 7-Bit-Slave-Adresse lautet, 0xE0müssen Sie die 8-Bit-Adresse an die API übergeben, I2C_Send7bitAddress(I2C1, uint8_t(0xE0<<1), I2C_Direction_Transmitter);aber ich vermute stark, dass es 0x70 ist und Sie sie bereits verschoben haben
Hast du ein Oszilloskop, das du anstelle des Saleae ausprobieren kannst? Wenn ich Probleme mit I2C hatte, lag das daran, dass mein Pullup zu schwach und die Wellenform sehr schlampig war. Die Saleae würden das nicht zeigen, aber ein Zielfernrohr würde es tun.
@AbelTom die I2C Send7Bit-Funktion konvertiert das 8-Bit-Format.
@ammar.cma Ich weiß nicht, von welcher Implementierung Sie sprechen, aber ich sprach von der Std_Periph/CMSIS-Implementierung, die Funktion enthält keine Verschiebungsoperationen. Und eigentlich sollte die 7-Bit-Adresse + R-Bit gesendet werden.
Der F407 scheint nicht einwandfrei zu funktionieren. Die Stoppbedingung fehlt (würde als roter Punkt angezeigt). Für die Stoppbedingung sollte SCK auf High gehen, bevor SDA auf High geht.

Antworten (1)

danke für alle vorschläge. Ich habe die Lösung gefunden und sie ist irgendwie seltsam. Es funktioniert auf beiden Platinen korrekt, aber auf dem STM32F415 funktioniert es nicht, wenn der Logikanalysator die Daten erfasst. Beim F407 spielt es keine Rolle. Es ist eine Art Heisenbug, es passiert nicht, wenn ich nicht hinschaue, aber ich musste schauen, um zu wissen, ob es funktioniert.

Dies bedeutet wahrscheinlich, dass Ihre Pullup-Widerstände zu schwach sind. Dies ist einer der Gründe, warum das Betrachten mit einem Oszilloskop nützlich ist, um den Charakter des Signals zu erkennen, selbst wenn der Logikanalysator das Protokoll besser entschlüsseln kann (zumindest sobald Sie eine nicht triviale Datenmenge erhalten, die die Geschwindigkeit und Benutzeroberfläche eines der eingebaute I2C-Decoder eines typischen modernen Oszilloskops).
Und wenn Ihr Unternehmen ein Oszilloskop kauft, aber keine Lizenz für den I2C-Decoder kauft