?? at24c256.c
字號:
/*-------------------------------------------------------------------------
AT24C256 I2C Serial Memory
Written By - Dipl.-Ing. (FH) Michael Schmitt
michael.schmitt@t-online.de
Initial Version Mai 2000
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#ifndef __FILE_AT24C256_C
#define __FILE_AT24C256_C
// Read one or a couple of bytes (maybe all) from the target.
// this is done using the burst mode (or page read mode)
// this is the fastest way to receive more than one byte
// after a byte is received, we send an ACK to the target, to make clear that we
// want another byte from it. The slower way would be to send a stop command
// and restart the byte read mode with a new adress. But this would mean
// at least 21 clock pulses more before the next byte can be received. So every additional
// byte needs only 1/3 of clock pulses to be received.
// ensured: WD is triggered at paragaph bounderies (16 bytes) MK
//
// AT24C256 ONLY !!
unsigned char I2CReadBurst24C256( unsigned char deviceAdr, unsigned int startAdr, unsigned int length, unsigned char xdata *destination)
{
// unsigned char i;
// unsigned char res;
unsigned int xdata endAdr;
endAdr = startAdr + length;
WatchDog();
/* Start I2C */
I2CSendStart();
/* Send Device Adr. + Page + WriteCMD */
I2CSendByte( 0xA0 | deviceAdr ); // Send Device Adress 1010 A2/P2 A1/P1 A0/P0 R/W=0(Write Word Adress)
if( !I2CCheckACK() ) goto NO_ACK;
I2CSendByte( (startAdr >> 8) & 0x00FF ); // HighByte Adress
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
I2CSendByte( startAdr & 0x00FF ); // LowByte Adress
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
I2CSendStop();
/* OK, send Start again */
I2CSendStart();
/* Send Device Adr. + Page + ReadCMD */
I2CSendByte( 0xA1 | deviceAdr ); // Send Device Adress 1010 A2/P2 A1/P1 A0/P0 R/W=1(Read from Word Adress)
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
/* Yes, now start read in Bytes, until finished */
while( startAdr < endAdr )
{
// res = I2CGetByte();
*destination++=I2CGetByte(); // writing to destination and incrementing
startAdr++; // incrementing addresscounter for device
/* if (startAdr <= endAdr) FE */
if (startAdr < endAdr)
{
/* Send ACK, because we want more Bytes */
I2CSendACK();
// I2CSDA = 0;
}
else
{
/* Send NACK, we have all Bytes */
I2CSendNACK();
// I2CSDA = 1;
}
// NOP; /* Now follows the 1/0 clock transition for NACK or ACK */
// I2CSCL = 1;
// NOP;
// I2CSCL = 0;
/* Retrigger Watchdog every 256 Bytes - this is rarely called */
if ( (startAdr & 0xFF) == 0 )
WatchDog();
}
/* OK, if finished or not, send STOP to tell Device, that burst read mode is finished */
I2CSendStop();
return TRUE; // success exit
NO_ACK:
#ifdef EXT_ERRHAN
// cleanup lost clock
I2CClkSyncByte();
#endif
/* OK, if finished or not, make shure i2c is stopped */
I2CSendStop();
return FALSE; // failure exit
}
// although this function has been called writeburst, we do not write all bytes in the
// way, they were read in in function readburst. Because most of the I2C serial EEProms
// need about 10msec write time for each byte. (ATMEL can receive 4 bytes at once and
// write them at once but 4 x 10msec). So, to be on the safe way, i choose to write the
// old way. STARTCMD DEVCODE ADRESS BYTE ACK STOP
// This is not really a burst mode, i know
// AT24C256 ONLY !!
unsigned char I2CWriteBurst24C256( unsigned char deviceAdr, unsigned int startAdr, unsigned int length, unsigned char xdata *source)
{
unsigned int xdata endAdr;
unsigned char AckLoopCount;
unsigned char TempAck;
/* Check here if Chip is currently writing a byte and busy. */
/* This should be done with single byte write's and the ACK-Polling mechanism */
endAdr = startAdr + length;
WatchDog();
for( ; startAdr < endAdr; startAdr++ )
{
/* Start I2C */
I2CSendStart();
/* Send Device Adr. + Page + WriteCMD */
I2CSendByte( 0xA0 | deviceAdr ); // Send Device Adress 1010 A2/P2 A1/P1 A0/P0 R/W=0(Write Word Adress)
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
// {
// return FALSE;
// }
/* Yes, send StartAdr */
I2CSendByte( ((startAdr >> 8) & 0x00FF) ); // HighByte Adress
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
I2CSendByte( startAdr & 0x00FF ); // LowByte Adress
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
I2CSendByte(*source);
/* Did Device send an ACK ? */
if( !I2CCheckACK() ) goto NO_ACK;
/* YES, this Byte is stored, now we have to wait 10msec */
source++;
/* OK, if finished or not, send STOP to tell Device, that burst write mode is finished */
I2CSendStop();
/* now wait until device acknowledges again */
AckLoopCount = 0;
do{
/* Start I2C */
I2CSendStart();
/* Send Device Adr. + Page + WriteCMD */
I2CSendByte( 0xA0 | deviceAdr); // Send Device Adress 1010 A2/P2 A1/P1 A0/P0 R/W=0(Write Word Adress)
/* Did Device send an ACK ? */
AckLoopCount++;
TempAck = I2CCheckACK();
/* Stoppe I2C */
I2CSendStop();
}
while ( !TempAck && (128 >= AckLoopCount) ); // AckLoopCount is unsigned char!! (Loop takes 80us @ 24MHz)
// so 128 gives the 10ms which are the maximum
// of the datasheet (even for VCC=2.7 devices)
// if (!TempAck) return FALSE; // Only OK if exit on Ack
if (!TempAck) goto NO_ACK; // Only OK if exit on Ack
/* calm Watchdog every now and then */
if ( (startAdr & 0x07) == 0 ) // Retrigger Watchdog every xx Bytes
WatchDog();
}
// I2CSendStop();
return TRUE; // success exit
NO_ACK:
#ifdef EXT_ERRHAN
// cleanup lost clock
I2CClkSyncByte();
#endif
I2CSendNACK();
/* OK, if finished or not, make shure i2c is stopped */
I2CSendStop();
return FALSE; // failure exit
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -