Slave kann I2C nicht auf Low ziehen

Ich versuche, 3 TCA9539PWR und einen TCA6408A auf einem I2C-Bus zu verwenden.

Hier ist das schematische Diagramm:

Geben Sie hier die Bildbeschreibung ein

Wenn ich jedoch versuche, die Adressen des TCA9539PWR zu senden, antwortet keine von ihnen (kein ACK), und wenn ich versuche, die Adresse des TCA6408A (0x40,) zu senden, zeigt die Welle, dass der Bus nicht vollständig heruntergezogen werden kann.

Geben Sie hier die Bildbeschreibung ein

Ich verwende 10k-Pullup-Widerstände, und ich denke, der Widerstand ist stark genug. Ich kann die Auflösung auf der Platine nicht einfach ändern, daher ist es für mich schwierig, das zu testen.

Das ist ein Teil des Codes, den ich zur Steuerung von SDA und SCL verwende:


void SDA_OUT(void) //init SDA to send Data
{
   GPIO_InitTypeDef GPIO_InitStruct;
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   GPIO_InitStruct.Pin = I2C_SDA_Pin;
   HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct );
}

//...

void SDA_IN(void)    //release the SDA wire
{
   GPIO_InitTypeDef GPIO_InitStruct = {0};
   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   GPIO_InitStruct.Pin = I2C_SDA_Pin;
   HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct );
}

//The SCL wire was initialized by STM32CUBEMX;
  GPIO_InitStruct.Pin = I2C_SDA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Würden Sie den Code zeigen, wo die SDA- und SCL-Pins initialisiert werden?
@Justme Sicher, ich habe meine Frage bearbeitet. Danke.
Sollte der GPIO-Modus nicht ein Open-Drain-Modus sein? Sie verwenden GPIO im Push-Pull-Modus. Ich denke, das könnte das Problem sein.
Ich verstehe nicht, warum das I2C in Software bitbangt wird, da der STM32 ein I2C-Peripheriegerät enthält, sodass Sie nicht bitbangen müssen.

Antworten (2)

I2C-Pins dürfen nicht auf High-Ausgang gesetzt werden. Sie verwenden Push-Pull-Ausgänge. STM32 kann sie als Open-Drain-Ausgänge konfigurieren. In diesem Fall ist es nicht einmal erforderlich, ihn auf Eingabe zum Lesen zu ändern. In Wirklichkeit würden Sie das Protokoll nicht selbst bitbangen, da der STM32 ein i2C-Peripheriegerät enthält.

Die andere Möglichkeit, I2C zu bitbangen, ohne den Open-Collector-Modus zu verwenden, besteht darin, das Ausgangsregisterbit auf Null zu setzen und für den Ausgangswert in das Modusregister zu wechseln: Eingang für High (tatsächlich High-Z) oder Ausgang für Low.

Die SDA-Leitung sollte als Open Drain konfiguriert werden, nicht als Push-Pull. Beim Push-Pull zieht der Sklave tief, während dein Herr hoch zieht.