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

Microchip i2c EEProm Chips

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
jmann



Joined: 27 Dec 2004
Posts: 21

View user's profile Send private message

Microchip i2c EEProm Chips
PostPosted: Sun Apr 17, 2005 9:15 pm     Reply with quote

This is the driver I wrote for a 512 Mbit (64 Kbyte) microchip i2c EEProm. to be best of my simple testing, it works, as I have used it for a few simple tasks. the chip I used had a 64 byte buffer.

update (may 2005): I won senior project of the year!!!!


Code:

//------------------------------------
// Access to External EE-Prom
//
// Read/WriteExtMem(Address, Data, Length)
// ->Address (int16) 16 bit Address to first byte of read/write on EEprom.
//    Valid addresses are from 0x0000 through 0xFFFF
// ->Data (pointer) a pointer to the variable where
//    data comes from or is written to sequentially
// ->Length (int16) How much data to read/Write to/from *Data (in bytes).
// LIMITS
// ->Data cannot be accesses through the  0x7FFF-0x8000 point. That is that
//    all write/read data must be contained within 0x0000-0x07FFF or
//    0x8000-0xFFFF.
// ->Data is not checked for these location constraints.
//
//   Driver by Jeffrey Mann
//
//------------------------------------
/* I2c address for external EEprom*/
#define EEpromWrite        0b10100000
#define EEpromRead         0b10100001
#define ACK                     0
#define NoACK                 1


//------------------------------------
// Read to External EE-Prom
//------------------------------------
int1 ReadExtMem(int16 Address, char *data, int16 length)
{
   int16 i, blockmask;
   BlockMask=0;
   if (address>0x7FFF)
      blockmask=0b00001000;
   disable_interrupts(global) //Disable Intterrupts
   i2c_start();
   if (i2c_write(EEpromWrite | blockmask)||
       i2c_write(make8(Address, 1))||
       i2c_write(make8(Address, 0)))
   {
       enable_interrupts(global);
       return ERROR;
   }
   i2c_start(); //repeated start
   if (i2c_write(eePromRead | blockmask))
   {
       enable_interrupts(global);
       return ERROR;
   }
   for( i = 0; i < length-1 ; i++)
      *Data++ = i2c_read(ACK);  //read all but last data byte
   *Data = i2c_read(NoACK);     //read last data byte (with NoACK)
   i2c_stop();
   enable_interrupts(global);
   return noError;
}

//------------------------------------
// Write to External EE-Prom
//------------------------------------
int1 WriteExtMem(int16 Address, char *data, int16 length)
{
   int8 i, blockmask, waiting;
   BlockMask=0;
   if (address>0x7FFF)
      blockmask=0b00001000;
   if (length==0) return NoError;
   disable_interrupts(global);
   i2c_start();
   if (i2c_write(EEpromWrite | blockmask))
       return ERROR;
WriteStart:                                         //  HA! I found a valid use for GOTO
   if (i2c_write(make8(Address, 1))||
       i2c_write(make8(Address, 0)))
   {
       enable_interrupts(global);
       return ERROR;
   }
   for (i=0; i<64 && length; i++, length--)          //  EEProm can only write 64 bytes at a time
   {
      if(i2c_Write(*Data++)==NoACK)
         {
            enable_interrupts(global);
            Return ERROR;
         }
   }
   i2c_stop();
   enable_interrupts(global)
   if (length)                                             //if after 64 bytes, more data is waiting to be written,
   {
      Address=address+64;
      i2c_start();
      while (i2c_write(EEpromWrite | blockmask)==1)  //NoACK // wait for write to finish so more data can be written
         i2c_start() ;
      disable_interrupts(global);
      goto WriteStart;
   }
   return noError;

}


Last edited by jmann on Wed May 25, 2005 3:50 pm; edited 2 times in total
dam



Joined: 10 May 2005
Posts: 4

View user's profile Send private message

PostPosted: Wed May 11, 2005 2:38 am     Reply with quote

