Jump to content
 
DavePfz

Detection of I2C Address NAK

Recommended Posts

This is a follow through of the discussion at https://www.microforum.cc/topic/90-help-with-mcc-generated-i2csimple-getting-stuck-in-a-loop/

I have a need to poll the I2C bus to detect presence or absence/failure of a device in a system controlled by a PIC18LF46K22. The code base is generated by MPLAB's MCC. The post above addressed that type of situation.

I tried to work through that discussion in comparing it to the current code generated by MCC and have noted too many differences. That discussion was 2 years ago and I'm sure there have been many changes to MCC since that time.

So, the question boils down to: In the current scheme as generated by MCC is there a way for the application to determine that an I2C Address has been NAK'ed?

Thanks for any pointers...

Share this post


Link to post
Share on other sites

I just downloaded the latest MPLAB (V5.50) and MCC (V5.03, Classic), setup a project with the 18LF46K22 and added the MSSP peripheral.

This driver has callbacks for all the major states.  When a device is not present there will be a NAK in the address phase.  The callback you will need is configured with 

void I2C1_SetAddressNackCallback(i2c1_callback_t cb, void *ptr);
So you can create a callback for the NAK as follows:


typedef struct
{
  i2c1_address_t address;
  bool present;
} address_present_t;

i2c1_operations_t callbackAddrNak(void *funPtr)
{
	address_present_t *Present = funPtr;
  	Present.present = false;
  	return I2C1_STOP;
}

// this code comes from the i2c1_master_example provided by MCC
uint8_t I2C1_Read1ByteRegister(i2c1_address_t address, uint8_t reg)
{
    uint8_t returnValue = 0x00;
  	address_present_t present;
	present.address = address;
    
    while(!I2C1_Open(address)); // sit here until we get the bus..
  	I2C1_SetAddressNackCallback(callbackAddrNak,&present; // setup the address NACK callback with the address data 
    I2C1_SetDataCompleteCallback(rd1RegCompleteHandler,&returnValue);
    I2C1_SetBuffer(&reg,1);
    I2C1_MasterWrite();
    while(I2C1_BUSY == I2C1_Close()); // sit here until finished.
    
    if(present.present == FALSE)
	{
      // do something appropriate.
      // some memories fail to respond (generate a NAK) when they are busy.
      // a missing device will also result in a NAK.
    }
                                
    return returnValue;
}


Note:  A NAK can be the "normal" operation of some devices such as a memory.  Often an EEPROM will refuse to ACK their address when they are busy writing.  You use a process called NAK polling.  If you do the device scan during a time when you can expect all devices to be active and ready, then you should be able to generate a map of the available addresses.

 

Good Luck

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


 


×
×
  • Create New...