Hi,
Am trying to write 100 bytes in EEPROM . In debug mode it is working fine. But when i try to write and read in single shot then while reading , after reading the 14 bytes, it again reading the same 14 bytes. Am sharing my code with this. Anyone please suggest the solution.
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
// Note: I2C Macros used in this example can be found in the// DSP2833x_I2C_defines.h file
// Prototype statements for functions found within this file.void I2CA_Init(void);Uint16 I2CA_WriteData(struct I2CMSG *msg);Uint16 I2CA_ReadData(struct I2CMSG *msg);void readdata(void);void writedata(void);interrupt void i2c_int1a_isr(void);Uint16 readarray[100],writearray[100];
#define I2C_SLAVE_ADDR 0x50#define I2C_NUMBYTES 14#define I2C_EEPROM_HIGH_ADDR 0x00#define I2C_EEPROM_LOW_ADDR 0x01
// Global variables// Two bytes will be used for the outgoing address,// thus only setup 14 bytes maximumstruct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_ADDR, I2C_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR, };
struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_ADDR, I2C_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR};
struct I2CMSG *CurrentMsgPtr; // Used in interruptsUint16 PassCount;Uint16 FailCount;Uint16 readcount;Uint16 writecount;Uint16 Error,j;Uint16 count,count1;
void main(void){ Uint16 i; readcount=0; writecount=0; j=0;
CurrentMsgPtr = &I2cMsgOut1;
// Step 1. Initialize System Control:// PLL, WatchDog, enable Peripheral Clocks// This example function is found in the DSP2833x_SysCtrl.c file. InitSysCtrl();
// Step 2. Initalize GPIO:// This example function is found in the DSP2833x_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 DSP2833x_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 DSP2833x_DefaultIsr.c.// This function is found in DSP2833x_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 DSP2833x_InitPeripherals.c// InitPeripherals(); // Not required for this example I2CA_Init();
// Step 5. User specific code
// Clear Counters PassCount = 0; FailCount = 0;
// Clear incoming message buffer for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++) { readarray[i] = 0x0000; }
// 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;
for( count=0; count<7; ) { writedata(); } for(count1=0;count1<7;) { readdata(); }}
void writedata(void){ Error = I2CA_WriteData(&I2cMsgOut1); // If communication is correctly initiated, set msg status to busy // and update CurrentMsgPtr for the interrupt service routine. // Otherwise, do nothing and try again next loop. Once message is // initiated, the I2C interrupts will handle the rest. Search for // ICINTR1A_ISR in the i2c_eeprom_isr.c file. if (Error == I2C_SUCCESS) { CurrentMsgPtr = &I2cMsgOut1; I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY; } }void readdata(void) { // Check incoming message status. if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) { DELAY_US(10); // EEPROM address setup portion while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS) { // Maybe setup an attempt counter to break an infinite while // loop. The EEPROM will send back a NACK while it is performing // a write operation. Even though the write communique is // complete at this point, the EEPROM could still be busy // programming the data. Therefore, multiple attempts are // necessary. } // Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1; I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY; j++; }
// Once message has progressed past setting up the internal address // of the EEPROM, send a restart to read the data bytes from the // EEPROM. Complete the communique with a stop bit. MsgStatus is // updated in the interrupt service routine. else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART) { // Read data portion while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS) { // Maybe setup an attempt counter to break an infinite while // loop. } // Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1; I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY; } }
void I2CA_Init(void){ // Initialize I2C I2caRegs.I2CSAR = 0x0050; // Slave address - EEPROM control code
#if (CPU_FRQ_150MHZ) // Default - For 150MHz SYSCLKOUT I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz) #endif #if (CPU_FRQ_100MHZ) // For 100 MHz SYSCLKOUT I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz) #endif
I2caRegs.I2CCLKL = 10; // NOTE: must be non zero I2caRegs.I2CCLKH = 5; // NOTE: must be non zero I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset // Stop I2C when suspended
I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT,
return;}
Uint16 I2CA_WriteData(struct I2CMSG *msg){ Uint16 i;
// Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. if (I2caRegs.I2CMDR.bit.STP == 1) { return I2C_STP_NOT_READY_ERROR; }
// Setup slave address I2caRegs.I2CSAR = msg->SlaveAddress;
// Check if bus busy if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; }
// Setup number of bytes to send // MsgBuffer + Address I2caRegs.I2CCNT = msg->NumOfBytes+2;
// Setup data to send I2caRegs.I2CDXR = msg->MemoryHighAddr; I2caRegs.I2CDXR = msg->MemoryLowAddr+writecount; for (i=0; i<msg->NumOfBytes; i++)
{ writearray[i+writecount]= (i+writecount); I2caRegs.I2CDXR = writearray[i+writecount]; } // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20; return I2C_SUCCESS;}
Uint16 I2CA_ReadData(struct I2CMSG *msg){ // Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. if (I2caRegs.I2CMDR.bit.STP == 1) { return I2C_STP_NOT_READY_ERROR; }
I2caRegs.I2CSAR = msg->SlaveAddress;
if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) { // Check if bus busy if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } I2caRegs.I2CCNT = 2; I2caRegs.I2CDXR = msg->MemoryHighAddr; I2caRegs.I2CDXR = msg->MemoryLowAddr+readcount; I2caRegs.I2CMDR.all = 0x2620; // Send data to setup EEPROM address } else if(msg->MsgStatus == I2C_MSGSTAT_RESTART) { I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver }
return I2C_SUCCESS;}
interrupt void i2c_int1a_isr(void) // I2C-A{ Uint16 IntSource, i;
// Read interrupt source IntSource = I2caRegs.I2CISRC.all;
// Interrupt source = stop condition detected if(IntSource == I2C_SCD_ISRC) { // If completed message was writing data, reset msg to inactive state if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY) { count++; writecount=writecount+14; if(writecount==56)writecount=65; } else { // If a message receives a NACK during the address setup portion of the // EEPROM read, the code further below included in the register access ready // interrupt source code will generate a stop condition. After the stop // condition is received (here), set the message status to try again. // User may want to limit the number of retries before generating an error. if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP; } // If completed message was reading EEPROM data, reset msg to inactive state // and read data from FIFO. else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP; for(i=0; i < I2C_NUMBYTES; i++) { readarray[i+readcount] = I2caRegs.I2CDRR; } { // Check recieved data for(i=0; i < I2C_NUMBYTES; i++) { if(writearray[i+readcount] == readarray[i+readcount]) { PassCount++; } else { FailCount++; } } readcount= readcount+14; count1++; if(readcount==56)readcount=65;
}
} } } // end of stop condition detected
// Interrupt source = Register Access Ready // This interrupt is used to determine when the EEPROM address setup portion of the // read data communication is complete. Since no stop bit is commanded, this flag // tells us when the message has been sent instead of the SCD flag. If a NACK is // received, clear the NACK bit and command a stop. Otherwise, move on to the read // data portion of the communication. else if(IntSource == I2C_ARDY_ISRC) { if(I2caRegs.I2CSTR.bit.NACK == 1) { I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; } else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART; } } // end of register access ready
else { // Generate some error due to invalid interrupt source asm(" ESTOP0"); }
// Enable future I2C (PIE Group 8) interrupts PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;}