This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Having a bit of trouble waiting for a pin to go high

I'm fairly new to working this close to hardware and am playing around with a few things.  I'm trying to bit bang i2c over a couple of gpio lines and everything seems to be working just fine until I try to read the ack/nack bit after a write.  In the attached image the address is sent just fine, but when the register is sent it appears the slave holds down the line, which should be fine.  However my code for the byte write looks like the following:

uint8 i2c_write(uint8 data, const uint32_t clockPin, const uint32_t dataPin)
{
    uint8 ndx, ack  = 0;

    nrf_gpio_cfg_output(dataPin);

    for(ndx = 0; ndx < 8; ndx++)
    {
        nrf_gpio_pin_clear(clockPin);

        //get the current bit to send
        if(data & 0x80)
        {
            nrf_gpio_pin_set(dataPin);
        }
        else
        {
            nrf_gpio_pin_clear(dataPin);
        }

        nrf_gpio_pin_set(clockPin);

        /* Ensure that the clock is high */
        if( !waitForSCL(clockPin) )
        {
            //we failed to bring the clock high
            comTimeout = TRUE;
            break;
        }

        //next bit
        data <<= 1;
    }//end for

    nrf_gpio_pin_clear(clockPin);

    nrf_gpio_cfg_input(dataPin, NRF_GPIO_PIN_NOPULL);

    nrf_gpio_pin_set(clockPin);

    /* Ensure that the clock is high */
    if( !waitForSCL(clockPin) )
    {
        //we failed to bring the clock high
        comTimeout = TRUE;
    }

    ack = nrf_gpio_pin_read(dataPin);

    // pull both lines low again
    nrf_gpio_pin_clear(clockPin);

    nrf_gpio_cfg_output(dataPin);
    I2C_LOW(dataPin);

    //acks are low, nacks are high
    return !ack;
} //end i2c_write

static boolean waitForSCL(uint32_t clockPin)
{
    uint16 maxTries = MAX_TRIES;

    while( 0 == nrf_gpio_pin_out_read(clockPin)  && (maxTries>0) )
    {
        nrf_gpio_pin_set(clockPin);
        maxTries--;
    }

    return ( maxTries > 0 );
} // end of waitForSCL

Output from logic analyzer (SCL on bottom, SDA on top):

It looks like the function waitForSCL isn't doing what I'm intending for it to do.  Since I'm setting the clock high right before I check this function it makes sense that many times the first call to nrf_gpio_pin_out_read would read the line high right away, but when the slave is clock stretching it seems to still always read that as high.  I've tried a bunch of different delays and a bunch of other stuff, but I appear to be stuck.  Most likely this is an easy fix that I'm just not familiar enough with the SDK APIs to figure out.  Thanks for any help!

Parents Reply Children
  • It is not the slave that is holding down the clock. You are just before exiting the write function.  After that since there are no clock, no response from slave because it is waiting for your clock to go high. 

  • I'm definitely having trouble seeing this so I quickly implemented the same functionality with TWI just to test against.  The output seems pretty similar to what I have in the image above (timing is different of course).

    After the clock cycle on this one on the far right the two bytes that are expected to be written to the register are there, which leads me to believe that this is a very delayed ack/nack bit similar to the image above.  The difference is the TWI code waits for that ack/nack and my code does not.

    The goal of the WaitForSCL function for me was to essentially hang just like this

    until the clock line went high again so I could read the data line for the ack/nack.

Related