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

24LC256.c multi page and multi chip write

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



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

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

24LC256.c multi page and multi chip write
PostPosted: Thu Jun 04, 2009 10:43 am     Reply with quote

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);
}

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