I2C implementation Communication Ack issue

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
AsDh_4015406
Level 1
Level 1
10 sign-ins 5 replies posted 5 questions asked

Hi All,

I  tried to implement I2C communication between Cy8C4025AZI-S412( Slave ) and Pic Microcontroller(Master). The speed is 100kbps and used polling method. When button not pressed then it will sent 0xFF. The polling time is 100msec by PIC controller.

The issue is, 

1) Sometimes acknowledge not given by Slave.(need to sent data 3 to 4 times  or delay of 30ms  then it gives ack ).

I used one example code to develop I2C.

My code is below,

#include <project.h>

/* Macro Declaration */
#define BUFFER_SIZE (1u)
#define PACKET_SIZE (BUFFER_SIZE)

/* The I2C Slave read and write buffers */
uint8 i2cReadBuffer [BUFFER_SIZE] = {0};
uint8 i2cWriteBuffer[BUFFER_SIZE]= {0};

uint8_t flag1=0;

uint8_t flag3=0;

void Received_Data_From_Master1();

int main()
{

     /* Eneble Global Interrupt */

      CyGlobalIntEnable;

      CapSense_Start();
      CapSense_ScanAllWidgets();

     /* Start the I2C Slave And I2C Address Setting*/
     I2CS_I2CSlaveInitReadBuf(i2cReadBuffer, BUFFER_SIZE);
     I2CS_I2CSlaveInitWriteBuf(i2cWriteBuffer, BUFFER_SIZE);

       I2CS_I2CSlaveSetAddress(0x08);
       I2CS_Start();

for (;;)
{
    CyDelay(2);
   /* With Respect to Master i.e Checked Whether the Master Write Complted Or Not */
    if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_WR_CMPLT))
{
          /* Calling Function to Collect The Data From Master */
          Received_Data_From_Master1();
          /* Enable this above function when we used the data On Switch Function */

            /* Clear the slave write buffer and status */
            I2CS_I2CSlaveClearWriteBuf();
            (void) I2CS_I2CSlaveClearWriteStatus();
}

if(CapSense_NOT_BUSY == CapSense_IsBusy())
{
      /* API For Capsense Update Scanning And Process */
      CapSense_ProcessAllWidgets();           /* Process all widgets */
      CapSense_RunTuner();                            /* To sync with Tuner application */
      /* Checked whether Left Button Active or Not*/
if((flag3==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID)) )
{
      flag3=1;              /* Reseting Left Button Flag */
      i2cReadBuffer[0] = 0x01;
      while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
      /* Clear the slave read buffer and status */
       I2CS_I2CSlaveClearReadBuf();
      (void) I2CS_I2CSlaveClearReadStatus();
      i2cReadBuffer[0] = 0xFF;
}
else if((flag3==1) && (!(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID))))
{
       flag3=0; /* Setting Left Button Flag */
       i2cReadBuffer[0] = 0xFF;
}


/* Checking Right Button active or not */
if((flag1==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID)))
{
        flag1=1; /* Reseting the flag*/
         i2cReadBuffer[0] = 0x06;
         while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
        /* Clear the slave read buffer and status */
        I2CS_I2CSlaveClearReadBuf();
        ( void) I2CS_I2CSlaveClearReadStatus();
         i2cReadBuffer[0] = 0xFF;
}
else if((flag1==1)&& (!(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID))))
{

          flag1=0; 

}
}

}

}

void Received_Data_From_Master1()
{
switch(i2cWriteBuffer[0])
{
  /* After Receiving 00 touch will be Ready to Work */
  case 0x00:
         i2cReadBuffer[0] = 0x19; /*According to New Document Wants to transmit new data acknowledgement */
         POWER_LED_Write(0);
          break;

}

}

Any Help will be highly appreciated .

Thanks & Regards,

AsDh

 

 

 

 

 

0 Likes
1 Solution
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @AsDh_4015406 

 

The issue is caused mostly due to the delay at the beginning of the loop. I modified the code to the following:

 

#include <project.h>

/* Macro Declaration */
#define BUFFER_SIZE (1u)
#define PACKET_SIZE (BUFFER_SIZE)

/* The I2C Slave read and write buffers */
uint8 i2cReadBuffer [BUFFER_SIZE] = {0};
uint8 i2cWriteBuffer[BUFFER_SIZE]= {0};

uint8_t flag1=0;

uint8_t flag3=0;

void Received_Data_From_Master1();