Thanks for this code ! I've use it to drive a 24LC256 in my latest project, and it works perfectly !
dam



Joined: 10 May 2005
Posts: 4

View user's profile Send private message

PostPosted: Mon Oct 10, 2005 2:02 pm     Reply with quote

Well in fact I had to modify the original code a bit to drive a 24LC256, for those who are interested, here is the code.

Code:
/*---------------------------------------------------------------------------*
 * EEPROM 24LC256 driver (Microchip, I�C, 256 Kbits)                         *
 *                                                                           *
 * Parameters:                                                               *
 * -> Address  15 bit address of first byte to read/write on eeprom.         *
 *             Valid addresses are from 0x0000 to 0x7FFF                     *
 * -> Data     a pointer to the variable where data comes from or is written *
 *             to sequentially                                               *
 * -> Length   how much data to read/Write to/from *data (in bytes)          *
 *                                                                           *
 * Last modified 10-oct-05                                                   *
 * Original code by Jeffrey Mann, mod. by Damien Teney                       *
 *---------------------------------------------------------------------------*/


/*-----------------------------------------------------*
 * I�C addresses of the external EEPROM                *
 *-----------------------------------------------------*/
#define EEPROM_WRITE        0b10100000
#define EEPROM_READ         0b10100001


/*-----------------------------------------------------*
 * Read from the external EEPROM                       *
 *-----------------------------------------------------*/
int1 readExtMem(unsigned int16 address, char *data, unsigned int16 length) {
  int16 i;

  i2c_start();
  if (i2c_write(EEPROM_WRITE) || i2c_write(make8(address, 1)) || i2c_write(make8(address, 0)))
    return false;

  i2c_start(); // Repeated start
  if (i2c_write(EEPROM_READ))
    return false;

  for(i = 0; i < length-1; i++)
    *Data++ = i2c_read(1); // Read all but last data byte

  *Data = i2c_read(0); // Read last data byte (with no ack)

  i2c_stop();

  return true;
}


/*-----------------------------------------------------*
 * Write to the external EEPROM                        *
 *-----------------------------------------------------*/
int1 writeExtMem(unsigned int16 address, char *data, unsigned int16 length) {
  int8 i;

  if (length == 0)
    return false;

  i2c_start();
  if (i2c_write(EEPROM_WRITE))
    return false;

WriteStart:

  if (i2c_write(make8(address, 1)) || i2c_write(make8(address, 0)))
    return false;

  for (i=0; i < 64 && length; i++, length--) // EEProm can only write 64 bytes at a time
    if(i2c_Write(*Data++) == 1)
      return false;

  i2c_stop();

  if (length) { // If after 64 bytes, more data is waiting to be written
    address = address + 64;

    i2c_start();

    while (i2c_write(EEPROM_WRITE) == 1)  // NoACK // wait for write to finish so more data can be written
      i2c_start() ;

    goto WriteStart;
  }

  return true;
}


Last edited by dam on Tue Jun 08, 2010 7:39 am; edited 1 time in total
pirev



Joined: 19 Mar 2005
Posts: 13
Location: Bulgaria

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Tue Oct 11, 2005 7:25 am     Reply with quote

Hi, I thing that WriteExtMem() function will not work properly in all of situations. Here is a quote from MicroChip document DS21203M.PDF ( 24xx256 ) , page 9 :
Quote:

Note: Page write operations are limited to writing
bytes within a single physical page,
regardless of the number of bytes actually
being written. Physical page boundaries
start at addresses that are integer
multiples of the page buffer size (or ‘page
size’) and end at addresses that are
integer multiples of [page size - 1]. If a
Page Write command attempts to write
across a physical page boundary, the
result is that the data wraps around to the
beginning of the current page (overwriting
data previously stored there), instead of
being written to the next page, as might be
expected. It is, therefore, necessary for the
application software to prevent page write
operations that would attempt to cross a
page boundary.


Here is my solution ( if some one found errors in my source, please send me notification ):
Code:

