CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C Help-- error data return

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
chingB



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

I2C Help-- error data return
PostPosted: Fri Apr 23, 2004 7:54 am     Reply with quote

Hi,

I got an I2C application and my code is listed below:

Code:

#define REC_MARKER   (0xb0)

#define FRAM_SDA     PIN_C4      // i2c data line
#define FRAM_SCL      PIN_C3      // i2c clock line

// total external memory size
#define FRAM_TOTAL_MEM_SIZE   131072

// block length for one transaction (data size)
#define BLOCK_LENGTH  16

// define I2C read/write address
#define FRAM_WR_ADDR  0xA0        // initial FRAM write address at 1st chip
#define FRAM_RD_ADDR  0xA1        // initial FRAM read address at 1st chip

#define ENABLE_FRAM_WP()                       \
        output_high(PIN_C5)       // enable FRAM write protect

#define DISABLE_FRAM_WP()                      \
        output_low(PIN_C5)        // disable FRAM write protect

// for I2C read/write routines
#define I2C_IDLE()                             \
        while ((SSPCON2 & 0x1F) || (SSP_RW))

#define I2C_START()                            \
        SSP_SEN = 1;                           \
        while (SSP_SEN) {                      \
           #asm nop #endasm                    \
        }

#define I2C_RESTART()                          \
        SSP_RSEN = 1;                          \
        while (SSP_RSEN) {                     \
           #asm nop #endasm                    \
        }

#define I2C_STOP()                             \
        SSP_PEN = 1;                           \
        while (SSP_PEN) {                      \
           #asm nop #endasm                    \
        }

#define I2C_WRITE(x)                           \
        SSPBUF = (x);                          \
        while (SSP_BF) {                       \
           #asm nop #endasm                    \
        }                                      \
        I2C_IDLE()

#define I2C_READ(x)                            \
        SSP_RCEN = 1;                          \
        while (SSP_RCEN) {                     \
           #asm nop #endasm                    \
        }                                      \
        SSP_ACKDT = (x);                       \
        SSP_ACKEN = 1;                         \
        while (SSP_ACKEN) {                    \
           #asm nop #endasm                    \
        }

static BOOLEAN  I2C_Device_Ready(unsigned int8 uID);

static BOOLEAN I2C_Device_Ready(unsigned int8 uID)
{
   do
   {
      // Important to clear these bits before we attempt to write
      BCLIF = 0;
      SSP_WCOL = 0;
      I2C_IDLE();     // ensure module is idle
      I2C_START();
   } while (BCLIF);

   I2C_WRITE(uID);    // send memID

   if (!SSP_ACKSTAT)  // test for ACK condition, if received
      return (TRUE);
   return (FALSE);    // no ACK
}

// Write one block of data to the FM24C256 chip
void write_fram_block(
   unsigned int32 uAddress,      // FM24C256 address to write data
   unsigned int8 Block,          // block length or page length to write
   unsigned int8 *data)          // pointer to data buffer for write
{
   unsigned int8 uControl;       // FM24C256 chipselect
   unsigned int8 uI;

   // chipselect for specific FM24C256 to write
   uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;

   DISABLE_FRAM_WP();            // write protect is disabled

   while (!I2C_Device_Ready(uControl));
   I2C_WRITE((make8(uAddress,1)) & 0x7F);  // send MSB of mem address
   I2C_WRITE(make8(uAddress,0));           // send LSB of mem address

   for (uI=0; uI<Block; uI++) {
      I2C_WRITE(*data++);        // send data to FM24C256
   }

   I2C_STOP();
   ENABLE_FRAM_WP();             // write protect is enabled/engage
}

// Write one byte data to FM24C256 chip
void write_fram_Byte(
   unsigned int32 uAddress,      // FRAM address to write data
   unsigned int8 uData)          // byte written to FRAM
{
   unsigned int8 uControl;

   // chipselect for specific FM24C256 to write
   uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;

   DISABLE_FRAM_WP();            // write protect is disabled

   while (!I2C_Device_Ready(uControl));
   I2C_WRITE((make8(uAddress,1)) & 0x7F);  // send MSB of mem address
   I2C_WRITE(make8(uAddress,0));           // send LSB of mem address
   I2C_WRITE(uData);  // send data

   I2C_STOP();
   ENABLE_FRAM_WP();             // write protect is enabled/engage
}

// Read one block of data from FM24C256 chip
void read_fram_block(
   unsigned int32 uAddress,      // FM24C256 address to read data
   unsigned int8 Block,          // block length or one page write
   unsigned int8 *data)          // pointer to gaReadMemRFbuf to store data
{
   unsigned int8 uControl;

   // chipselect for specific FM24C256 to read
   uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;

   while (!I2C_Device_Ready(uControl));
   I2C_WRITE((make8(uAddress,1)) & 0x7F);  // send MSB of mem address
   I2C_WRITE(make8(uAddress,0));           // send LSB of mem address
   I2C_RESTART();
   I2C_WRITE(uControl | 0x01);   // set address for read

   while (Block > 1) {
      I2C_READ(0);
      *data = SSPBUF;
      data++;
      Block--;
   }

   I2C_READ(1);
   *data = SSPBUF;
   I2C_STOP();
}

// Read one byte data from FM24C256 chip
unsigned int8 read_fram_byte(
   unsigned int32  uAddress)    // FM24C256 address to read data
{
   unsigned int8 uControl;

   // chipselect for specific FM24C256
   uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;

   while (!I2C_Device_Ready(uControl));
   I2C_WRITE((make8(uAddress,1)) & 0x7F);  // send MSB of mem address
   I2C_WRITE(make8(uAddress,0));           // send LSB of mem address
   I2C_RESTART();
   I2C_WRITE(uControl | 0x01);    // set address for read
   I2C_READ(1);
   I2C_STOP();
   return (SSPBUF);  // return with data
}