int main()
{

	/* Eneble Global Interrupt */

	CyGlobalIntEnable;

	CapSense_Start();
	CapSense_ScanAllWidgets();

	/* Start the I2C Slave And I2C Address Setting*/
	I2CS_I2CSlaveInitReadBuf(i2cReadBuffer, BUFFER_SIZE);
	I2CS_I2CSlaveInitWriteBuf(i2cWriteBuffer, BUFFER_SIZE);

	I2CS_I2CSlaveSetAddress(0x08);
	I2CS_Start();

	for (;;)
	{
        
		//CyDelay(2);
		/* With Respect to Master i.e Checked Whether the Master Write Complted Or Not */
		if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_WR_CMPLT))
		{
			/* Calling Function to Collect The Data From Master */
			Received_Data_From_Master1();
			/* Enable this above function when we used the data On Switch Function */

			/* Clear the slave write buffer and status */
			I2CS_I2CSlaveClearWriteBuf();
			(void) I2CS_I2CSlaveClearWriteStatus();
		}
        if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_RD_CMPLT))
        {
            /* Clear the slave read buffer and status */
            I2CS_I2CSlaveClearReadBuf();
            (void) I2CS_I2CSlaveClearReadStatus();
        }
		if(CapSense_NOT_BUSY == CapSense_IsBusy())
		{
			/* API For Capsense Update Scanning And Process */
			CapSense_ProcessAllWidgets();           /* Process all widgets */
			CapSense_RunTuner();                            /* To sync with Tuner application */
			/* Checked whether Left Button Active or Not*/
			if((flag3==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID)) )
			{
                POWER_LED_Write(0);
				flag3=1;              /* Reseting Left Button Flag */
				i2cReadBuffer[0] = 0x01;
//				while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
//				/* Clear the slave read buffer and status */
//				I2CS_I2CSlaveClearReadBuf();
//				(void) I2CS_I2CSlaveClearReadStatus();
				//i2cReadBuffer[0] = 0xFF;
			}
			else if((flag3==1) && (!(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID))))
			{
				flag3=0; /* Setting Left Button Flag */
				i2cReadBuffer[0] = 0xFF;
			}


			/* Checking Right Button active or not */
			if((flag1==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID)))
			{
				flag1=1; /* Reseting the flag*/
				i2cReadBuffer[0] = 0x06;
//				while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
//				/* Clear the slave read buffer and status */
//				I2CS_I2CSlaveClearReadBuf();
//				( void) I2CS_I2CSlaveClearReadStatus();
				i2cReadBuffer[0] = 0xFF;
			}
			else if((flag1==1)&& (!(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID))))
			{

				flag1=0; 

			}
            CapSense_ScanAllWidgets();
		}

	}

}

void Received_Data_From_Master1()
{
	switch(i2cWriteBuffer[0])
	{
	/* After Receiving 00 touch will be Ready to Work */
	case 0x00:
		i2cReadBuffer[0] = 0x19; /*According to New Document Wants to transmit new data acknowledgement */
		POWER_LED_Write(0);
		break;

	}

}

/* [] END OF FILE */

 

The major difference is the I2C receiver code at the beginning of the loop to clear after a transaction and the CapSense_ScanAllWidgets() API at the end of the CapSense_IsBusy() condition.

I tried this out with Bridge control panel (Which is installed along with PSoC Creator) as the host and there was no NACK by the slave. Please try this out and let me know if this works.

 

Best regards, 

Hari

View solution in original post

0 Likes
4 Replies
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @AsDh_4015406 

 

The issue is caused mostly due to the delay at the beginning of the loop. I modified the code to the following:

 

#include <project.h>

/* Macro Declaration */
#define BUFFER_SIZE (1u)
#define PACKET_SIZE (BUFFER_SIZE)

/* The I2C Slave read and write buffers */
uint8 i2cReadBuffer [BUFFER_SIZE] = {0};
uint8 i2cWriteBuffer[BUFFER_SIZE]= {0};

uint8_t flag1=0;

uint8_t flag3=0;

void Received_Data_From_Master1();