//
// I2C Master interface for PIC16/PIC18 using MSSP module
// Written by Svetoslav Pirev, Bulgaria, Plovdiv, pirev@abv.bg, ICQ: 321848589
// ver 1.0 - 10 Oct 2005
//

//#define I2C_SPEED   ( ( OSC_CLOCK / ( 4 * 400000 ) ) - 1 )   // 400 kHz
#define I2C_SPEED   ( ( OSC_CLOCK / ( 4 * 100000 ) ) - 1 )   // 100 kHz
//#define I2C_SPEED   ( ( OSC_CLOCK / ( 4 *  75000 ) ) - 1 )   // 75 kHz
//#define I2C_SPEED   ( ( OSC_CLOCK / ( 4 *  50000 ) ) - 1 )   // 50 kHz
//#define I2C_SPEED   ( ( OSC_CLOCK / ( 4 *  25000 ) ) - 1 )   // 25 kHz

//#define M2416
//#define M2432
//#define M2465
//#define M24128
//#define M24256
//#define M24512
#define M24515

#ifdef M2416   // 24LC16B
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 2048;
const int8 I2C_PAGE_SIZE = 16;
#else

#ifdef M2432   // 24LC32
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 8192;
const int8 I2C_PAGE_SIZE = 32;
#else

#ifdef M2465   // 24LC65
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 8192;
const int8 I2C_PAGE_SIZE = 8;
#else

#ifdef M24128   // 24LC128
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 16384;
const int8 I2C_PAGE_SIZE = 64;
#else

#ifdef M24256   // 24LC256
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 32768;
const int8 I2C_PAGE_SIZE = 64;
#else

#ifdef M24512   // 24LC512
const int8 I2C_SLAVE = 0xA0;
const int32 I2C_EEPROM_SIZE = 65536;
const int8 I2C_PAGE_SIZE = 128;
#else

#ifdef M24515   // 24LC515; Note: pin 3 must be connect to VCC for proper operation !
const int8 I2C_SLAVE = 0xA2;
const int32 I2C_EEPROM_SIZE = 65536;
const int8 I2C_PAGE_SIZE = 64;
#endif

#endif
#endif
#endif
#endif
#endif

// Variables for I2C interface
int16   i2caddr;
int8   i2cslave,   // I2C address of Slave device
      i2cflags,   // flags
      i2ccount;

#bit i2c_error=i2cflags.0
#bit i2c_page_cross=i2cflags.1

// Initialize MSSP module for Master I2C mode operation
void I2CInitMaster(void) {
   i2cslave = I2C_SLAVE;
   SSPCON = 0;
   SSPIE = 0;      // Disable interrupt from I2C module
   TRISC |= 0b00011000;   // Make SCL & SDA to be inputs

   SMP = 1;      //  enable 100KHz & 1MHz !
   CKE = 0;      //   I2C specification !
   GCEN = 0;      //    disable interrupt when detect general call address on the i2c bus .
   SSPADD = I2C_SPEED;
   SSPCON = 0x08;   //   Master mode, 7-bit address, clock=(Fosc/(4*I2CClock))-1;
   SSPIF = 0;
   SSPEN = 1;      //    Enable I2C port
}

/////////////////////////////////////////////////////////////
void I2CClearColision(void)   {
   WCOL = 0; BCLIF = 0;
}

// From MicroChip document 00735A.PDF
/////////////////////////////////////////////////////////////
void I2CWait(void)   {
   while( (SSPCON2 & 0x1F) | R_W );
}

/////////////////////////////////////////////////////////////
void I2CWrite(char data)   {
   SSPBUF = data;
   I2CWait();
// In Master Transmit Mode: Check for Acknowledge
   i2c_error = 0;
   if( ACKSTAT )
      i2c_error = 1;
}

/////////////////////////////////////////////////////////////
void I2CIsFree(void)   {
   i2c_error = 1;
   if( I2C_STOP || ! I2C_START )
      i2c_error = 0;
}

/////////////////////////////////////////////////////////////
void I2CStart(void)   {
   SEN = 1;      // Initiate Start condition
   I2CWait();
}

