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.

CCS/TMS320F28379D: C2000™ microcontrollers forum

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Hi. I am trying to communicate with magnetometer through I2C. I learned how to initialize I2C peripheral and some I2C standard functions used in example i2c_ex2_eeprom.c and i2c_ex1_loopback.c. Now I try to make my own I2C functions based on those examples to build up my sensor library. As I saw in example, to read and write to I2C, we follow this procedure (assumed all initializations have been done):

To write to I2C:

- set slave address

- set register address to be written

- put data ready to be sent 

- send start condition

- send stop condition

To read I2C

- set slave address

- set register address to be read

- send start condition

- wait for I2C_INTSRC_REG_ACCESS_RDY to be triggered and then, send stop condition inside ISR

- set number of bytes to be read

- read data using I2C_getData()

I follow this procedure and make some function as shown below. But I have some problem with read function ( write function seemed to be ok)

- I2C_INTSRC_REG_ACCESS_RDY was not triggered so stop condition could not be sent to end the setting up address process

- the program stuck in while(I2C_getStopConditionStatus(base)!=0). But it stuck in the second statement not the first one which I found weird since stop condition cant be sent inside ISR

Please give me some advice. Thanks in advance

void initI2C(uint32_t base)
{
    I2C_disableModule(base);
    // I2C configuration. Use a 400KHz I2C clock with a 33% duty cycle
    I2C_initMaster(base, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_33);
    I2C_setBitCount(base, I2C_BITCOUNT_8);
   // I2C_setSlaveAddress(base, slaveAddr);
    I2C_setEmulationMode(base,I2C_EMULATION_FREE_RUN);
    // enable stop condition and register-access-ready interrupts

    I2C_enableInterrupt(base,I2C_INT_STOP_CONDITION |
                        I2C_INT_REG_ACCESS_RDY);
    // FIFO configuration

    I2C_enableFIFO(base);
    I2C_clearInterruptStatus(base,I2C_INT_RXFF | I2C_INT_TXFF);
    I2C_enableModule(base);
}
int16_t i2cRead(uint32_t base, uint16_t slaveAddr,uint16_t regAddr,uint16_t *data,uint16_t data_length)
{
	uint16_t count;
	if(I2C_getStopConditionStatus(base))
	{
		return ERROR_STOP_NOT_READY;
	}

    I2C_setSlaveAddress(base, slaveAddr);
    I2C_setDataCount(base, 1);
    I2C_putData(base, regAddr);
    I2C_setConfig(base, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
 //   I2C_sendStopCondition(base);
    while(I2C_getStopConditionStatus(base)!=0);
    I2C_setDataCount(base,data_length);
    I2C_setConfig(base,I2C_MASTER_RECEIVE_MODE);
    I2C_sendStartCondition(base);
    I2C_sendStopCondition(base);
	while(I2C_getStopConditionStatus(base)!=0);   // this is where the program stuck
//	    while(data_ready_flag==0);
	    for(count=0;count<data_length;count++)
	    {
		//while(I2C_getRxFIFOStatus(base)==I2C_FIFO_RXEMPTY);
	        *(data+count) = I2C_getData(base);
	    }
	return SUCCESS;
}
int16_t i2cWrite(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t data)
{
	if(I2C_getStopConditionStatus(base))
	{
		return ERROR_STOP_NOT_READY;
	}
	I2C_setSlaveAddress(base, slaveAddr);
	if(I2C_isBusBusy(I2CB_BASE))
	    {
	        return(ERROR_BUS_BUSY);
	    }
	I2C_setDataCount(base,2);
	I2C_putData(base,regAddr);
	I2C_putData(base, data);
	I2C_setConfig(base,I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
    I2C_sendStopCondition(base);
    return SUCCESS;
}
int16_t i2cWriteMulti(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t *data,uint16_t data_length)
{
	uint16_t i;
	if(I2C_getStopConditionStatus(base))
	{
		return ERROR_STOP_NOT_READY;
	}
	I2C_setSlaveAddress(base, slaveAddr);
	if(I2C_isBusBusy(I2CB_BASE))
	    {
	        return(ERROR_BUS_BUSY);
	    }
	I2C_setDataCount(base,data_length+1);
	I2C_putData(base,regAddr);
	for(i=0; i<data_length;i++)
	{
		I2C_putData(base, *(data+i));
	}
    I2C_setConfig(base,I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
    I2C_sendStopCondition(base);
    return SUCCESS;

}
__interrupt void i2cISR()
{
    count++;
	intSource = I2C_getInterruptSource(I2CB_BASE);
	switch(intSource)
	{
	case I2C_INTSRC_STOP_CONDITION:
	{
	 
	}
	break;
	case I2C_INTSRC_REG_ACCESS_RDY:
	{
	    if((I2C_getStatus(I2CB_BASE)&I2C_STS_NO_ACK)!=0)
        {
            I2C_sendStopCondition(I2CB_BASE);
            I2C_clearStatus(I2CB_BASE, I2C_STS_NO_ACK);
        }
	}
	break;
	}
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);

}

  • Is there any reference that refer to driverlib
  • The application report uses 2 F2808 processors, one as master and one as slave. I would take a look at the code for the master and see if there are any differences between what is done there and what you are doing.

    It does look like they were able to communicate between the two F2808 devices, one as master and one as a slave device.

    When I did a search, this is the document that showed up - I am not sure if there is any more recent document that would cover driverlib.
  • I don't think it's typical to send a stop condition after sending the address for a read. The stop condition in the ISR is only meant for NACK handling--if a the stop condition is set at that point it means something went wrong and you need to retry.

    Since this is the case, doing a while(I2C_getStopConditionStatus(base)!=0); probably won't actually cause the application to spin there at all. It may move on to setting up for the read before the address has been fully sent. Try waiting for I2C_INT_REG_ACCESS_RDY at that point instead.

    Whitney
  • Thanks for your reply. I realized that I misunderstood the purpose of I2C_INT_REG_ACCESS_RDY the whole time. Now I removed the while condition and add a delay instead to see what happen but when i debug, the program did not even jump into I2C_INT_REG_ACCESS_RDY( I set a flag in Isr
    to verify that). Seems that it failed to send address for a read. Is there any explanation for this.
  • Do you have an oscilloscope or logic analyzer or something you could use to look at the activity on the I2C signals to see what it's managing to send?

    Whitney
  • This is what I get when analyze I2C read function. I dont have much experience using logic analyzer. Is there any problem with SDA signal ?

  • Updated:
    Now the program successfully jumped into I2C_INTSRC_REG_ACCESS_RDY, but sometimes it still stuck at the while(I2C_getStopConditionStatus(base)!=0) (the second one). sometimes it passed through but I could not get any data to the data buffer. Is it really necessary to get data inside I2C_INTSRC_STOP_CONDITION ISR as the example did ?
  • Another thing is that in each read function, the program jump into ISR 4 times. 2 times for I2C_INTSRC_STOP_CONDITION and 2 times for I2C_INTSRC_REG_ACCESS_RDY. Is it reasonable ?
  • Hi Minh,

    Your signals look fine, but you're SDA and SCL channels are reversed on your Saleae software. Also I suggest making the display setting "Hex" by clicking the cog wheel next to I2C on the right side of the pane. That will make it a lot easier to understand.

    Best,
    Kevin

  • At last, I figured out the way to get this done. I follow the same pattern as in the example which is to seperate reading process to 2 phase: set up phase and read data phase. Not like in the example they used many message_status, I simplified it by turning on and off a flag in ISR to switch between 2 phase(the flag must be volatile by the way). Here is the code for those who had the same problem

    /*
     * MyI2C.c
     *
     *  Created on: Dec 26, 2018
     *      Author: Quang Minh Bui
     */
    #include "MyI2C.h"
    
    
    #define MAX_BUF_SIZE 6
    
    //int setup_phase = 0;
    //uint16_t count = 0;
    //int check = 0;
    
    volatile int data_ready_flag = 0;
    volatile int data_count;
    volatile uint16_t reg_ready;
    volatile I2C_InterruptSource intSource;
    
    // buffer to store data read
    uint16_t data_temp;
    uint16_t buffer[MAX_BUF_SIZE];
    
    
    
    void initI2C(uint32_t base)
    {
        I2C_disableModule(base);
        I2C_disableLoopback(base);
        // I2C configuration. Use a 400KHz I2C clock with a 33% duty cycle
        I2C_initMaster(base, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_33);
        I2C_setBitCount(base, I2C_BITCOUNT_8);
       // I2C_setSlaveAddress(base, slaveAddr);
        I2C_setEmulationMode(base,I2C_EMULATION_FREE_RUN);
        // enable stop condition and register-access-ready interrupts
    
        I2C_enableInterrupt(base,I2C_INT_STOP_CONDITION |
                            I2C_INT_REG_ACCESS_RDY);
        // FIFO configuration
    
        I2C_enableFIFO(base);
        I2C_clearInterruptStatus(base,I2C_INT_RXFF | I2C_INT_TXFF);
        I2C_enableModule(base);
    }
    int16_t i2cRead(uint32_t base, uint16_t slaveAddr,uint16_t regAddr,uint16_t *data,uint16_t data_length)
    {
    //	uint16_t count;
    	if(I2C_getStopConditionStatus(base))
    	{
    		return ERROR_STOP_NOT_READY;
    	}
    	if(data_ready_flag==0)
    	{
        I2C_setSlaveAddress(base, slaveAddr);
        I2C_setDataCount(base, 1);
        I2C_putData(base, regAddr);
        I2C_setConfig(base, I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(base);
        reg_ready = 1;
    	}
    
        if(data_ready_flag==1)
        {
            I2C_setDataCount(base,data_length);
            I2C_setConfig(base,I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(base);
            I2C_sendStopCondition(base);
            while(data_ready_flag==1);
            for(data_count = 0; data_count<data_length; data_count++)
            {
                *(data+data_count) = I2C_getData(base);
            }
    
        }
    
    	return SUCCESS;
    }
    int16_t I2CRead(uint32_t base, uint16_t slaveAddr,uint16_t regAddr,uint16_t *data,uint16_t data_length)
    {
        while(i2cRead(base, slaveAddr,regAddr,data,data_length)!=SUCCESS);
        while(data_ready_flag!=1);
        i2cRead(base, slaveAddr,regAddr,data,data_length);
        return 1;
    }
    int16_t i2cWrite(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t data)
    {
    	if(I2C_getStopConditionStatus(base))
    	{
    		return ERROR_STOP_NOT_READY;
    	}
    	I2C_setSlaveAddress(base, slaveAddr);
    	if(I2C_isBusBusy(I2CB_BASE))
    	    {
    	        return(ERROR_BUS_BUSY);
    	    }
    	I2C_setDataCount(base,2);
    	I2C_putData(base,regAddr);
    	I2C_putData(base, data);
    	I2C_setConfig(base,I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(base);
        I2C_sendStopCondition(base);
        return SUCCESS;
    }
    int16_t i2cWriteMulti(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t *data,uint16_t data_length)
    {
    	uint16_t i;
    	if(I2C_getStopConditionStatus(base))
    	{
    		return ERROR_STOP_NOT_READY;
    	}
    	I2C_setSlaveAddress(base, slaveAddr);
    	if(I2C_isBusBusy(I2CB_BASE))
    	    {
    	        return(ERROR_BUS_BUSY);
    	    }
    	I2C_setDataCount(base,data_length+1);
    	I2C_putData(base,regAddr);
    	for(i=0; i<data_length;i++)
    	{
    		I2C_putData(base, *(data+i));
    	}
        I2C_setConfig(base,I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(base);
        I2C_sendStopCondition(base);
        return SUCCESS;
    }
    __interrupt void i2cISR()
    {
    //    count++;
    	intSource = I2C_getInterruptSource(I2CB_BASE);
    	switch(intSource)
    	{
    	case I2C_INTSRC_STOP_CONDITION:
    	{
    
    	    if(data_ready_flag == 1)
    	    {
    	        data_ready_flag = 0;
    	    }
    
    	}
    	break;
    	case I2C_INTSRC_REG_ACCESS_RDY:
    	{
    //	    count ++;
    	    if((I2C_getStatus(I2CB_BASE)&I2C_STS_NO_ACK)!=0)
            {
                I2C_sendStopCondition(I2CB_BASE);
                I2C_clearStatus(I2CB_BASE, I2C_STS_NO_ACK);
            }
    	    data_ready_flag = 1;
    
    	}
    	break;
    	}
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //
    //
    ///*
    // * MyI2C.c
    // *
    // *  Created on: Dec 26, 2018
    // *      Author: Quang Minh Bui
    // */
    //#include "MyI2C.h"
    //
    //
    //#define MAX_BUF_SIZE 6
    //
    //uint16_t msg_status;
    //#define MSG_STATUS_INACTIVE         0x0000 // Message not in use, do not send
    //#define MSG_STATUS_SEND_WITHSTOP    0x0010 // Send message with stop bit
    //#define MSG_STATUS_WRITE_BUSY       0x0011 // Message sent, wait for stop
    //#define MSG_STATUS_SEND_NOSTOP      0x0020 // Send message without stop bit
    //#define MSG_STATUS_SEND_NOSTOP_BUSY 0x0021 // Message sent, wait for ARDY
    //#define MSG_STATUS_RESTART          0x0022 // Ready to become master-receiver
    //#define MSG_STATUS_READ_BUSY        0x0023 // Wait for stop before reading data
    //int data_ready_flag = 0;
    //int setup_phase = 0;
    //uint16_t count = 0;
    //int check = 0;
    //int data_count;
    //I2C_InterruptSource intSource;
    //
    //// buffer to store data read
    //uint16_t data_temp;
    //uint16_t buffer[MAX_BUF_SIZE];
    //
    //
    //
    //void initI2C(uint32_t base)
    //{
    //    I2C_disableModule(base);
    //    I2C_disableLoopback(base);
    //    // I2C configuration. Use a 400KHz I2C clock with a 33% duty cycle
    //    I2C_initMaster(base, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_33);
    //    I2C_setBitCount(base, I2C_BITCOUNT_8);
    //   // I2C_setSlaveAddress(base, slaveAddr);
    //    I2C_setEmulationMode(base,I2C_EMULATION_FREE_RUN);
    //    // enable stop condition and register-access-ready interrupts
    //
    //    I2C_enableInterrupt(base,I2C_INT_STOP_CONDITION |
    //                        I2C_INT_REG_ACCESS_RDY);
    //    // FIFO configuration
    //
    //    I2C_enableFIFO(base);
    //    I2C_clearInterruptStatus(base,I2C_INT_RXFF | I2C_INT_TXFF);
    //    I2C_enableModule(base);
    //}
    //int16_t i2cRead(uint32_t base, uint16_t slaveAddr,uint16_t regAddr,uint16_t *data,uint16_t data_length)
    //{
    //    check = 0;
    ////  uint16_t count;
    //    msg_status = MSG_STATUS_SEND_NOSTOP;
    //    if(I2C_getStopConditionStatus(base))
    //    {
    //        return ERROR_STOP_NOT_READY;
    //    }
    //
    //    I2C_setSlaveAddress(base, slaveAddr);
    //    if(msg_status == MSG_STATUS_SEND_NOSTOP)
    //    {
    //        if(I2C_isBusBusy(base))
    //        {
    //            return(ERROR_BUS_BUSY);
    //        }
    //        I2C_setDataCount(base, 1);
    //        I2C_putData(base, regAddr);
    //        I2C_setConfig(base, I2C_MASTER_SEND_MODE);
    //        I2C_sendStartCondition(base);
    //        msg_status = MSG_STATUS_SEND_NOSTOP_BUSY;
    //    }
    //    while(msg_status!=MSG_STATUS_RESTART);
    //
    //    I2C_setDataCount(base,data_length);
    //    I2C_setConfig(base,I2C_MASTER_RECEIVE_MODE);
    //    I2C_sendStartCondition(base);
    //    I2C_sendStopCondition(base);
    //    msg_status = MSG_STATUS_READ_BUSY;
    //
    //
    // //   I2C_sendStopCondition(base);
    ////    while(I2C_getStopConditionStatus(base)!=0);
    ////    SysCtl_delay(100);
    //
    ////    while(I2C_getStopConditionStatus(base)!=0);
    //////    SysCtl_delay(100);
    ////
    //////      while(data_ready_flag==0);
    ////        for(data_count=0;data_count<data_length;data_count++)
    ////        {
    ////        while(I2C_getRxFIFOStatus(base)==I2C_FIFO_RXEMPTY);
    ////            *(data+data_count) = I2C_getData(base);
    ////            data_temp = *(data+data_count);
    ////        }
    //    return SUCCESS;
    //}
    //int16_t i2cWrite(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t data)
    //{
    //    msg_status = MSG_STATUS_SEND_WITHSTOP;
    //    if(I2C_getStopConditionStatus(base))
    //    {
    //        return ERROR_STOP_NOT_READY;
    //    }
    //    I2C_setSlaveAddress(base, slaveAddr);
    //    if(I2C_isBusBusy(I2CB_BASE))
    //        {
    //            return(ERROR_BUS_BUSY);
    //        }
    //    I2C_setDataCount(base,2);
    //    I2C_putData(base,regAddr);
    //    I2C_putData(base, data);
    //    I2C_setConfig(base,I2C_MASTER_SEND_MODE);
    //    I2C_sendStartCondition(base);
    //    I2C_sendStopCondition(base);
    //    msg_status = MSG_STATUS_WRITE_BUSY;
    //    return SUCCESS;
    //}
    //__interrupt void i2cISR()
    //{
    //    count++;
    //    intSource = I2C_getInterruptSource(I2CB_BASE);
    //    switch(intSource)
    //    {
    //    case I2C_INTSRC_STOP_CONDITION:
    //    {
    //        if(msg_status == MSG_STATUS_WRITE_BUSY)
    //            msg_status = MSG_STATUS_INACTIVE;
    //        else
    //        {
    //            if(msg_status == MSG_STATUS_SEND_NOSTOP_BUSY)
    //                msg_status = MSG_STATUS_SEND_NOSTOP;
    //            else if(msg_status == MSG_STATUS_READ_BUSY)
    //            {
    //                msg_status = MSG_STATUS_INACTIVE;
    //                for(data_count=0; data_count<1; data_count++)
    //                {
    //                    buffer[0] = I2C_getData(I2CB_BASE);
    //                }
    //            }
    //        }
    //
    //
    //
    //    }
    //    break;
    //    case I2C_INTSRC_REG_ACCESS_RDY:
    //    {
    //        if((I2C_getStatus(I2CB_BASE)&I2C_STS_NO_ACK)!=0)
    //        {
    //            I2C_sendStopCondition(I2CB_BASE);
    //            I2C_clearStatus(I2CB_BASE, I2C_STS_NO_ACK);
    //        }
    //        else if(msg_status==MSG_STATUS_SEND_NOSTOP_BUSY)
    //        {
    //            msg_status = MSG_STATUS_RESTART;
    //        }
    //        check = 1;
    //    }
    //    break;
    //    }
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    //}
    
    

  • Great! Thanks for sharing your solution.

    Whitney