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.
Hello,
I am working on I2C Master Receiver and Slave Transmitter.
In Slave Transmitter Interrupt, Transmit Interrupt (I2C_TX_ISRC) enters before Address as Slave Interrupt (I2C_AAS_ISRC).
This causes index confusion.
I have attached the relevant files.
I would appreciate if you share an I2C Slave example for TMS320F28035.
Thanks,
Kadir B.
//########################################################################### // //! \addtogroup f2803x_example_list //! <h1>I2C EEPROM(i2c_eeprom)</h1> //! //! This program requires an external I2C EEPROM connected to //! the I2C bus at address 0x50. //! This program will write 1-14 words to EEPROM and read them back. //! The data written and the EEPROM address written to are contained //! in the message structure, \b I2cMsgOut1. The data read back will be //! contained in the message structure \b I2cMsgIn1. //! //! \note This program will only work on kits that have an on-board I2C EEPROM. T //! (e.g. F2803x eZdsp) //! //! \b Watch \b Variables \n //! - I2cMsgIn1 //! - I2cMsgOut1 // //########################################################################### // $TI Release: F2803x C/C++ Header Files and Peripheral Examples V129 $ // $Release Date: January 15, 2015 $ // $Copyright: Copyright (C) 2009-2015 Texas Instruments Incorporated - // http://www.ti.com/ ALL RIGHTS RESERVED $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File typedef Uint16 uint16; Uint16 LoopCount = 0; Uint16 Error; Uint16 RxBufferIndex = 0; Uint16 RxBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; void I2CA_MASTER_RECEIVER_Init(void); Uint16 I2CA_MASTER_RECEIVE(void); __interrupt void i2c_int1a_isr(void); /* I2C */ #define _D_I2C_RX_BUFFER_SIZE 50 uint16 I2C_RxBuffer[_D_I2C_RX_BUFFER_SIZE]; uint16 *I2C_BufferStart; uint16 *I2C_BufferEnd; uint16 *I2C_PushIndex; uint16 *I2C_PullIndex; uint16 I2C_NewDataCount; void main(void) { // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2803x_SysCtrl.c file. InitSysCtrl(); // Step 2. Initalize GPIO: // This example function is found in the DSP2803x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); // Setup only the GP I/O only for I2C functionality InitI2CGpio(); // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2803x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2803x_DefaultIsr.c. // This function is found in DSP2803x_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.I2CINT1A = &i2c_int1a_isr; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize all the Device Peripherals: // This function is found in DSP2803x_InitPeripherals.c // InitPeripherals(); // Not required for this example // Step 5. User specific code /* I2C-A Basic Configuration */ I2CA_MASTER_RECEIVER_Init(); // Enable interrupts required for this example // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1 PieCtrlRegs.PIEIER8.bit.INTx1 = 1; // Enable CPU INT8 which is connected to PIE group 8 IER |= M_INT8; EINT; /* I2C */ /* Init I2C Interface */ memset(&I2C_RxBuffer, 0, sizeof(I2C_RxBuffer)); I2C_PushIndex = &I2C_RxBuffer[0]; I2C_PullIndex = &I2C_RxBuffer[0]; I2C_BufferStart = &I2C_RxBuffer[0]; I2C_BufferEnd = &I2C_RxBuffer[_D_I2C_RX_BUFFER_SIZE - 3]; I2C_NewDataCount = 0; Error = I2CA_MASTER_RECEIVE(); // Application loop for(;;) { LoopCount++; // if (LoopCount > 1000) { // LoopCount = 0; // } } // end of for(;;) } // end of main /* I2C-A BASIC CONFIGURATION */ void I2CA_MASTER_RECEIVER_Init(void) { /* Disable I2C-A */ I2caRegs.I2CMDR.bit.IRS = 0; /* Configure I2C Module clock using I2CPSC register I2C Module clock should be 7-12 MHz */ I2caRegs.I2CPSC.all = 6; /* Configure I2C baud rate using I2CCLKL and I2CCLKH */ I2caRegs.I2CCLKL = 10; I2caRegs.I2CCLKH = 5; /* Configure I2C Own address using I2COAR */ I2caRegs.I2COAR = 0x0001; /* Configure I2C Slave address to talk to using I2CSAR */ I2caRegs.I2CSAR = 0x0002; /* Non-FIFO mode */ /* Enable below I2C Interrupts using I2CIER * 0h Arbitration Lost (ARBL) * 1h No-acknowledge interrupt (NACK) * 3h Receive Ready (RRDY) * 4h Transmit Ready (XRDY) * */ I2caRegs.I2CIER.all = 0x001B; I2caRegs.I2CMDR.bit.IRS = 1; } Uint16 I2CA_MASTER_RECEIVE(void) { if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } /* Num. of bytes to be transmitted */ I2caRegs.I2CCNT = 1; /* * I2C-A Mode Register (I2CMDR) * 5h IRS * 9h TRX * 10h MST * 13h STT * 14h FREE * */ I2caRegs.I2CMDR.all = 0x6620; while (I2caRegs.I2CSTR.bit.ARDY == 0); RxBufferIndex = 0; I2caRegs.I2CCNT = 8; /* * I2C-A Mode Register (I2CMDR) * 5h IRS * 10h MST * 13h STT * 14h FREE * */ I2caRegs.I2CMDR.all = 0x6420; return I2C_SUCCESS; } Uint16 IntSource; __interrupt void i2c_int1a_isr(void) // I2C-A { // Read interrupt source IntSource = I2caRegs.I2CISRC.all; switch(IntSource) { case I2C_NACK_ISRC: /* Generate STOP condition */ I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; break; case I2C_RX_ISRC: RxBuffer[RxBufferIndex++] = I2caRegs.I2CDRR; if (RxBufferIndex >= 8) { /* Generate STOP condition */ I2caRegs.I2CMDR.bit.STP = 1; } break; case I2C_TX_ISRC: I2caRegs.I2CDXR = 0x00FF; break; } // Enable future I2C (PIE Group 8) interrupts PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; } //=========================================================================== // No more. //===========================================================================
//########################################################################### // //! \addtogroup f2803x_example_list //! <h1>I2C EEPROM(i2c_eeprom)</h1> //! //! This program requires an external I2C EEPROM connected to //! the I2C bus at address 0x50. //! This program will write 1-14 words to EEPROM and read them back. //! The data written and the EEPROM address written to are contained //! in the message structure, \b I2cMsgOut1. The data read back will be //! contained in the message structure \b I2cMsgIn1. //! //! \note This program will only work on kits that have an on-board I2C EEPROM. T //! (e.g. F2803x eZdsp) //! //! \b Watch \b Variables \n //! - I2cMsgIn1 //! - I2cMsgOut1 // //########################################################################### // $TI Release: F2803x C/C++ Header Files and Peripheral Examples V129 $ // $Release Date: January 15, 2015 $ // $Copyright: Copyright (C) 2009-2015 Texas Instruments Incorporated - // http://www.ti.com/ ALL RIGHTS RESERVED $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File Uint16 LoopCount = 0; //Uint16 LedFlag = 0; Uint16 I2C_AASISRCCount = 0; Uint16 I2C_TXISRCCount = 0; Uint16 I2C_I2CDRR = 0; Uint16 I2C_TXISRCIndex = 0; Uint16 I2C_TXIndex = 0; Uint16 I2C_TXBuffer[8] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80 }; Uint16 I2C_RXIndex = 0; Uint16 I2C_RXBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; void InitLedGpio(void); void I2CA_SLAVE_Init(void); __interrupt void i2c_int1a_isr(void); void main(void) { // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2803x_SysCtrl.c file. InitSysCtrl(); // Step 2. Initalize GPIO: // This example function is found in the DSP2803x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); InitLedGpio(); // Setup only the GP I/O only for I2C functionality InitI2CGpio(); // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2803x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2803x_DefaultIsr.c. // This function is found in DSP2803x_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.I2CINT1A = &i2c_int1a_isr; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize all the Device Peripherals: // This function is found in DSP2803x_InitPeripherals.c // InitPeripherals(); // Not required for this example I2CA_SLAVE_Init(); // Step 5. User specific code // Enable interrupts required for this example // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1 PieCtrlRegs.PIEIER8.bit.INTx1 = 1; // Enable CPU INT8 which is connected to PIE group 8 IER |= M_INT8; EINT; // Application loop for(;;) { LoopCount++; // if (LoopCount > 100) { // LoopCount = 0; // // if (LedFlag == 0) { LedFlag = 1; GpioDataRegs.GPADAT.bit.GPIO31 = 1; } // else { LedFlag = 0; GpioDataRegs.GPADAT.bit.GPIO31 = 0; } // } } // end of for(;;) } // end of main void InitLedGpio(void) { EALLOW; /* General purpose I/O */ GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0; GpioCtrlRegs.GPADIR.bit.GPIO31 = 1; EDIS; } void I2CA_SLAVE_Init(void) { /* Disable I2C */ I2caRegs.I2CMDR.bit.IRS = 0; /* Configure I2C Module clock using I2CPSC register I2C Module clock should be 7-12 MHz */ I2caRegs.I2CPSC.all = 6; /* Configure I2C baud rate using I2CCLKL and I2CCLKH */ I2caRegs.I2CCLKL = 10; I2caRegs.I2CCLKH = 5; /* Configure I2C Own address using I2COAR */ I2caRegs.I2COAR = 0x0002; // /* Configure I2C Slave address to talk to using I2CSAR */ // I2caRegs.I2CSAR = 0x0002; I2caRegs.I2CMDR.bit.TRX = 1; /* Transmitter mode */ /* * I2C Interrupt Enable Register (I2CIER) * 3h RRDY * 4h XRDY * 6h AAS * */ I2caRegs.I2CIER.all = 0x0058; /* Enable I2C. */ I2caRegs.I2CMDR.bit.IRS = 1; } __interrupt void i2c_int1a_isr(void) // I2C-A { Uint16 IntSource; // Read interrupt source IntSource = I2caRegs.I2CISRC.all; switch (IntSource) { case I2C_RX_ISRC: I2C_RXBuffer[I2C_RXIndex++] = I2caRegs.I2CDRR; I2caRegs.I2CSTR.bit.RRDY = 1; break; case I2C_TX_ISRC: I2C_TXISRCCount++; I2caRegs.I2CDXR = I2C_TXBuffer[I2C_TXIndex++]; break; case I2C_AAS_ISRC: I2C_AASISRCCount++; I2C_TXIndex = 0; I2C_RXIndex = 0; break; } // Enable future I2C (PIE Group 8) interrupts PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; } //=========================================================================== // No more. //===========================================================================
Hello Kadir,
There is an I2C example for this device located here (C2000Ware_X_XX_XX_XX\device_support\f2803x\examples\c28\i2c_eeprom).
To clarify, are you using two different F28035 devices, where one is a slave and the other is master? Also, can you send a screenshot of the waveform that is received?
Best regards,
Omer Amir
Hi Omer,
First of all, thank you for your feedback.
I already know, there is an I2C example for F28035 but just Master not for Slave.
Yes, I am using two different F28035 devices, one is Master Receiver, and the other is Slave Transmitter.
I am sending screenshot of the PicoScope waveform and file.
Thanks,
Kadir B.
Hello Kadir,
I've looked over your code and compared it to the screenshot, and there is one thing I am curious about. For the master code, it sets the slave address as 2, but in the slave code its own address is set as 0x68. I've looked in the I2CSAR/I2COAR registers, and from what I understand they should match between the slave and master. This may be what's causing the Address as Slave Interrupt to not be entered in first, although I'm not sure why it goes to the transmit interrupt instead, but perhaps if you can clarify the addressing question than I can look into it.
Best regards,
Omer Amir
Hi Omer,
I accidentally send the wrong code.
I work Slave Address as 2.
I encountered the problem when Slave Address as 2.
Hi Kadir,
Okay, that helps. Also, the I2C transmission you screenshotted is coming from master, correct? And that's why you're expecting the I2C_AAS_ISRC flag to be set? And in its place, you are getting a transmit-data-ready flag that's set, meaning the slave is ready to transmit but the communication has not been started.
Best regards,
Omer Amir
Hi Omer,
I2C transmission starts with the Master sending the address, after Slave send data.
In Address as Slave interrupt, I clear the index of the tranmission buffer. (TxBuffer), after Slave send data in Transmission interrrupt.
I use Address as Slave interrupt for clear index.
Thanks,
Kadir B.
Hello Kadir,
If you comment out all the other interrupt flags except the "Address as Slave", does it reach that point in the code? Or is it never triggered at all?
Best regards,
Omer Amir
Hi Omer,
I comment out all the other interrupt flags except the "Address as Slave".
"Transmit-data-ready" is triggered.
I am sharing screenshots.
Thanks,
Kadir B.
Hi Kadir,
Sorry if it wasn't clear, but I meant remove everything in your switch statement so the "Address as Slave" case is the only one available, like so:
switch (IntSource) { /*case I2C_RX_ISRC: I2C_RXBuffer[I2C_RXIndex++] = I2caRegs.I2CDRR; I2caRegs.I2CSTR.bit.RRDY = 1; break; case I2C_TX_ISRC: I2C_TXISRCCount++; I2caRegs.I2CDXR = I2C_TXBuffer[I2C_TXIndex++]; break;*/ case I2C_AAS_ISRC: I2C_AASISRCCount++; I2C_TXIndex = 0; I2C_RXIndex = 0; break; }
Best regards,
Omer Amir
Hello Omer,
Sorry for my miss understanding.
I could trigger only once the "Address as Slave" from Master.
I think stop condition does not occur.
Thanks,
Kadir B.
Hi Kadir,
When you say you triggered the "Address as Slave" from master, do you mean it was triggered in the code for the slave device or master device? And on what basis does it seem like the stop condition is not occurring?
Best regards,
Omer Amir