/////////////////////////////////////////////////////////////
void I2CRepStart(void)   {
   RSEN = 1;      // Second Start condition
   I2CWait();
   I2CWrite( i2cslave | 0x01 );      // Set Read operation
}

/////////////////////////////////////////////////////////////
void I2CStop(void)   {
   PEN   = 1;      // Generate STOP condition
   I2CWait();
}

/////////////////////////////////////////////////////////////
void I2CWriteAck(void)   {
// In Master receive mode: Value that will be transmitted when the user
// initiates an Acknowledge sequence at the end of a receive.
//
   ACKDT = 0;      //   Acknowledge
// In Master receive mode: Initiate Acknowledge sequence on SDA & SCL
// and transmit ACKDT data bit. Automatically cleared by hardware
//
   ACKEN = 1;
   I2CWait();
}

/////////////////////////////////////////////////////////////
void I2CWriteNotAck(void)   {
// In Master receive mode: Value that will be transmitted when the user
// initiates an Acknowledge sequence at the end of a receive.
//
   ACKDT = 1;      // Not Acknowledge
// In Master receive mode: Initiate Acknowledge sequence on SDA & SCL
// and transmit ACKDT data bit. Automatically cleared by hardware
//
   ACKEN = 1;
   I2CWait();
}

/////////////////////////////////////////////////////////////
char I2CRead(void)   {
   while( R_W );         // Wait for transmit to end ...
   RCEN = 1;            // Enter Master mode reception
   I2CWait();            // Wait to receive one byte
   return SSPBUF;
}

/////////////////////////////////////////////////////////////
void I2CWriteAddr(void)   {
   I2CClearColision();
   I2CIsFree();         // If I2C is free ?
   if(   i2c_error )
      return;            // bus is busy !
   I2CStart();                  // Send Start signal
#ifdef M24515
   i2cslave &= ~0x08;
   if( bit_test(i2caddr,15) )
      i2cslave |= 0x08;
#endif
   I2CWrite( i2cslave );         // Set Write operation
   if( i2c_error )
      return;
   I2CWrite( (int8)(i2caddr>>8) );   // Send high byte of address
   if( i2c_error )
      return;
   I2CWrite( (int8)i2caddr );         //   Send low byte of address
}

void I2CCheckPageCross(void) {
   i2c_page_cross = 0;
   if( ++i2caddr % I2C_PAGE_SIZE == 0 )
      i2c_page_cross = 1;
}

int8 I2CReadByte(int16 addr)   {
   i2caddr = addr;
   I2CWriteAddr();         // Write I2C device address
   if( i2c_error )
      return 0;         // bus is busy !
   I2CRepStart();         // Second Start ...
   if( i2c_error )
      return 0;         // bus is busy !
   I2CRead();
   I2CWriteNotAck();      // Send Not Acknowledge signal
   I2CStop();            // Generate Stop condition
   return SSPBUF;
}

/////////////////////////////////////////////////////////////
void I2CReadBuffer(int16 addr,int8 *dst,int8 count)   {
   i2caddr = addr;
   I2CWriteAddr( );   // Write address in address registers
   if( i2c_error )
      return;            // bus is busy !
   I2CRepStart();         // Second Start ...
   if( i2c_error )
      return;            // bus is busy !
   i2ccount = count;
   do {
      *dst++ = I2CRead();
      if( --count == 0 )
         break;
#ifdef M24515
      if( ++i2caddr == 0x8000 ) {
         I2CStop();
         I2CWriteAddr( );
         if( i2c_error )
            break;
         I2CRepStart();
         if( i2c_error )
            break;
      } else
         I2CWriteAck();
#else
      I2CWriteAck();
#endif
   } while( 1 );
   i2caddr = addr;
   I2CWriteNotAck();      // Send Not Acknowledge signal
   I2CStop();            // Generate STOP condition
}

