El esclavo no puede tirar de I2C bajo

Estoy tratando de usar 3 TCA9539PWR y un TCA6408A en un bus I2C.

Aquí está el diagrama esquemático:

ingrese la descripción de la imagen aquí

Sin embargo, cuando trato de enviar las direcciones del TCA9539PWR, ninguno de ellos responde (sin ACK) y cuando intento enviar la dirección del TCA6408A (0x40), la ola muestra que no puede bajar el bus por completo.

ingrese la descripción de la imagen aquí

Uso resistencias pull-up de 10k, y creo que la resistencia es lo suficientemente fuerte; no puedo cambiar la resolución en la placa de circuito impreso fácilmente, por lo que es difícil para mí probar eso.

Esa es una parte del código que uso para controlar SDA y SCL:


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);
¿Mostrarías el código donde se inicializan los pines SDA y SCL?
@Justme Claro, he editado mi pregunta. Gracias.
¿No debería estar el modo GPIO en un modo de drenaje abierto? Está utilizando el modo push-pull GPIO. Creo que ese podría ser el problema.
No entiendo por qué bitbanging el I2C en el software, ya que el STM32 contiene un periférico I2C para que no tenga que bitbangear.

Respuestas (2)

Los pines I2C no deben establecerse en salida alta. Está utilizando salidas push-pull. STM32 puede configurarlos como salidas de drenaje abierto. En ese caso ni siquiera es necesario cambiarlo a entrada para lectura. En realidad, usted mismo no rompería el protocolo, ya que el STM32 contiene un periférico i2C.

La otra forma de bit-bang I2C sin usar el modo de colector abierto es preestablecer el bit de registro de salida a cero y cambiar al registro de modo para el valor de salida: entrada para alto (en realidad Z alto) o salida para unidad baja.

La línea SDA debe configurarse como drenaje abierto, no como push-pull. Con push-pull, el esclavo tira hacia abajo, mientras que su maestro tira hacia arriba.