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.

Compiler/TMS320F28379D: TMS320F28379D I2C in Slave Send and receive mode

Part Number: TMS320F28379D
Other Parts Discussed in Thread: ENERGIA

Tool/software: TI C/C++ Compiler

Hi,

I want my TMS320F28379D  to act as a Slave Receive/Sender. I have modified the external loopback example to get this done. 

My receiver is working properly But When I am transmitting, The master is receiving the data in wrong sequence.

I am sending numbers from 0 to 9 but My master is receiving different data every time as follows.

6789456789
4567894567
8945678945
6789456789
4567894567

Please find my code below. And let me know what's

#include "driverlib.h"
#include "device.h"


//
// Defines
//
#define SLAVE_ADDRESS 0x3C

volatile uint16_t rData[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Receive data buffer
volatile uint16_t aData[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Receive data buffer
//
unsigned int a0 = 0;
unsigned int a1 = 1;
unsigned int a2 = 2;
unsigned int a3 = 3;
unsigned int a4 = 4;
unsigned int a5 = 5;
unsigned int a6 = 6;
unsigned int a7 = 7;
unsigned int a8 = 8;
unsigned int a9 = 9;

void initI2CFIFO(void);
__interrupt void i2cFIFOISR(void);

//
// Main
//
void main(void)
{

//
// Initialize device clock and peripherals
//
Device_init();

//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();

//
// // Initialize GPIOs 104 and 105 for use as SDA A and SCL A respectively
// //
// GPIO_setPinConfig(GPIO_104_SDAA);
// GPIO_setPadConfig(104, GPIO_PIN_TYPE_PULLUP);
// GPIO_setQualificationMode(104, GPIO_QUAL_ASYNC);
//
// GPIO_setPinConfig(GPIO_105_SCLA);
// GPIO_setPadConfig(105, GPIO_PIN_TYPE_PULLUP);
// GPIO_setQualificationMode(105, GPIO_QUAL_ASYNC);

//
// Initialize GPIOs 40 and 41 for use as SDA B and SCL B respectively
//
GPIO_setPinConfig(GPIO_40_SDAB);
GPIO_setPadConfig(40, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);

GPIO_setPinConfig(GPIO_41_SCLB);
GPIO_setPadConfig(41, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(41, GPIO_QUAL_ASYNC);

GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);

//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();

//
// Interrupts that are used in this example are re-mapped to ISR functions
// found within this file.
//
// Interrupt_register(INT_I2CA_FIFO, &i2cFIFOISR);
Interrupt_register(INT_I2CB_FIFO, &i2cFIFOISR);
//
// Set I2C use, initializing it for FIFO mode
//
initI2CFIFO();

//
// Initialize the data buffers
//
// for (i = 0; i < 2; i++)
// {
// sData[i] = i;
// rData[i] = 0;
// }

//
// Enable interrupts required for this example
//
// Interrupt_enable(INT_I2CA_FIFO);
Interrupt_enable(INT_I2CB_FIFO);

//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;

//
// Loop forever. Suspend or place breakpoints to observe the buffers.
//
while (1)
{
// A FIFO interrupt will be generated for each Tx and Rx based
// on the Interrupt levels configured.
// The ISR will handle pushing/pulling data to/from the TX and
// RX FIFOs resp.
if (rData[0] == 0 && rData[1] == 1 && rData[2] == 2 && rData[3] == 3
&& rData[4] == 4 && rData[5] == 5 && rData[6] == 6
&& rData[7] == 7 && rData[8] == 8 && rData[9] == 9)
{
GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);

}

else
{
GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);
}

// for (i = 0; i < 10; i++)
// {
// if (rData[i] == aData[i])
// {
// GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);
// }
//
// else
// {
// GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);
//
// }
//
// }
}
}

//
// Function to configure I2C A in FIFO mode.
//
void initI2CFIFO()
{
//
// Must put I2C into reset before configuring it
//
//I2C_disableModule(I2CB_BASE);
I2C_disableModule(I2CB_BASE);

//
// I2C configuration. Use a 400kHz I2CCLK with a 50% duty cycle.
// //
// I2C_initMaster(I2CB_BASE, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_50);
// I2C_setConfig(I2CB_BASE, I2C_MASTER_SEND_MODE);
//
// I2C_setDataCount(I2CB_BASE, 2);
// I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);

//
// I2C slave configuration
//
I2C_setConfig(I2CB_BASE, I2C_SLAVE_RECEIVE_MODE | I2C_SLAVE_SEND_MODE);

I2C_setDataCount(I2CB_BASE, 10);
I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);

