AT24C02 Driver
/* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __AT24_H #define __AT24_H #include <string.h> #include "hw_twi.h" #include "hw_def.h" /* AT24C02, 2K Bits SERIAL EEPROM: Internally organized with 32 pages of 8 bytes each, the 2K Bits requires an 8-bit data word address for random word addressing. // Serial EEPROM type ////////////////////////////////////////////////////////// #define IIC_EEPROM_AT24C01 1 // AT24C01 - 1K ( 128 x 8) ( 8 byte page write) #define IIC_EEPROM_AT24C02 2 // AT24C02 - 2K ( 256 x 8) ( 8 byte page write) #define IIC_EEPROM_AT24C04 4 // AT24C04 - 4K ( 512 x 8) (16 byte page write) #define IIC_EEPROM_AT24C08 8 // AT24C08 - 8K (1024 x 8) (16 byte page write) #define IIC_EEPROM_AT24C16 16 // AT24C16 -16K (2048 x 8) (16 byte page write) +---+---+---+---+---+---+---+---+ 1k/2K | 1 | 0 | 1 | 0 | A2| A1| A0|R/W| AT24C01A/AT24C02 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 4k | 1 | 0 | 1 | 0 | A2| A1| P0|R/W| AT24C04 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 8k | 1 | 0 | 1 | 0 | A2| P1| P0|R/W| AT24C08 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 16k | 1 | 0 | 1 | 0 | P2| P1| P0|R/W| AT24C16 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 512k | 1 | 0 | 1 | 0 | A2| A1| A0|R/W| AT24C512 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 1M | 1 | 0 | 1 | 0 | A2| A1| P0|R/W| AT24C1024 +---+---+---+---+---+---+---+---+ P0,P1,P2 - Page Address */ #define AT24_CMD_READ ( 0xA1 ) #define AT24_CMD_WRITE ( 0xA0 ) #define AT24_CHIP_SIZE ( 0x100 ) #define AT24_PAGE_SIZE ( 0x08 ) #define AT24_WRITE_TIMEOUT ( 50 ) #define AT24_PAGE_MASK ( AT24_PAGE_SIZE-1 ) #define AT24_PAGE_COUNT ( AT24_CHIP_SIZE/AT24_PAGE_SIZE ) unsigned int AT24_Init(void); void AT24_ReadMemory(unsigned int dwAddr, unsigned int dwSize, unsigned char * Memory); void AT24_WriteMemory(unsigned int dwAddr, unsigned int dwSize, unsigned char * Memory); #endif /*__AT24_H*/
#include "AT24.h" #include "hw_eeprom_addr.h" unsigned int AT24_Init(void) { #if ( 1 ) unsigned int TestValue; unsigned int i = 0; do { TestValue = 0xAA; AT24_ReadMemory(EEPROM_ADDR_TEST_UNIT, 1, (unsigned char *)&TestValue); if ( ( i > 0 ) || ( TestValue == 0x55 ) ) break; AT24_WriteMemory(EEPROM_ADDR_TEST_UNIT, 1, (unsigned char *)&TestValue); i++; } while (1); return ( TestValue == 0x55 ); #else unsigned int TestValue; TestValue = 0xAA; AT24_ReadMemory(EEPROM_ADDR_TEST_UNIT, 1, &TestValue); if ( TestValue != 0x55 ) { TestValue = 0x55; AT24_WriteMemory(EEPROM_ADDR_TEST_UNIT, 1, &TestValue); TestValue = 0xAA; AT24_ReadMemory(EEPROM_ADDR_TEST_UNIT, 1, &TestValue); } return ( TestValue == 0x55 ); #endif } // only for UserZone 0..2 void AT24_ReadMemory(unsigned int dwAddr, unsigned int dwSize, unsigned char * Memory) { //memset( Memory, 0xFF, dwSize ); if ( dwAddr + dwSize > AT24_CHIP_SIZE ) return; #if ( AT24_CHIP_SIZE > 0x0800 ) // AT24C32 > 2048 Bytes #else // AT24C16 : 2048 Bytes : P2:P1:P0:ADDR // Write Address HW_TWI_Start( HW_TWI_AT24 ); HW_TWI_SendByte(HW_TWI_AT24, AT24_CMD_WRITE | ( (dwAddr>>8) << 1 ) ); if ( HW_TWI_ReadACK( HW_TWI_AT24 ) == HW_TWI_NACK ) { HW_TWI_Stop( HW_TWI_AT24 ); return; } HW_TWI_SendByte(HW_TWI_AT24, dwAddr ); HW_TWI_ReadACK( HW_TWI_AT24 ); // READ Data HW_TWI_Start( HW_TWI_AT24 ); HW_TWI_SendByte(HW_TWI_AT24, AT24_CMD_READ | ( (dwAddr>>8) << 1 ) ); HW_TWI_ReadACK( HW_TWI_AT24 ); while ( dwSize ) { *Memory = HW_TWI_ReceiveByte ( HW_TWI_AT24 ); if ( dwSize == 1 ) HW_TWI_SendACK( HW_TWI_AT24, HW_TWI_NACK ); else HW_TWI_SendACK( HW_TWI_AT24, HW_TWI_ACK ); Memory++; dwSize--; } HW_TWI_Stop( HW_TWI_AT24 ); #endif } void AT24_WritePage(unsigned int dwAddr, unsigned int dwSize, unsigned char * Memory) { #if ( AT24_CHIP_SIZE > 0x0800 ) // AT24C32 > 2048 Bytes #else // AT24C16 : 2048 Bytes : P2:P1:P0:ADDR HW_TWI_Start( HW_TWI_AT24 ); HW_TWI_SendByte(HW_TWI_AT24, AT24_CMD_WRITE | ( (dwAddr>>8) << 1 ) ); if ( HW_TWI_ReadACK( HW_TWI_AT24 ) == HW_TWI_NACK ) { HW_TWI_Stop( HW_TWI_AT24 ); return; } HW_TWI_SendByte(HW_TWI_AT24, dwAddr ); HW_TWI_ReadACK( HW_TWI_AT24 ); while ( dwSize ) { HW_TWI_SendByte(HW_TWI_AT24, *Memory ); HW_TWI_ReadACK( HW_TWI_AT24 ); Memory++; dwSize--; } HW_TWI_Stop( HW_TWI_AT24 ); // Poll Ack from eeprom HW_TWI_WaitComplete(HW_TWI_AT24, AT24_CMD_WRITE | ( (dwAddr>>8) << 1 ), AT24_WRITE_TIMEOUT); #endif } /* When the word address, internally generated, reaches the page boundary, the following byte is placed at the beginning of the same page. If more than eight (1K/2K) or sixteen (4K, 8K, 16K) data words are transmitted to the EEPROM, the data word address will roll over and previous data will be overwritten. */ void AT24_WriteMemory(unsigned int dwAddr, unsigned int dwSize, unsigned char * Memory) { unsigned int dwSizeInPage; if ( dwAddr + dwSize > AT24_CHIP_SIZE ) return; while ( dwSize > 0 ) { dwSizeInPage = AT24_PAGE_SIZE - ( dwAddr & (AT24_PAGE_SIZE-1) ); if ( dwSizeInPage > dwSize ) dwSizeInPage = dwSize; AT24_WritePage(dwAddr, dwSizeInPage, Memory); dwSize -= dwSizeInPage; Memory += dwSizeInPage; dwAddr += dwSizeInPage; // now it must be page alignment } }