cancel
Showing results for 
Search instead for 
Did you mean: 

I2C: How to detect if ack failed

rickard
Associate II
Posted on June 30, 2009 at 22:13

I2C: How to detect if ack failed

5 REPLIES 5
rickard
Associate II
Posted on May 17, 2011 at 09:52

I'm having some problems with the I2C bus. I can use it for sending and receive data but I can't detect if the Slave is acknowledging the data or not.

My code looks likes:

I2C_GenerateStart(I2C0, ENABLE);

if( PF_I2C_WaitForAck(I2C_EVENT_MASTER_MODE_SELECT) != PF_OK )

{

return PF_ERROR;

}

I2C_Send7bitAddress(I2C0, SlaveAddress, I2C_MODE_TRANSMITTER);

if( PF_I2C_WaitForAck(I2C_EVENT_MASTER_MODE_SELECTED) != PF_OK )

{

return PF_ERROR;

}

I2C_Cmd(I2C0, ENABLE);

for(Index=0;Index

{

I2C_SendData(I2C0, Data[Index]);

if( PF_I2C_WaitForAck(I2C_EVENT_MASTER_BYTE_TRANSMITTED) != PF_OK)

{

return PF_ERROR;

}

if(I2C_CheckEvent(I2C0, I2C_EVENT_SLAVE_ACK_FAILURE) == SUCCESS)

{

PF_PutStringSC0_SCI((uint8 *)''ACK failed'');

return PF_ERROR;

}

}

if(GenerateStop == TRUE)

{

I2C_GenerateSTOP(I2C0, ENABLE);

}

The function PF_I2C_WaitForAck() waits for en event to occur and times out after 100 ms.

The I2C is setup as:

SCU_APBPeriphClockConfig(__I2C0,ENABLE);

I2C_DeInit(I2C0);

I2C_Struct.I2C_CLKSpeed = I2C_CLK_SPEED;

I2C_Struct.I2C_OwnAddress = I2C_MASTER_ADDRESS;

I2C_Struct.I2C_GeneralCall = I2C_GeneralCall_Disable;

I2C_Struct.I2C_Ack = I2C_Ack_Enable;

I2C_Init(I2C0, &I2C_Struct);

I2C_ITConfig(I2C0, DISABLE);

How to use the I2C_EVENT_SLAVE_ACK_FAILURE to see when the ack fails???

[ This message was edited by: rickard.thorstensson on 21-04-2008 08:36 ]

rich2
Associate II
Posted on May 17, 2011 at 09:52

I was able to get this working, but not by using I2C_CheckEvent(...). (I am using version 1.1 of the STR91x library.) Through lots of experimentation I discovered that although the ACK failure bit (AF) is alongside the other 'events' in the status registers, ACK failure is not an event but rather just a momentary condition. When you read the status register that contains the AF bit, the bit is automatically cleared.

The way to test for ACK failure that I use is to call I2C_GetLastEvent(..) and check for the specific AF bit (it may be 0x1000, I can't recall for sure). Don't use the masks provided by the firmware library, they don't work in this case. Specifically, looking for EVF | AF won't work, as this condition never occurs.

One caution though, I have only used this technique when testing for ACK failure after the first byte (the address byte) in order to see if the slave I'm addressing is actually there. I haven't used it for testing for ACK failure during the data bytes themselves, so this may not work.

This reply is long after the OP was made, but hopefully it will help somebody else out.

Rich

rickard
Associate II
Posted on May 17, 2011 at 09:52

Am I the only one using the I2C bus??? Someone must know how to detect if a slave is acking or not. I think it is very strange that the example code provided by st does not include this check.

ghofbauer9
Associate
Posted on June 03, 2011 at 10:19

Hi,

I have exactly the same story going on!

However, I can see the ACK on my DSO, The AF Flag is never set.

Wheter on right I2C address or wrong. I would like to know WHEN to check

for the AF Flag after addressing, as the adressing-finished (ENDAD) flag,

needs also to be checked. If the AF flag is cleared on reading the status register,

this ends in a dilemma, as it is uncertain which flasg comes up first.......

Hope anybody has an idea..

ghofbauer9
Associate
Posted on June 03, 2011 at 10:35

Hi,

problem solved, the AF flag is SET BEFORE ENDAD flag!

do

  {

      lastevent = I2C_GetLastEvent(I2C0);

    if (lastevent & I2C_FLAG_AF)

    {

                I2C_GenerateSTOP (I2C0, ENABLE);

                I2C_Cmd (I2C0, DISABLE);

                  return -1;

    }

    else if (lastevent  == I2C_EVENT_MASTER_MODE_SELECTED)

    {

       

            break;

    }

  }while(1 == 1);