4
\$\begingroup\$

I am trying to implement bit-banging i2c to communicate between an atmega128A's GPIO and an SHT21 (I2C bus was used for some other devices). The first task is to send a write sequence to the SHT21. Using an oscilloscope, I can see that the sequence sending out from the atmega has the correct start signal, correct order of bits, correct stop signal, signal levels looks correct. The serial analyzer from the scope reads out correct I2C message: S80W~A (SHT21 address is 0x80, writing so last bit is 0). Yet there is not any ACK response from the SHT21. The SDA and SCL are both pulled up to 3.3V via 6.7K resistors.

I really need help finding out what is wrong.

code sending the first byte repeatly if no ACK receive:

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

code of i2c protocol:

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
    }

}
\$\endgroup\$
  • \$\begingroup\$ Does the device respond if you put it on the proper I2C bus? \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 14 '14 at 23:00
  • \$\begingroup\$ I assume you are asking about the SHT21, yes it responses correctly on a proper I2C bus \$\endgroup\$ – user3421560 Mar 14 '14 at 23:07
  • 1
    \$\begingroup\$ @user3421560 Can you edit your question and add a few more things: snippet of your bit-banging code, oscilloscope screenshot of the first byte on your I2C (both SDA and SCL, if possible) ? \$\endgroup\$ – Nick Alexeev Mar 14 '14 at 23:16
  • \$\begingroup\$ You asked the same question on Stackoveflow and I'm repeating my comment: are you actually putting the GPIOs in open-collector/drain mode? In other words, when you call SCK_HI or DATA_HI, does your GPIO just release the line (correct) or force it high (bad)? \$\endgroup\$ – DoxyLover Mar 15 '14 at 0:41
  • \$\begingroup\$ @DoxyLover Thank you so much for your comment. I put it here since someone left a comment saying it would be better luck to try over here. About the problem. In the code I set SCK and SDA high by calling setbit(port, pinnumber). It does seem like it is forcing the line high. I will try to fix it asap \$\endgroup\$ – user3421560 Mar 15 '14 at 1:53
3
\$\begingroup\$

Per your comment, your GPIO pins are not open-collector but are forcing both high and low. I2C requires open-collector on both the clock and data lines. Without this, the slave cannot, for example, ACK by pulling the data line low (since the master is actively pulling it high).

If you cannot set open-collector mode, another way is to leave the output data bit low and switch the pin mode between output (low) and input (effectively open-collector).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.