bitbanging i2c problema con ACK de esclavo

4

Estoy tratando de implementar i2c de bit banging para comunicarse entre un GPIO de atmega128A y un SHT21 (el bus I2C se usó para algunos otros dispositivos). La primera tarea es enviar una secuencia de escritura al SHT21. Al usar un osciloscopio, puedo ver que la secuencia de envío desde la atmósfera tiene la señal de inicio correcta, el orden correcto de los bits, la señal de detención correcta y los niveles de señal parecen correctos. El analizador en serie del alcance lee el mensaje I2C correcto: S80W ~ A (la dirección SHT21 es 0x80, y el último bit es 0). Sin embargo, no hay ninguna respuesta ACK del SHT21. El SDA y el SCL se elevan a 3.3V a través de resistencias de 6.7K.

Realmente necesito ayuda para descubrir qué está mal.

El código

envía el primer byte repetidamente si no se recibe ACK:

 i2c_start();
  while(!i2c_send(0x80)){
    i2c_stop();
    i2c_start();
  }

código del protocolo i2c:

void i2c_start ()
{
    // Pull data high and sck low to ensure transition of start sequence
    DATA_HIGH ();

    SCK_HIGH ();
    DATA_LOW ();
    SCK_LOW ();
}
void i2c_stop ()
{
    DATA_LOW ();
    SetBit (DDRD, 7);
    //pull data high while clck is high to end transmission.
    SCK_HIGH ();
    DATA_HIGH ();
}

uchar i2c_send (uchar command)
{
    uchar i;

    for (i = 0; i < 8; i++)     // Send command
    {


        if ((command & 0x80) == 0x80)
            DATA_HIGH ();
        else
            DATA_LOW ();
        SCK_LOW ();
        SCK_HIGH ();
        SCK_LOW ();

        command = command << 1;
    }

    Delay(5);
    ClrBit (DDRD, 7);       // Change Data Direction
    //SetBit (PORTD, 7);      // Turn on internal pull-up

    //SCK_LOW ();
    SCK_HIGH ();

    if (!CheckBit (PIND, 7))     // Read ACK
    {
        SCK_LOW ();
        SetBit (DDRD, 7);
        return 1;
    }
    else
    {
        SCK_LOW ();
        SetBit (DDRD, 7);
        return 0;               // NO ACK
    }

}
    
pregunta user3421560

1 respuesta

3

Según su comentario, sus pines GPIO no son de colector abierto, sino que están forzando a alto y bajo. I2C requiere un colector abierto tanto en el reloj como en las líneas de datos. Sin esto, el esclavo no puede, por ejemplo, ACK tirando de la línea de datos a un nivel bajo (ya que el maestro la está colocando a un nivel alto).

Si no puede establecer el modo de colector abierto, otra forma es dejar el bit de datos de salida bajo y cambiar el modo pin entre salida (bajo) y entrada (colector abierto de manera efectiva).

    
respondido por el DoxyLover

Lea otras preguntas en las etiquetas