/////////////////////////////////////////////////////////////
void I2CWriteByte(   int16 addr,   // destination address in I2C memory
               int8 data)   // data byte
{
   i2caddr = addr;
   I2CWriteAddr( );   // Write address in address registers
   if( i2c_error )
      return;            // bus is busy !
   I2CWrite( data );
   I2CStop();
   // Waiting write operation to complete with polling for end of cycle
   while( 1 ) {
      I2CWriteAddr();
      if( ! i2c_error )
         break;
      I2CInitMaster();
   }
   I2CRepStart();         // Send Start signal
   if( i2c_error )
      return;
   // Verify write operation
   if( data != I2CRead() )
      i2c_error = 1;
   I2CWriteNotAck();      // Send Not Acknowledge signal
   I2CStop();            // Generate STOP condition
}

/*
Note: 24xx512, 24xx515, 24xx256, 24xx128 ( MicroChip & Atmel )
   Page write operations are limited to writing
   bytes within a single physical page, regardless
   of the number of bytes actually being
   written. Physical page boundaries start at
   addresses that are integer multiples of the
   page buffer size (or ‘page size’) and end at
   addresses that are integer multiples of
   [page size - 1]. If a page write command
   attempts to write across a physical page
   boundary, the result is that the data wraps
   around to the beginning of the current page
   (overwriting data previously stored there),
   instead of being written to the next page as
   might be expected. It is therefore necessary
   for the application software to prevent
   page write operations that would attempt to
   cross a page boundary.
 */
void I2CWriteBuffer(int16 addr, // destination address in I2C memory
               int8 *src,   // source adress
               int count)   // number of data bytes to transfer
{
   if( count == 0 || count > I2C_PAGE_SIZE ) {
      i2c_error = 1;
      return;
   }
   i2caddr = addr;
   I2CWriteAddr( );
   if( i2c_error )
      return;
   i2ccount = count;
   while( 1 ) {
      I2CWrite( *src++ );
      if( i2c_error )
         goto I2CWriteBufferNotOk;
      if( --i2ccount == 0 )
         break;
#ifdef M24515
      I2CCheckPageCross();
      if( i2c_page_cross ) {
         I2CStop();
         while( 1 ) {
            I2CWriteAddr();
            if( ! i2c_error )
               break;
            I2CInitMaster();
         }
      }
#endif
   }
   I2CStop();
   i2caddr = addr;
   // Waiting write operation to complete with polling for end of cycle
   while( 1 ) {
      I2CWriteAddr();
      if( ! i2c_error )
         break;
      I2CInitMaster();
   }
   I2CRepStart();
   if( i2c_error )
      goto I2CWriteBufferNotOk;
   // Verify write operation
   src -= count;
   i2ccount = count;
   do {
      if( *src++ != I2CRead() ) {
         i2c_error = 1;
         goto I2CWriteBufferNotOk;
      }
      if( --i2ccount == 0 )
         break;
#ifdef M24515
      I2CCheckPageCross();
      if( i2c_page_cross ) {
         I2CWriteNotAck();
         I2CStop();
         I2CWriteAddr();
         if( i2c_error )
            goto I2CWriteBufferNotOk;
         I2CRepStart();
         if( i2c_error )
            goto I2CWriteBufferNotOk;
      } else
         I2CWriteAck();
#else
      I2CWriteAck();
#endif
   } while( 1 );
   I2CWriteNotAck();

I2CWriteBufferOk:
   I2CStop();
   return;

I2CWriteBufferNotOk:
   I2CStop();
   I2CInitMaster();
}

pirev



Joined: 19 Mar 2005
Posts: 13
Location: Bulgaria

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Tue Oct 11, 2005 7:25 am     Reply with quote

Here is my software I2C implementation:
Code:

//
// I2C Master interface for PIC16/PIC18, software implementation
//
// Written by Svetoslav Pirev, Bulgaria, Plovdiv, pirev@abv.bg, ICQ: 321848589
// ver 1.0 - 30 Oct 2001
// ver 1.1 - 16 Jul 2003
// ver 1.2 - 08 Oct 2005
//