void ConfigureI2C()
{
   // initialize FRAM clock and data I/O
   output_float(FRAM_SCL);    // set clock lines to input
   output_float(FRAM_SDA);    // set data lines to input

   // Configure the MSSP as an I2C Port for PIC18F452
   // Relevant port pins configured as inputs
   SSP_SSPEN = 1;   // Enable I2C mode

   SSP_SSPM3 = 1;   // setup I2C mode
   SSP_SSPM2 = 0;
   SSP_SSPM1 = 0;
   SSP_SSPM0 = 0;

   SSPCON2 = 0;

   SSP_SMP = 0;
   SSP_CKE = 0;     // Set I2C Levels

   // Set I2C Speed. The formula is:
   //
   // SSPADD value = (Fosc/(i2c clock speed * 4)) -1
   //
   // Examples:
   //
   // SSPADD values for an Fosc of 8 MHz:
   // *** NOTE: If you run your PIC at a different Fosc, then you
   // *** you need to calculate new values.
   //
   // For an i2c clock of 100 KHz, SSPADD = 19
   // For an i2c clock of 400 KHz, SSPADD = 4
   // For an i2c clock of 1 MHz, SSPADD = 1

   SSPADD = 4;      // 1 MHz i2c clock at 20MHz oscillator
   SSP_SMP = 1;     // disable slew rate control for 1 MHz operation ONLY

   // *** NOTE: Based on my oscilloscope readings, the i2c clock
   // *** speed seems to run a little slower than what the formula says.
   // *** For example, "400 KHz" is really 370 KHz or so.
   // *** "1 MHz" is really running slightly less than that speed.
}

void init_mcu()      // MCU Initialization Routine
{
   delay_ms(2000);   // delay for 2 seconds (stabilized MCU?)

   ConfigureI2C();   // initialize I2C I/O and configure for I2C mode

   setup_adc_ports(NO_ANALOGS);    // setup PortA to digital I/O

}



The code below is my test program:
Code:

main()
{
   unsigned int8 i;
   char tempbuffer[16];
   char temp2=0;
   unsigned int8 minutes;
   unsigned int8 hours;
   unsigned int8 mthdays;
   unsigned int8 months;
   unsigned int8 years;
   unsigned int8 y2kyrs;
   unsigned int32 addr=0;
   unsigned int16 cnt=0;
   unsigned int16 logcount=0;

   init_mcu();
   delay_ms(500);
   output_low(PIN_A0);

   for (i=0; i<16; i++)
      tempbuffer[i]=0;


   minutes = 30;     // 00 ~ 59 minutes
   hours   = 14;     // 00 ~ 23 hours, military format
   mthdays = 15;     // 01 ~ 31 day(s) of the month
   months  = 11;     // 01 ~ 12 months, 1-Jan ... 12-Dec
   years   = 04;     // 00 ~ 99 2-digit year within a century
   y2kyrs  = 20;     // 20 ~ 99 Y2K year or century

   for (cnt=0; cnt<8192; cnt++){
      addr = cnt*16;
      write_fram_block(addr,16,tempbuffer);
   }

   tempbuffer[0] = (months & 0x0f) | REC_MARKER;
   tempbuffer[1] = mthdays;
   tempbuffer[2] = y2kyrs;
   tempbuffer[3] = years;
   tempbuffer[4] = '0';
   tempbuffer[5] = '1';
   tempbuffer[6] = '2';
   tempbuffer[7] = '3';
   tempbuffer[8] = '4';
   tempbuffer[9] = '5';
   tempbuffer[10] = '6';
   tempbuffer[11] = '7';
   tempbuffer[12] = '8';
   tempbuffer[13] = '9';
   tempbuffer[14] = hours;
   tempbuffer[15] = minutes;

   printf("\r\n\r\n");
   delay_ms(500);
   for (cnt=1000; cnt<3600; cnt++){
      addr = cnt*16;
      write_fram_block(addr,16,tempbuffer);
   }

   printf("\r\n\r\n");
   delay_ms(1000);
   
   temp2=0;
   for (cnt=0;cnt<8192;cnt++){
      addr = cnt*16;
      temp2 = read_fram_byte(addr);
      temp2 = temp2 & 0xf0;
     
      if (temp2 == REC_MARKER)
         logcount++;
   }
   
   printf("\r\nLogCount=%lu",logcount);
   printf("\r\n\r\n");

   while (TRUE);
}



My application is like this... I write a 16byte data to the FRAM with the 1st byte of the array is and'ed with 0x0f then or'ed with 0xb0.

Then I scan the entire 4 FRAM chip reading the 1st byte of 16 byte data for 0xb0 and increment the FRAM reading by 16bytes...

If 0xb0 found it increment the log counter....

My problem really is that I got an incorrect value of log count.

I need ur help guys... I can't figure out the problem...

BTW, I have four(4) FM24C256 from ramtron with a total records of 8192 where each record consist of 16bytes data. I run this on PIC18F452 at 20MHz using PCWH v3.188.

In addition, I'm using linear addressing in reading the entire 4 FRAM chips.

Thank u.
chingB



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 5:18 pm     Reply with quote

Anyone can help me with my problem?

Thnx
Guest








FRAM linear addressing
PostPosted: Fri Apr 23, 2004 10:16 pm     Reply with quote

Quote:
In addition, I'm using linear addressing in reading the entire 4 FRAM chips.
End quote:

You cannot linear address across chips. each chip starts at 0 and ends at 32767

You have to take care of the linear addressing.

Anyway, there are plenty of code samples on this forum, search for FRAM or EEPROM both will works just don't bother with the delay for the FRAM.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group