|
|
View previous topic :: View next topic |
Author |
Message |
jmann
Joined: 27 Dec 2004 Posts: 21
|
Microchip i2c EEProm Chips |
Posted: Sun Apr 17, 2005 9:15 pm |
|
|
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
|
|
Posted: Wed May 11, 2005 2:38 am |
|
|
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
|
|
Posted: Mon Oct 10, 2005 2:02 pm |
|
|
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
|
|
Posted: Tue Oct 11, 2005 7:25 am |
|
|
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
|
|
Posted: Tue Oct 11, 2005 7:25 am |
|
|
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
|
|
Posted: Mon Oct 16, 2006 4:13 am |
|
|
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
|
|
Posted: Fri Mar 19, 2010 11:21 am |
|
|
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. |
|
|
|
|
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
|