#bit _SCL=PORTC.3
#bit _SDA=PORTC.4
#bit _SCLTRIS=TRISC.3
#bit _SDATRIS=TRISC.4

//#define M2416
//#define M2432
//#define M2465
//#define M24128
//#define M24256
//#define M24512
#define M24515

#ifdef M2416   // 24LC16B
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 2048;
const int8 I2C_PAGE_SIZE = 16;
#else

#ifdef M2432   // 24LC32
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 8192;
const int8 I2C_PAGE_SIZE = 32;
#else

#ifdef M2465   // 24LC65
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 8192;
const int8 I2C_PAGE_SIZE = 8;
#else

#ifdef M24128   // 24LC128
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 16384;
const int8 I2C_PAGE_SIZE = 64;
#else

#ifdef M24256   // 24LC256
const int8 I2C_SLAVE = 0xA0;
const int16 I2C_EEPROM_SIZE = 32768;
const int8 I2C_PAGE_SIZE = 64;
#else

#ifdef M24512   // 24LC512
const int8 I2C_SLAVE = 0xA0;
const int32 I2C_EEPROM_SIZE = 65536;
const int8 I2C_PAGE_SIZE = 128;
#else

#ifdef M24515   // 24LC515
const int8 I2C_SLAVE = 0xA2;
const int32 I2C_EEPROM_SIZE = 65536;
const int8 I2C_PAGE_SIZE = 64;
#endif

#endif
#endif
#endif
#endif
#endif
const int8 I2C_NORMAL_BUS = 5;    // 5us - 100kHz bus
const int8 I2C_FAST_BUS = 2;    // 2us - 400kHz bus
const int8 I2C_WRITE_DELAY = 5;   // 5ms

// Variables for I2C interface
int16   i2caddr;
int8   i2cslave,   // I2C address of slave device
      i2cflags,   // I2C bus flags
      i2cdata,
      i2ccount,
      i2ccount2,
      i2ctemp;

#bit i2c_error=i2cflags.0
#bit i2c_page_cross=i2cflags.1

void I2CFreeBus(void);

void I2CInitMaster(void) {
   i2cslave = I2C_SLAVE;
   I2CFreeBus();
}

void I2CDelay(void)   {
   delay_us( I2C_NORMAL_BUS );
}

void I2CWriteDelay(void)   {
   delay_ms( I2C_WRITE_DELAY );
}

void InSDA(void)   {
   _SDATRIS = 1; _SDA = 0;
}

void OutSDA(void)   {
   _SDATRIS = 0;
}

void I2CFreeBus(void)   {
   _SDATRIS = 1; _SCLTRIS = 1;
}

void I2CGetBus(void)   {
   _SDA = 1; _SCL = 1;
   _SDATRIS = 0; _SCLTRIS = 0;
}

void IsI2CFree(void)   {
#asm
   bcf      i2c_error
   btfsc   _SDA
   btfss   _SCL
   bsf      i2c_error
#endasm
}

void I2CStart(void)   {
   _SCL = 1; I2CDelay();
   _SDA = 0; I2CDelay();
   _SCL = 0; I2CDelay();
}

void I2CStop(void)   {
   _SDA = 0; I2CDelay();
   _SCL = 1; I2CDelay();
   _SDA = 1; I2CDelay();
}

void I2CWrite(int8 data)   {
   i2ccount = 8;
   do {
      _RLF_F( data );
      if( _C )
         _SDA = 1;
        else
         _SDA = 0;
        _SCL = 1; I2CDelay();
       _SCL = 0; I2CDelay();
   } while( --i2ccount != 0 );
}

int8 I2CRead(void)   {
   InSDA();
     i2ccount = 8;
     do {
         _SCL = 1; I2CDelay();
         _C = 0;
      if( _SDA )
         _C = 1;
         _RLF_F( i2cdata );
         _SCL = 0; I2CDelay();
     } while( --i2ccount != 0 );
     OutSDA();
     return i2cdata;
}

