This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

i2c as a slave mode i tm4c1294ncpdt

Other Parts Discussed in Thread: MSP430F5529, MSP430F5329, TM4C1294NCPDT

Hi All,

can any one works on i2c as a slave with multiple btye recieve ?? 

i get 1 byte at a time but 2nd byte don't get.

  • Hello Prateek,

    Please attach your code for Slave device? Also how are you controlling the master to request to transmit/ receive 2 bytes?
  • hi Amit,

    tm4c129 act as a slave for i2c and msp430f5529 and msp430f5329 worked as a master. 

    so i am sending 3 byte by master and slave will read the data and then process it. 

    i am attaching my slave code for tm4c1294ncpdt. my master code working fine and i am tested in my last project.

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include <math.h>
    #include "inc/tm4c129xnczad.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/udma.h"
    
    #define SLAVE_ADDRESS 0x3A
    
    unsigned char ui8I2CBuf[10];
    int i2c1status=0;
    int i2c2status=0;
    
    
    void I2C5_Init()
      {
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB0_I2C5SCL);
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_0);
      GPIOPinConfigure(GPIO_PB1_I2C5SDA);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_1);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C5);
      I2CSlaveEnable(I2C5_BASE);
      I2CSlaveIntEnableEx(I2C5_BASE, I2C_SLAVE_INT_DATA);
      I2CMasterInitExpClk(I2C5_BASE, SysCtlClockGet(), false);
      I2CSlaveInit(I2C5_BASE, SLAVE_ADDRESS);
      IntMasterEnable();
      }
    
      void I2C6_Init()
      {
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
      GPIOPinConfigure(GPIO_PA6_I2C6SCL);
      GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
      GPIOPinConfigure(GPIO_PA7_I2C6SDA);
      GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
      I2CSlaveEnable(I2C6_BASE);
      I2CSlaveIntEnableEx(I2C6_BASE, I2C_SLAVE_INT_DATA);
      I2CMasterInitExpClk(I2C6_BASE, SysCtlClockGet(), false);
      I2CSlaveInit(I2C6_BASE, SLAVE_ADDRESS);
      IntMasterEnable();
      }
      
      void I2C5Slave_IntHandler()
    {
    	I2CSlaveIntClear(I2C6_BASE);
    	i2c1status = 1;
    }
    
    void I2C6Slave_IntHandler()
    {
    	I2CSlaveIntClear(I2C7_BASE);
    	i2c2status = 1;
    }
    
    void call_12c(uint32_t Base,int adr)
    {
    	uint32_t state;
    	state = I2CSlaveStatus(Base);
    	switch(state)
    	{
    		case I2C_SLAVE_ACT_RREQ :
    		ui8I2CBuf[i] = I2CSlaveDataGet(base);
    		i++;
    		while(!adr);  // waiting for i2c stop bit
    		break;
    		case I2C_SLAVE_ACT_TREQ :
    		ui8I2CBuf[i] = I2CSlaveDataGet(base);
    		i++;
    		while(!adr);  // waiting for i2c stop bit
    		break;
    	}
    }
    
    int main()
    {
    	I2C6_Init();
    	I2C5_Init();
    	
    	while(1)
    	{
    		if(i2c1status==1)
    			call_12c(I2C5_BASE,i2c1status);
    		if(i2c2status==1)
    			call_12c(I2C6_BASE,i2c2status);
    	}
    }
      
      

    this is for generic which collect all data form both adc.

  • Hello Prateek,

    When the I2C_SLAVE_ACT_RREQ is set then the CPU reads from I2C Slave. When I2C_SLAVE_ACT_TREQ is set the I2C slave has to send the data out by using I2CSlaveDataPut and not read using I2CSlaveDataGet.
  • HI Amit,

    i know about that but, i need to register address for data trasfer. thats why i read when I2C_SLAVE_ACT_TREQ, and after that i trasfer data.
    when stop bit never occur, i2c read all data to read and save in buffer in incremented form and then put at that location.
  • Hello Prateek

    What!!!! If you need register address then it has to be in receive function, where the master sends the data. In Transmit request the Slave owns the SDA line. Please refer to the I2C Application Note to first understand I2C operations....

    www.ti.com/.../spma073.pdf
  • Hi Amit,

    if i2c act as slave for any other master, then why i use master command like this
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    while(I2CMasterBusy(I2C0_BASE));

    in i2c slave data flow is like this

    Start | Slave addr | Write | ACK | REG ADDR | ACK | Repetive Start | Slave addr | Read | ACK | D0 | ACK | D1 | ACK STOP
    thats why i use read function.
  • Hello Prateek,

    You understanding of slave data flow is correct. But the implementation of the code is incorrect. Please refer to the following active thread for a reference code that the customer made.

    e2e.ti.com/.../2033944
  • Hi Amit,

    Thanks for this,
  • HI all,

    can any one give me idea about how to get stop bit in I2C act as a slave bit.

    i can put my code here.

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include <math.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_types.h"
    #include "inc/tm4c129xnczad.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/i2c.h"
    #include "i2c_b.h"
    #include "memory.h"
    
    #define SLAVE_ADDRESS 0x3A
    static unsigned char g_ui8I2CGetBuf[5];
    static unsigned char g_ui8I2CPutBuf[5];
    
    int i2cput;
    int I2C0Alert;
    int I2C5Alert;
    int I2C6Alert;
    int I2C7Alert;
    
    // init
    
    void SysClk_Init()
    {
    	SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
    			SYSCTL_CFG_VCO_480), 120000000);
    }
    
      void I2C0_Init()
      {
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
      I2CSlaveEnable(I2C0_BASE);
      I2CSlaveIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_DATA);
      I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
      I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
      I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
      IntMasterEnable();
      }
      
        void I2C5_Init()
      {
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB0_I2C5SCL);
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_0);
      GPIOPinConfigure(GPIO_PB1_I2C5SDA);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_1);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C5);
      I2CSlaveEnable(I2C5_BASE);
      I2CSlaveIntEnableEx(I2C5_BASE, I2C_SLAVE_INT_DATA);
      I2CMasterInitExpClk(I2C5_BASE, SysCtlClockGet(), false);
      I2CSlaveInit(I2C5_BASE, SLAVE_ADDRESS);
      I2CMasterSlaveAddrSet(I2C5_BASE, SLAVE_ADDRESS, false);
      IntMasterEnable();
      }
      
      // vector table handler
      
      void I2C0_IntHandler()
    {
    	I2CSlaveIntClear(I2C0_BASE);
    	I2C0Alert = 1;
    }
    
    void I2C5_IntHandler()
    {
    	I2CSlaveIntClear(I2C5_BASE);
    	I2C5Alert = 1;
    }
      
      // collect data 
      void ATS_I2C_IntHandler(uint32_t Base,int AlertStatus)
    {
      uint32_t I2CState;
      unsigned char result;
      int i=0;
      AlertStatus = 0;
    
     I2CState = I2CSlaveStatus(Base);
    
    	switch(I2CState)
    	{
    	case I2C_SLAVE_ACT_NONE :
    
    		break;
    	case I2C_SLAVE_ACT_RREQ :
    		g_ui8I2CGetBuf[i] =(unsigned char) I2CSlaveDataGet(Base);
    		i++;
    		while(!AlertStatus);
    		break;
    	case I2C_SLAVE_ACT_TREQ :
    
            I2CSlaveDataPut(Base,g_ui8I2CPutBuf[i]);
            i++;
            while(!AlertStatus);
    		break;
    	}
    }
    
    
    int main(void)
    {	
        SysClk_Init();
    	I2C0_Init();
    	I2C5_Init();
    	
    	while(1)
    	{
    			if(I2C0Alert==1)
    		{
    		ATS_I2C_IntHandler(I2C0_BASE,I2C0Alert);
    		}
    		if(I2C5Alert==1)
    		{
    			ATS_I2C_IntHandler(I2C5_BASE,I2C5Alert);
    		}
    	}
    
    }

    i need to get stop bit after last data get for reading how much data can come across i2c. in this i2c worked as a slave.

    plz help me how to proceed next ??

  • Hello Prateek,

    Did you check the I2C interrupt status register which has the I2C STPRIS condition flag?
  • HI Amit,

    i check only i2c data interrupt by which i can get data, but i need to find stop bit for some data calculation.
    i post my code in previous comment. (4265.main.c) plz look at ones.
  • Hello Prateek,

    The function ATS_I2C_IntHandler is not an interrupt handler. It is a function being called by the main application loop.
  • HI Amit, yes ATS_I2C_intHandler is not an interrupt handler, its my function for multiple I2C working with there own priority.

    i just need to stop bit after data coming, for taking length of data.
  • Hello Prateek,

    Then you need to poll the I2CSRIS bit for Stop interrupt status in the ATS function.
  • HI amit,

    i can't understand this, can you describe it using any short example by which i can get details about it.
  • Hello Prateek,

    You need to call the API I2CSlaveIntStatusEx with the 2nd parameter set to false. Then the return value needs to be AND-ed with the define I2C_SLAVE_INT_STOP and checked to see if the resulting value is I2C_SLAVE_INT_STOP. If yes, then clear the interrupt status and consider a valid stop condition on the bus,