//
// Configure for external loopback
//
// I2C_setSlaveAddress(I2CB_BASE, SLAVE_ADDRESS);
I2C_setOwnSlaveAddress(I2CB_BASE, SLAVE_ADDRESS);
//I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);

//
// FIFO and interrupt configuration
//
// I2C_enableFIFO(I2CB_BASE);
// I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_TXFF);

//
// Transmit FIFO interrupt levels are set to generate an interrupt
// when the 16 byte TX fifo contains 2 or lesser bytes of data.
//
// I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TX2, I2C_FIFO_RX2);
// I2C_enableInterrupt(I2CB_BASE, I2C_INT_TXFF | I2C_INT_STOP_CONDITION);

I2C_enableFIFO(I2CB_BASE);
I2C_clearInterruptStatus(
I2CB_BASE, I2C_INT_RXFF | I2C_INT_TXFF | I2C_INT_STOP_CONDITION);

//
// Receive FIFO interrupt levels are set to generate an interrupt
// when the 16 byte RX fifo contains 2 or greater bytes of data.
//
I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TX10, I2C_FIFO_RX10);
I2C_enableInterrupt(I2CB_BASE,
I2C_INT_RXFF | I2C_INT_TXFF | I2C_INT_STOP_CONDITION);

//
// Configuration complete. Enable the module.
//
//I2C_enableModule(I2CB_BASE);
I2C_enableModule(I2CB_BASE);
}

//
// I2C TX and Receive FIFO ISR
//
__interrupt
void i2cFIFOISR(void)
{
uint16_t i;

//
// If receive FIFO interrupt flag is set, read data
//
if ((I2C_getInterruptStatus(I2CB_BASE) & I2C_INT_RXFF) != 0)
{
for (i = 0; i < 10; i++)
{
rData[i] = I2C_getData(I2CB_BASE);
}

//
// Check received data
//

//
// Used to keep track of the last position in the receive
// stream for error checking
//

//
// Turn On an LED to depict data transfer
//

//
// Clear interrupt flag
//
I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_RXFF);

}
//
// If transmit FIFO interrupt flag is set, put data in the buffer
//
else if ((I2C_getInterruptStatus(I2CB_BASE) & I2C_INT_TXFF) != 0)
{
I2C_putData(I2CB_BASE, a0);
I2C_putData(I2CB_BASE, a1);
I2C_putData(I2CB_BASE, a2);
I2C_putData(I2CB_BASE, a3);
I2C_putData(I2CB_BASE, a4);
I2C_putData(I2CB_BASE, a5);
I2C_putData(I2CB_BASE, a6);
I2C_putData(I2CB_BASE, a7);
I2C_putData(I2CB_BASE, a8);
I2C_putData(I2CB_BASE, a9);

//
// Send the start condition
//
I2C_sendStartCondition(I2CB_BASE);

//
// Increment data for next cycle
//

//
// Clear interrupt flag
//
I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_TXFF);

//
// Turn Off an LED to depict data transfer
//

}

//
// Issue ACK
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
}

//
// End of File
//

wrong.

Regards