void I2CReadAck(void)   {
   InSDA();      // Make _SDA to be input
   _SCL = 1; I2CDelay();
   i2c_error = 0;
   if( _SDA )
      i2c_error = 1;
    _SCL = 0; I2CDelay();
   OutSDA();
}

// Master in receive mode must generate AckNo signal for slave
void I2CWriteAck(void)   {
   _SDA = 0; I2CDelay();
   _SCL = 1; I2CDelay();
   _SCL = 0; I2CDelay();
}

void I2CWriteNotAck(void) {
   _SDA = 1; I2CDelay();
   _SCL = 1; I2CDelay();
   _SCL = 0; I2CDelay();
}

void I2CRepStart(void)   {
   _SDA = 1; I2CDelay();
   I2CStart();
   // Write device address for read operation
   I2CWrite( i2cslave | 0x01 );
   I2CReadAck();
}

void I2CWriteAddr(void)   {
   IsI2CFree();
   if( i2c_error )
      return;
   I2CGetBus();
   I2CStart();
#ifdef M24515
   i2cslave &= ~0x08;
   if( bit_test(i2caddr,15) )
      i2cslave |= 0x08;
#endif
   // Write device address
   I2CWrite( i2cslave ); I2CReadAck();
   if( i2c_error )
      return;
   // Write high byte of address in memory
   I2CWrite( (int8)(i2caddr>>8) ); I2CReadAck();
   if( i2c_error )
      return;
   // Write low byte ot address in memory
   I2CWrite( (int8)i2caddr); I2CReadAck();
}

void I2CCheckPageCross(void) {
   i2c_page_cross = 0;
   if( ++i2caddr % I2C_PAGE_SIZE == 0 )
      i2c_page_cross = 1;
}

// I2CReadByte() - Ok !
int8 I2CReadByte(int16 addr)   {
   i2caddr = addr;
   I2CWriteAddr( );
   if( i2c_error )
      goto RdByteErr;
   I2CRepStart();
   if( i2c_error )
      goto RdByteErr;
   i2cdata = I2CRead();
   I2CWriteNotAck();
   I2CStop(); I2CFreeBus();
   return i2cdata;
RdByteErr:
    I2CFreeBus();
   return 0;
}

// I2CReadBuffer() - Ok !
void I2CReadBuffer(int16 addr, char *dst,int8 count )   {
   i2caddr = addr;
   I2CWriteAddr( );
    if( i2c_error )
      goto RdSeqErr;
   I2CRepStart();
   if( i2c_error )
      goto RdSeqErr;
   do {
        *dst++ = I2CRead();
      if( --count == 0 )
         break;
#ifdef M24515
      if( ++i2caddr == 0x8000 )   {
         I2CStop();
         I2CWriteAddr( );
         if( i2c_error )
            break;
         I2CRepStart();
         if( i2c_error )
            break;
      } else
         I2CWriteAck();
#else
      I2CWriteAck();
#endif
   } while( 1 );
   I2CWriteNotAck();
   I2CStop();
RdSeqErr:
   I2CFreeBus();
   i2caddr = addr;
}

void I2CWriteByte(int16 addr,int8 data)   {
   i2caddr = addr;
   I2CWriteAddr( );
   if( i2c_error )
      goto WrByteErr;
   I2CWrite( data );
   I2CReadAck();
   if( i2c_error )
      goto WrByteErr;
   I2CStop();
   // Polling for end of write operation
   i2caddr = addr;
   while( 1 ) {
      I2CWriteAddr( );
      if( ! i2c_error )
         break;
      I2CInitMaster();
   }
   // Verify data
   I2CRepStart();
   if( i2c_error )
      goto   WrByteErr;
   if( data != I2CRead() )
      i2c_error = 1;
   I2CWriteNotAck();
WrByteErr:
   I2CStop();
   I2CFreeBus();
}

