treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
24LC256.c multi page and multi chip write |
Posted: Thu Jun 04, 2009 10:43 am |
|
|
This driver is designed to look at multiple I2C chips as one large address space. And the multi-write driver spans the 64 byte boundary and the chip boundary.
Code: | ///////////////////////////////////////////////////////////////////////////
// Name : 24CLC256.c //
// Author : Timothy Reitmeyer //
// Date : 06/04/2009 //
// Version: 0.1 //
///////////////////////////////////////////////////////////////////////////
// Library for a Microchip 24LC256 Serial EEPROM, 32768 int8 memory ////
// init_ext_eeprom(); Call before the other functions are used ////
// write_ext_eeprom(a,d); Write the int8 d to the address a ////
// d = read_ext_eeprom(a); Read the int8 d from the address a ////
// multi_write_ext_eeprom(a,char *d,size);//can cross page/chip boundary////
// multi_read_ext_eeprom(a,char *d,size);//can cross page/chip boundary ////
// The main program may define EEPROM_SDA, EEPROM_SCL to override ////
// 2^15=32768 address space. 2^3=8 3 bits for 8 chips ////
// For a total of 18 bits (using int32) ////
///////////////////////////////////////////////////////////////////////////
//((very similar to my fram driver))
// 8 chips, 32768 BYTES each chip
// start addr's 0,32768,65536,98304,131072,163840,196608,229376
// Page write boundary at 64 bytes
// microchip note: Page write operations are limited to writing
// bytes within a single physical page,
// regardless of the number of bytes actually
// being written. so... don't check the number of bytes written, check if the
// address is on a 64 byte boundary
#ifndef EEPROM_SDA
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#endif
#use I2C(MASTER,SDA=EEPROM_SDA,SCL=EEPROM_SCL,FORCE_HW,FAST=400000,RESTART_WDT)
//#use I2C(MASTER,SDA=EEPROM_SDA,SCL=EEPROM_SCL,FORCE_HW,RESTART_WDT) //start with slow
#define EEPROM_ADDRESS int32
#define EEPROM_PAGE_BDY 64 //can do page write at 64 byte boundrys
#define EEPROM_SIZE 32768
#ifndef EEPROM_CHIPS
#define EEPROM_CHIPS 4
#endif
#define EEPROM_MAX_ADDRESS (EEPROM_SIZE*EEPROM_CHIPS)-1 //4 chips 0,1,2,3
//#define hi(x) (*(&x+1)) //data held at addr of x + 1
#define hi(x) (*((int8*)&x+1)) //new Ttelmah future proof
#define lo(x) (*(&x)) //data held at addr of x
//======================init_ext_eeprom===========================//
void init_ext_eeprom(){
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
//======================read_ext_eeprom===========================//
int8 read_ext_eeprom(int32 address) {
int8 data;
// if(address>EEPROM_MAX_ADDRESS)
// {
// bit_set(ERRORS,4);
// //fprintf(DEBUG,"ERROR address too big!\n\r%lu\n\r",address);
// }
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
data=i2c_read(0);
i2c_stop();
return(data);
}
//======================multi_read_ext_eeprom===========================//
//start addr 0,32768,65536,98304,131072,163840,196608,229376
BOOLEAN multi_read_ext_eeprom(int32 address,char *data,int32 size){
int1 flag_first_one=TRUE;
//fprintf(DEBUG,"-mr-");
for(;size;data++,size--,address++)
{
if(address%EEPROM_SIZE==0 || flag_first_one)
{
if (flag_first_one) flag_first_one=FALSE;
//fprintf(DEBUG,"sending slave address=%lu\n\r",address);
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
}
if((address+1)%EEPROM_SIZE && size!=1)
{
*data=i2c_read(1);//The ack will put next data on bus
//fprintf(DEBUG,"read with ack %lu=%u\n\r",address,*data);
}
else
{
*data=i2c_read(0);//No ack on last read of chip
//fprintf(DEBUG,"read without ack %lu=%u\n\r",address,*data);
//fprintf(DEBUG,"I2c stop\n\r");
i2c_stop();
}
}
//fprintf(DEBUG,"-mr- done!\n\r");
return(TRUE);
}
//======================write_ext_eeprom===========================//
void write_ext_eeprom(int32 address,int8 data)
{
int1 status;
// if(address>EEPROM_MAX_ADDRESS)
// {
// bit_set(ERRORS,4);
// //fprintf(DEBUG,"ERROR address too big!\n\r%lu\n\r",address);
// }
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);
i2c_write(hi(address));
i2c_write(lo(address));
i2c_write(data);
i2c_stop();
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
while(status==1)
{
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
}
i2c_stop();
}
//======================multi_write_ext_eeprom===========================//
BOOLEAN multi_write_ext_eeprom(int32 address,char *data,int32 size)
{
int1 status, FirstTime=TRUE;
for(;size;data++,size--,address++)
{
//fprintf(DEBUG,"a=%lu s=%lu\n\r",address,size);
if(address%EEPROM_PAGE_BDY==0 || address%EEPROM_SIZE==0 || FirstTime)
//if(address%EEPROM_SIZE==0 || FirstTime)
{
//fprintf(DEBUG,"start %lu\n\r",address);
if(FirstTime) FirstTime=FALSE;
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);
i2c_write(hi(address));
i2c_write(lo(address));
}
i2c_write(*data);
if((address+1)%EEPROM_PAGE_BDY==0 || size-1==0)
{
//fprintf(DEBUG,"stop/pg %lu\n\r",address);
i2c_stop();
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
while(status==1)
{
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
}
i2c_stop();
}
}
return(TRUE);
}
BOOLEAN clr_ext_eeprom(int32 address,int32 size,char data) //fill/clear seep with a given int8
{
int1 status, FirstTime=TRUE;
for(;size;size--,address++)
{
//fprintf(DEBUG,"a=%lu s=%lu\n\r",address,size);
if(address%EEPROM_PAGE_BDY==0 || address%EEPROM_SIZE==0 || FirstTime)
//if(address%EEPROM_SIZE==0 || FirstTime)
{
//fprintf(DEBUG,"start %lu\n\r",address);
if(FirstTime) FirstTime=FALSE;
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);
i2c_write(hi(address));
i2c_write(lo(address));
}
i2c_write(data);
if((address+1)%EEPROM_PAGE_BDY==0 || size-1==0)
{
//fprintf(DEBUG,"pg %lu\n\r",address);
i2c_stop();
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
while(status==1)
{
i2c_start();
status= i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
}
i2c_stop();
}
}
return(TRUE);
}
////======================clr_ext_eeprom===========================//
//BOOLEAN clr_ext_eeprom(int32 address,int32 size,char data) //fill/clear seep with a given int8
//{
// int32 start_size;
// //fprintf(DEBUG,"-c-\n\r");
// start_size=size;
// i2c_start();
// i2c_write((0xA0|(int8)(address>>14))&0xFE);
// i2c_write(hi(address));
// i2c_write(lo(address));
// for(;size;size--,address++){
// if(address>EEPROM_MAX_ADDRESS){
// //fprintf(DEBUG,"ERROR address too big!\n\r%lu\n\r",address);
// bit_set(ERRORS,4);
// }
// if(address%EEPROM_SIZE==0 && size!=start_size && size!=1){
// //fprintf(DEBUG,"chip boundary -c- addr=%lu\n\r",address);
// //reissue I2C for next chip
// i2c_stop();
// output_float(EEPROM_SCL);
// output_float(EEPROM_SDA);
// i2c_start();
// i2c_write((0xA0|(int8)(address>>14))&0xFE);
// i2c_write(hi(address));
// i2c_write(lo(address));
// }
// i2c_write(data);
// }
// i2c_stop();
// return(TRUE);
//}
//=======================eeprom_chksum============================//
int8 eeprom_chksum(int32 address,int32 size)
{
int8 chksum=0;
int32 start_size;
//fprintf(DEBUG,"-cs-\n\r");
if(size==0){
chksum=0;
return(chksum);
}
start_size=size;
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
for(;size;size--,address++)
{
restart_wdt();
// if(address>EEPROM_MAX_ADDRESS)
// {
// bit_set(ERRORS,4);
// //fprintf(DEBUG,"ERROR address too big!\n\r%lu\n\r",address);
// }
if(size==1){
//fprintf(DEBUG,"last addr=%lu\n\r",address);
chksum+=i2c_read(0);//last read requires no ack
i2c_stop();
return(chksum);
}
if(address%(EEPROM_SIZE-1)==0 && size!=start_size)
{
//fprintf(DEBUG,"chip boundary addr=%lu\n\r",address);
chksum+=i2c_read(0);//last read requires no ack
i2c_stop();
//fprintf(DEBUG,"-cs-noack-%lu=%u\n\r",address,chksum);
size--;address++;
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
}
chksum+=i2c_read(1);//The ack will put next data on bus
//fprintf(DEBUG,"-cs-%lu=%u\n\r",address,chksum);
}
//fprintf(DEBUG,"wrong exit\n\r");
}
|
Little test program, change array size to bigger than 64 and address
to cross chips ect..
Code: | //05/14/2009 9:54AM Single 24LC256 EEPROM
//05/15/2009 3:39PM multi-read
#define FIRM_MAJOR (int8) 'i'
#define FIRM_MINOR (int8) 14
#include <18F4525.h>
#fuses hs,nowdt,noprotect,nolvp,put
#use delay(clock=18432000,RESTART_WDT)
#use rs232(baud=19200,xmit=PIN_D7,invert,stream=DEBUG)
#case
#zero_ram
#define HARD_MAJOR (int8) 0
#define HARD_MINOR (int8) 0 //KPD315
#define BEEP PIN_C0
#define RELAY PIN_C1
#
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#define EEPROM_CHIPS 4
//start addrs 0,32768,65536,98304,(((131072)))
#define AddrVal 125
int8 ERRORS;
#include "Microchip_24LC256.C"
#include <STDLIB.H>
void init(void);
void main(void)
{
int8 i,tmp;
int8 w[10];//1024 byte write array with random data
int8 r[10];//1024 byte empty array for read data
int32 addr;//array is written to and read from address
int32 cnt;//counter for setting up array
int8 inside_chip;//must loop 32 times the 1024 arrray to fill a chip
int8 chip_cnt;//must loop 4 times. Once for each FRAM chip
init();
init_ext_eeprom();
addr=AddrVal;
for (cnt=0;cnt<sizeof(w);cnt++)w[cnt]=rand();//fill the array with rand data
multi_write_ext_eeprom(addr,w,sizeof(w));//write the array
//for(addr=AddrVal,cnt=0;cnt<sizeof(w);cnt++,addr++)write_ext_eeprom(addr,w[cnt]);//write the array
addr=AddrVal;
multi_read_ext_eeprom(addr,r,sizeof(r));//read the array
for (cnt=0;cnt<sizeof(w);cnt++)//check the array
if(r[cnt]!=w[cnt])
fprintf(DEBUG,"\w\rr=%03u w=%03u c=%lu\n\r",r[cnt],w[cnt],cnt);
fprintf(DEBUG,"\n\rDone!\n\r");
while(1);
}
|
|
|