int main()
{

	/* Eneble Global Interrupt */

	CyGlobalIntEnable;

	CapSense_Start();
	CapSense_ScanAllWidgets();

	/* Start the I2C Slave And I2C Address Setting*/
	I2CS_I2CSlaveInitReadBuf(i2cReadBuffer, BUFFER_SIZE);
	I2CS_I2CSlaveInitWriteBuf(i2cWriteBuffer, BUFFER_SIZE);

	I2CS_I2CSlaveSetAddress(0x08);
	I2CS_Start();

	for (;;)
	{
        
		//CyDelay(2);
		/* With Respect to Master i.e Checked Whether the Master Write Complted Or Not */
		if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_WR_CMPLT))
		{
			/* Calling Function to Collect The Data From Master */
			Received_Data_From_Master1();
			/* Enable this above function when we used the data On Switch Function */

			/* Clear the slave write buffer and status */
			I2CS_I2CSlaveClearWriteBuf();
			(void) I2CS_I2CSlaveClearWriteStatus();
		}
        if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_RD_CMPLT))
        {
            /* Clear the slave read buffer and status */
            I2CS_I2CSlaveClearReadBuf();
            (void) I2CS_I2CSlaveClearReadStatus();
        }
		if(CapSense_NOT_BUSY == CapSense_IsBusy())
		{
			/* API For Capsense Update Scanning And Process */
			CapSense_ProcessAllWidgets();           /* Process all widgets */
			CapSense_RunTuner();                            /* To sync with Tuner application */
			/* Checked whether Left Button Active or Not*/
			if((flag3==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID)) )
			{
                POWER_LED_Write(0);
				flag3=1;              /* Reseting Left Button Flag */
				i2cReadBuffer[0] = 0x01;
//				while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
//				/* Clear the slave read buffer and status */
//				I2CS_I2CSlaveClearReadBuf();
//				(void) I2CS_I2CSlaveClearReadStatus();
				//i2cReadBuffer[0] = 0xFF;
			}
			else if((flag3==1) && (!(CapSense_IsWidgetActive(CapSense_BUTTON2_WDGT_ID))))
			{
				flag3=0; /* Setting Left Button Flag */
				i2cReadBuffer[0] = 0xFF;
			}


			/* Checking Right Button active or not */
			if((flag1==0)&&(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID)))
			{
				flag1=1; /* Reseting the flag*/
				i2cReadBuffer[0] = 0x06;
//				while (I2CS_I2C_SSTAT_RD_CMPLT!=(I2CS_I2CSlaveStatus()));
//				/* Clear the slave read buffer and status */
//				I2CS_I2CSlaveClearReadBuf();
//				( void) I2CS_I2CSlaveClearReadStatus();
				i2cReadBuffer[0] = 0xFF;
			}
			else if((flag1==1)&& (!(CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID))))
			{

				flag1=0; 

			}
            CapSense_ScanAllWidgets();
		}

	}

}

void Received_Data_From_Master1()
{
	switch(i2cWriteBuffer[0])
	{
	/* After Receiving 00 touch will be Ready to Work */
	case 0x00:
		i2cReadBuffer[0] = 0x19; /*According to New Document Wants to transmit new data acknowledgement */
		POWER_LED_Write(0);
		break;

	}

}

/* [] END OF FILE */

 

The major difference is the I2C receiver code at the beginning of the loop to clear after a transaction and the CapSense_ScanAllWidgets() API at the end of the CapSense_IsBusy() condition.

I tried this out with Bridge control panel (Which is installed along with PSoC Creator) as the host and there was no NACK by the slave. Please try this out and let me know if this works.

 

Best regards, 

Hari

0 Likes
AsDh_4015406
Level 1
Level 1
10 sign-ins 5 replies posted 5 questions asked

Hi Hari,

Master(PIC) polling time is every 100ms .

when button not pressed, I need to sent 0xFF and button pressed then sent particular button data like 0x01,0x06 etc.

I have run  one timer  in Cy8C4025AZI-S412 of 100ms for sending data 0xFF when button not pressed .

but sometimes data got missing...

Any Solution to achieved the proper communication.

Thanks & Regards,

AsDh 

 

0 Likes
AsDh_4015406
Level 1
Level 1
10 sign-ins 5 replies posted 5 questions asked

Hi Hari,

In Above scenario, I found the NAK Signal During the write frame.

I have attached the logic analyzer observation result for the same.

Master Device:- PIC Controller 

Slave Device :- Cy8C4025AZI-S413 

My Slave Address is 0x08 

Ideally After Address byte their should be ACK From Slave but  I observed NAK Signal.

I am not getting where is the exact mistake?

Any help will be highly appreciated.

Regards,

AsDh

Screenshot (17).pngScreenshot (19).png

   

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @AsDh_4015406 

 

Can you try sending the master's command using Bridge control panel? This program is automatically installed with PSoC creator and emulates an I2C master. You can use any USB to I2C bridge and send the commands. 

 

Best regards, 
Hari

0 Likes