/*
Note: 24xx512, 24xx515, 24xx256, 24xx128 ( MicroChip & Atmel )
   Page write operations are limited to writing
   bytes within a single physical page, regardless
   of the number of bytes actually being
   written. Physical page boundaries start at
   addresses that are integer multiples of the
   page buffer size (or ‘page size’) and end at
   addresses that are integer multiples of
   [page size - 1]. If a page write command
   attempts to write across a physical page
   boundary, the result is that the data wraps
   around to the beginning of the current page
   (overwriting data previously stored there),
   instead of being written to the next page as
   might be expected. It is therefore necessary
   for the application software to prevent
   page write operations that would attempt to
   cross a page boundary.
 */
void I2CWriteBuffer(int16 addr,int8 *src,int8 count)   {
   i2ccount2 = count;
   i2caddr = addr;
   I2CWriteAddr( );
   if( i2c_error )
      goto I2CWriteBufferNotOk;
   while( 1 ) {
      I2CWrite( *src++ );
      I2CReadAck();
      if( i2c_error )
         goto I2CWriteBufferNotOk;
      if( --i2ccount2 == 0 )
         break;
#ifdef M24515
      I2CCheckPageCross();
      if( i2c_page_cross ) {
         I2CStop();
         while( 1 ) {
            I2CWriteAddr();
            if( ! i2c_error )
               break;
            I2CInitMaster();
         }
      }
#endif
   }
   I2CStop();
   i2caddr = addr;
   // Waiting memory with polling
   while( 1 ) {
      I2CWriteAddr();
      if( ! i2c_error )
         break;
      I2CInitMaster();
   }
   I2CRepStart();
   if( i2c_error )
      goto I2CWriteBufferNotOk;
   // Veryfication
   src -= count;
   i2ccount2 = count;
   do {
      if( *src++ != I2CRead() )
         goto I2CWriteBufferNotOk;
      if( --i2ccount2 == 0 )
         break;
#ifdef M24515
      I2CCheckPageCross();
      if( i2c_page_cross ) {
         I2CWriteNotAck();
         I2CStop();
         I2CWriteAddr();
         if( i2c_error )
            goto I2CWriteBufferNotOk;
         I2CRepStart();
         if( i2c_error )
            goto I2CWriteBufferNotOk;
      } else
         I2CWriteAck();
#else
      I2CWriteAck();
#endif
   } while( 1 );
   I2CWriteNotAck();      // Send Not Acknowledge signal
   goto I2CWriteBufferOk;
I2CWriteBufferNotOk:
   i2c_error = 1;
I2CWriteBufferOk:
   I2CStop();
   I2CFreeBus();
   i2caddr = addr;
}

Neckruin



Joined: 17 Jan 2006
Posts: 66

View user's profile Send private message

PostPosted: Mon Oct 16, 2006 4:13 am     Reply with quote

Quote:
LIMITS
// ->Data cannot be accesses through the 0x7FFF-0x8000 point. That is that
// all write/read data must be contained within 0x0000-0x07FFF or
// 0x8000-0xFFFF.
// ->Data is not checked for these location constraints.


What does this mean exactly Jeff?
I'm using a M24512 by ST external memory in a project and I don't understand why you change the Enable Select bits when the address is higher than 0x7FFF. This memory has a capacity of 64Kbytes, so, you should be able to access to a full range (from 0x0000 to 0xFFFF) of addresses in a single chip. So, if you change the Enable Select bits... I suposse that that means you are using more than one external memory or... what else??
Could you explain it to me please????

Thank you very much,

Juanma
jmann



Joined: 27 Dec 2004
Posts: 21

View user's profile Send private message

PostPosted: Fri Mar 19, 2010 11:21 am     Reply with quote

Neckruin wrote:
Quote:
LIMITS
// ->Data cannot be accesses through the 0x7FFF-0x8000 point. That is that
// all write/read data must be contained within 0x0000-0x07FFF or
// 0x8000-0xFFFF.
// ->Data is not checked for these location constraints.


What does this mean exactly Jeff?


When sequentially accessing data, you cannot cross this boundary in a sequential transaction. The chip treats these sort of like separate chips internally.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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