Vishal

  • For future reference, please use the syntax highlighter tool when you post code (it's the </> button in the text box tool bar). Should make it much easier for me to follow your code.

    There seems to be some misunderstanding about the role of a slave device in I2C. For example, slave devices do not send start and stop conditions or drive the clock. You don't need to set the data count either since the slave device as no control over that either. It's all determined by the master device.

    Not knowing anything about your master device, it's hard for me to guess what exactly is happening. Do you have a logic analyzer or oscilloscope or something you can use to view the transmissions to see what is being sent?

    Whitney

  • Hi Whitney,

    I am new to programming. And don't have much idea about it. Where Can I find the example for slave read/write for F28379D as All 3 examples provided are master read/write with internal loopback. Or Can you tell me what to modify in my code to make it work? On the master side, I am having an MSP432, that I am running on Energia.

    Regards

    Vishal

  • The external loopback example that you mentioned before is the only one that demonstrates I2C slave operation. Unfortunately, I think it only demonstrates slave-receiver and not slave-transmitter.

    I don't think your extra configurations are causing any problems though--since you're running in slave mode, they'll likely just be ignored.

    I do think there's an issue with how you're writing the data though. The FIFO interrupt is generated when TXFFST is equal to or less than TXFFIL (10 in your case), but your code is written assuming that there are at least 10 open bytes in the FIFO which isn't necessarily the case. I think your TXFFIL should be set to tell you when there are 10 bytes available--in other words interrupt when there are 6 or fewer words in the 16-word FIFO.

    Whitney

  • Hi Whitney,

    Thanks you for your response. I Set the TX FIFO interrupt level to 6. Now my transmitter is working fine. But If I make my RX FIFO interrupt level to 6, My receiver is receiving data in incorrect sequence. So I kept TX FIFO to 6 and RX FIFO to 10. Both are working fine.

    Here is the working code.

    #include "driverlib.h"
    #include "device.h"
    #include "global_variables.h"
    
    //
    // Defines
    //
    #define SLAVE_ADDRESS   0x3C
    
    volatile uint16_t rData[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Receive data buffer
    volatile uint16_t aData[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Receive data buffer
    //
    unsigned int a0 = 0;
    unsigned int a1 = 1;
    unsigned int a2 = 2;
    unsigned int a3 = 3;
    unsigned int a4 = 4;
    unsigned int a5 = 5;
    unsigned int a6 = 6;
    unsigned int a7 = 7;
    unsigned int a8 = 8;
    unsigned int a9 = 9;
    unsigned int i = 0;
    
    void initI2CFIFO(void);
    __interrupt void i2cFIFOISR(void);
    
    //
    // Main
    //
    void main(void)
    {
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
    //    // Initialize GPIOs 104 and 105 for use as SDA A and SCL A respectively
    //    //
    //    GPIO_setPinConfig(GPIO_104_SDAA);
    //    GPIO_setPadConfig(104, GPIO_PIN_TYPE_PULLUP);
    //    GPIO_setQualificationMode(104, GPIO_QUAL_ASYNC);
    //
    //    GPIO_setPinConfig(GPIO_105_SCLA);
    //    GPIO_setPadConfig(105, GPIO_PIN_TYPE_PULLUP);
    //    GPIO_setQualificationMode(105, GPIO_QUAL_ASYNC);
    
        //
        // Initialize GPIOs 40 and 41 for use as SDA B and SCL B respectively
        //
        GPIO_setPinConfig(GPIO_40_SDAB);
        GPIO_setPadConfig(40, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);
    
        GPIO_setPinConfig(GPIO_41_SCLB);
        GPIO_setPadConfig(41, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(41, GPIO_QUAL_ASYNC);
    
        GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
    
        GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT);
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        //  Interrupt_register(INT_I2CA_FIFO, &i2cFIFOISR);
        Interrupt_register(INT_I2CB_FIFO, &i2cFIFOISR);
        //
        // Set I2C use, initializing it for FIFO mode
        //
        initI2CFIFO();
    
        //
        // Initialize the data buffers
        //
    //    for (i = 0; i < 2; i++)
    //    {
    //        sData[i] = i;
    //        rData[i] = 0;
    //    }
    
        //
        // Enable interrupts required for this example
        //
        //  Interrupt_enable(INT_I2CA_FIFO);
        Interrupt_enable(INT_I2CB_FIFO);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Loop forever. Suspend or place breakpoints to observe the buffers.
        //
        while (1)
        {
            // A FIFO interrupt will be generated for each Tx and Rx based
            // on the Interrupt levels configured.
            // The ISR will handle pushing/pulling data to/from the TX and
            // RX FIFOs resp.
            if (rData[0] == 0 && rData[1] == 1 && rData[2] == 2 && rData[3] == 3
                    && rData[4] == 4 && rData[5] == 5 && rData[6] == 6
                    && rData[7] == 7 && rData[8] == 8 && rData[9] == 9)
            {
                GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);
                GPIO_writePin(DEVICE_GPIO_PIN_LED2, 1);
    
    
            }
    
            else
            {
                GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);
                GPIO_writePin(DEVICE_GPIO_PIN_LED2, 0);
            }
            for (i = 0; i < 10; i++)
            {
                rData[i] = 0;
            }
            DEVICE_DELAY_US(1000000);
    
        }
    }
    
    //
    // Function to configure I2C A in FIFO mode.
    //
    void initI2CFIFO()
    {
    //
    // Must put I2C into reset before configuring it
    //
    //I2C_disableModule(I2CB_BASE);
        I2C_disableModule(I2CB_BASE);
    
    //
    // I2C configuration. Use a 400kHz I2CCLK with a 50% duty cycle.
    //    //
    //    I2C_initMaster(I2CB_BASE, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_50);
    //    I2C_setConfig(I2CB_BASE, I2C_MASTER_SEND_MODE);
    //
    //    I2C_setDataCount(I2CB_BASE, 2);
    //    I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);
    
    //
    // I2C slave configuration
    //
        I2C_setConfig(I2CB_BASE, I2C_SLAVE_RECEIVE_MODE | I2C_SLAVE_SEND_MODE);
    
        I2C_setDataCount(I2CB_BASE, 10);
        I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);
    
    //
    // Configure for external loopback
    //
    // I2C_setSlaveAddress(I2CB_BASE, SLAVE_ADDRESS);
        I2C_setOwnSlaveAddress(I2CB_BASE, SLAVE_ADDRESS);
    //I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
        I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
    
    //
    // FIFO and interrupt configuration
    //
    // I2C_enableFIFO(I2CB_BASE);
    // I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_TXFF);
    
    //
    // Transmit FIFO interrupt levels are set to generate an interrupt
    // when the 16 byte TX fifo contains 2 or lesser bytes of data.
    //
    //    I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TX2, I2C_FIFO_RX2);
    //    I2C_enableInterrupt(I2CB_BASE, I2C_INT_TXFF | I2C_INT_STOP_CONDITION);
    
        I2C_enableFIFO(I2CB_BASE);
        I2C_clearInterruptStatus(
                I2CB_BASE, I2C_INT_RXFF | I2C_INT_TXFF | I2C_INT_STOP_CONDITION);
    
    //
    // Receive FIFO interrupt levels are set to generate an interrupt
    // when the 16 byte RX fifo contains 2 or greater bytes of data.
    //
        I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TX6, I2C_FIFO_RX10);
        I2C_enableInterrupt(I2CB_BASE,
        I2C_INT_RXFF | I2C_INT_TXFF | I2C_INT_STOP_CONDITION);
    
    //
    // Configuration complete. Enable the module.
    //
    //I2C_enableModule(I2CB_BASE);
        I2C_enableModule(I2CB_BASE);
    }
    
    //
    // I2C TX and Receive FIFO ISR
    //
    __interrupt
    void i2cFIFOISR(void)
    {
        uint16_t i;
    
    //
    // If receive FIFO interrupt flag is set, read data
    //
        if ((I2C_getInterruptStatus(I2CB_BASE) & I2C_INT_RXFF) != 0)
        {
            for (i = 0; i < 10; i++)
            {
                rData[i] = I2C_getData(I2CB_BASE);
            }
    
    //
    // Check received data
    //
    
    //
    // Used to keep track of the last position in the receive
    // stream for error checking
    //
    
    //
    // Turn On an LED to depict data transfer
    //
    
    //
    // Clear interrupt flag
    //
            I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_RXFF);
    
        }
    //
    // If transmit FIFO interrupt flag is set, put data in the buffer
    //
        else if ((I2C_getInterruptStatus(I2CB_BASE) & I2C_INT_TXFF) != 0)
        {
            I2C_putData(I2CB_BASE, a0);
            I2C_putData(I2CB_BASE, a1);
            I2C_putData(I2CB_BASE, a2);
            I2C_putData(I2CB_BASE, a3);
            I2C_putData(I2CB_BASE, a4);
            I2C_putData(I2CB_BASE, a5);
            I2C_putData(I2CB_BASE, a6);
            I2C_putData(I2CB_BASE, a7);
            I2C_putData(I2CB_BASE, a8);
            I2C_putData(I2CB_BASE, a9);
    
            //
            // Send the start condition
            //
            I2C_sendStartCondition(I2CB_BASE);
    
            //
            // Increment data for next cycle
            //
    
            //
            // Clear interrupt flag
            //
            I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_TXFF);
    
            //
            // Turn Off an LED to depict data transfer
            //
    
        }
    
        //
        // Issue ACK
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    //
    // End of File
    //
    
    

    Regards

    Vishal Kakade