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

Ramtron FM24C256 FRAM

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
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

Ramtron FM24C256 FRAM
PostPosted: Fri Aug 05, 2005 7:47 am     Reply with quote

PCH3.230/PIC18F452 /16Mhz.
Does anyone have a good working driver for FM24C256 That can do multi-write accross chips? I took 24256 driver and have mod'd it do FM24C256 multi-write. But what is best tech to find last write of chip, reissue I2C command, and continue writing?
Code:

//////////////////////////////////////////////////////////////////
//Library for a Ramtron FM24C256 FRAM 32768 byte serial memory////
//init_fram();    Call before the other functions are used    ////
//write_fram(a,d);  Write the byte d to the address a         ////
//d = read_fram(a);  Read the byte d from the address a       ////
//multi_write_fram(a,char *d,size);//can't cross chip boundry ////
//multi_read_fram(a,char *d,size);//can't cross chip boundry  ////
//The main program may define FRAM_SDA, FRAM_SCL to override  ////
// 2^15=32768 address space.  2^3=8   3 bits for 8 chips      ////
// For a total of 18 bits  (using int32)
//////////////////////////////////////////////////////////////////
#ifndef FRAM_SDA
  #define FRAM_SDA  PIN_C4
  #define FRAM_SCL  PIN_C3
#endif
//#use I2C(MASTER,SDA=FRAM_SDA,SCL=FRAM_SCL,FORCE_HW,RESTART_WDT)
//fast is 3X faster
#use I2C(MASTER,SDA=FRAM_SDA,SCL=FRAM_SCL,FORCE_HW,FAST,RESTART_WDT)
#define FRAM_ADDRESS int32
#define FRAM_SIZE    32768
#define FRAM_CHIPS   1
#define FRAM_MAX_ADDRESS FRAM_SIZE * FRAM_CHIPS //4 chips 0,1,2,3
#define hi(x)  (*(&x+1))  //data held at addr of x + 1
#define lo(x)  (*(&x))    //data held at addr of x
//======================init_fram===========================//
void init_fram(){
  output_float(FRAM_SCL);
  output_float(FRAM_SDA);
}
//======================write_fram===========================//
void write_fram(int32 address,int8 data){
  short int status;
  i2c_start();
  i2c_write((0xA0|(BYTE)(address>>14))&0xFE);
  i2c_write(hi(address));
  i2c_write(lo(address));
  i2c_write(data);
  i2c_stop();
}
//======================read_fram===========================//
BYTE read_fram(int32 address) {
  BYTE data;
  i2c_start();
  i2c_write(0xA0);
  i2c_write(hi(address));
  i2c_write(lo(address));
  i2c_start();
  i2c_write(0xA1);//fram read
  data=i2c_read(0);
  i2c_stop();
  return(data);
}
//======================clr_fram===========================//
BOOLEAN clr_fram(char data)  //fill/clear fram with a given int8
{
  int32 address=0;
  int16 size=FRAM_MAX_ADDRESS;
  i2c_start();
  i2c_write((0xA0|(BYTE)(address>>14))&0xFE);
  i2c_write(hi(address));
  i2c_write(lo(address));
  for(;size;size--){
    i2c_write(data);
  }
  i2c_stop();
  return(TRUE);
}
//======================multi_write_fram===========================//
//does not handle chip to chip multi-write
BOOLEAN multi_write_fram(int32 address,char *data,int16 size)
{
  i2c_start();
  i2c_write((0xA0|(BYTE)(address>>14))&0xFE);
  i2c_write(hi(address));
  i2c_write(lo(address));
  for(;size;data++,size--){
    i2c_write(*data);
  }
  i2c_stop();
  return(TRUE);
}

//======================multi_read_fram===========================//
//does not handle chip to chip multi-read
BOOLEAN multi_read_fram(int32 address,char *data,int16 size){
  i2c_start();
  i2c_write(0xA0);
  i2c_write(hi(address));
  i2c_write(lo(address));
  i2c_start();
  i2c_write(0xA1);//fram read
  size--;//reducing by 1, the for loop does all but the last read
  for(;size-1;data++,size--)
  {
    *data=i2c_read(1);//The ack will put next data on bus
  }
  //fprintf(DEBUG,"doing last read s=%lu a=%lu\n\r",size,address);
  //data++; //last read requires no ack
  *data=i2c_read(0);//last read requires no ack
  i2c_stop();
  return(TRUE);
}


I was thinking of if boundry addres and not first and not last
//if(address%FRAM_SIZE==0 && size!=start_size && size!=1){reisue I2C for next chip
Only thing, on read I must not ack the last(previous one)
Guest








PostPosted: Fri Aug 05, 2005 8:59 pm     Reply with quote

i have one here... i'll post it in this forum later...
Guest








PostPosted: Sat Aug 06, 2005 6:06 am     Reply with quote

Here's my code for FRAM FM24C256 which can write accross chip boundaries provided that you are accessing the chip in multiple of 2.

Hope this would help.


Code:


// Using PIC18F452 at 20MHz Clock

/////////////////////////// MCU Registers /////////////////////////////////////

#byte SSPSTAT    = 0xFC7               // MSSP Status Register for I2C Mode
#byte SSPCON1    = 0xFC6               // MSSP Control Register 1 for I2C Mode
#byte SSPCON2    = 0xFC5               // MSSP Control Register 2 for I2C Mode
#byte SSPBUF     = 0xFC9               // SSP Receive Buffer/Transmit Register
#byte SSPADD     = 0xFC8               // SSP Baud Rate Register in I2C Master
#byte PIR1       = 0xF9E               // Peripheral Interrupt Request Register

// Bits of SSPSTAT
#bit  SSP_SMP    = 0xFC7.7             // =1 for 1MHz I2C mode
#bit  SSP_CKE    = 0xFC7.6             // =1 for enable SMBus

// Bits of SSPCON1
#bit SSP_SSPEN   = 0xFC6.5             // =1 for enable serial (I2C mode)
#bit SSP_SSPM3   = 0xFC6.3             // SSP select bits
#bit SSP_SSPM2   = 0xFC6.2
#bit SSP_SSPM1   = 0xFC6.1
#bit SSP_SSPM0   = 0xFC6.0

// Bits of SSPCON2
#bit  SSP_ACKDT  = 0xFC5.5             // =1 for no ACK or 0 for ACK
#bit  SSP_ACKEN  = 0xFC5.4             // =1 initiate ACK sequence
#bit  SSP_RCEN   = 0xFC5.3             // =1 for enable rx mode I2C
#bit  SSP_PEN    = 0xFC5.2             // =1 for initiate stop condition
#bit  SSP_RSEN   = 0xFC5.1             // =1 for initiate repeated chart
#bit  SSP_SEN    = 0xFC5.0             // =1 for initiate start condition

// Bits of PIR1
#bit SSP_SSPIF   = 0xF9E.3             // =1 for tx/rx is complete


///////////////////////// Defines /////////////////////////////////////////////

#define R_W_MASK           0x04        // R/W register mask
#define SSPIF_MASK         0x08        // SSP interrupt flag register mask

#define FRAM_WR_ADDR       0xA0        // starting FRAM chip write address
#define FRAM_RD_ADDR       0xA1        // starting FRAM chip read address

#define FRAM_SDA           PIN_C4      // I2C data line
#define FRAM_SCL           PIN_C3      // I2C clock line
#define FRAM_WP            PIN_C5      // I2C write protect pin


/////////////////////////////// I2C Routines //////////////////////////////////

// Waits for I2C process to complete
void I2CWait(void)
{
   while (!(PIR1 & SSPIF_MASK));       // Wait for Interrupt
   SSP_SSPIF = 0;                      // bit_clear(PIR1,SSPIF);
}

// Send a char via I2C
void I2CSend(char ch)
{
   SSPBUF = ch;                        // Load DATA to send
   I2CWait();                          // Wait for completion
}

// Receive a char via I2C
char I2CReceive(void)
{
   while (SSPSTAT & R_W_MASK);         // Wait for Transmit to end

   SSP_RCEN = 1;                       // bit_set( SSPCON2, RCEN );
   I2CWait();                          // Wait for data to arrive.
   return(SSPBUF);                     // Return the data
}

// Send an I2C Acknowledge (ACK)
void I2CAck(void)
{
   SSP_ACKDT = 0;                      // bit_clear( SSPCON2, ACKDT );
   SSP_ACKEN = 1;                      // bit_set( SSPCON2, ACKEN );
   I2CWait();                          // Wait for completion
}

// Send an I2C No Acknowledge (NACK)
void I2CNak(void)
{
   SSP_ACKDT = 1;                      // bit_set( SSPCON2, ACKDT );
   SSP_ACKEN = 1;                      // bit_set( SSPCON2, ACKEN );
   I2CWait();                          // Wait for completion
}

// Generate an I2C Start Sequence
void I2CStart(void)
{
   SSP_SEN = 1;                        // bit_set( SSPCON2, SEN );
   I2CWait();                          // Wait for completion
}

// Generate an I2C Restart Sequence
void I2CRestart(void)
{
   SSP_RSEN = 1;                       // bit_set( SSPCON2, RSEN );
   I2CWait();                          // Wait for completion
}

// Generate an I2C Stop Sequence
void I2CStop(void)
{
   SSP_PEN = 1;                        // bit_set( SSPCON2, PEN );
   I2CWait();                          // Wait for completion
}

// Configure the MSSP as an I2C Port for PIC18F452 at 20MHz
// using 1MHz I2C clock
void ConfigureI2C(void)
{
   output_float(FRAM_SCL);             // set I2C clock pin to input
   output_float(FRAM_SDA);             // set I2C data pin to input

   SSP_SSPEN = 1;                      // bit_set( SSPCON1, SSPEN );
   SSP_SSPM3 = 1;                      // bit_set( SSPCON, SSPM3 );
   SSP_SSPM2 = 0;                      // bit_clear( SSPCON, SSPM2 );
   SSP_SSPM1 = 0;                      // bit_clear( SSPCON, SSPM1 );
   SSP_SSPM0 = 0;                      // bit_clear( SSPCON, SSPM0 );

   SSPCON2 = 0;

   SSP_SMP = 0;                        // bit_clear( SSPSTAT, SMP );
   SSP_CKE = 0;                        // bit_clear( SSPSTAT, CKE );

   // Set I2C Speed. The formula is:
   //
   // SSPADD value = (Fosc/(i2c clock speed * 4)) -1
   //
   // Examples:
   //
   // SSPADD values for an Fosc of 8 MHz:
   // *** NOTE: If you run your PIC at a different Fosc, then you
   // *** you need to calculate new values.
   //
   // For an i2c clock of 100 KHz, SSPADD = 19
   // For an i2c clock of 400 KHz, SSPADD = 4
   // For an i2c clock of 1 MHz, SSPADD = 1


   SSPADD = 4;    // 1 MHz i2c clock
   // Disable slew rate control for 1 MHz operation ONLY
   SSP_SMP = 1;                        // bit_set( SSPSTAT, SMP );


   // *** NOTE: Based on my oscilloscope readings, the i2c clock
   // *** speed seems to run a little slower than what the formula says.
   // *** For example, "400 KHz" is really 370 KHz or so.
   // *** "1 MHz" is really running slightly less than that speed.
}

// Write one block/page of 32bytes size to the FM24C256 chip
// with a 32-bit address
void write_fram_block32(int32 uAddress, int8 page, char *data)
{
   unsigned int8 i=0;
   unsigned int8 select=0;

   output_low(FRAM_WP);                // disable write protection

   // Chip select a chip for linear addressing method
   select = FRAM_WR_ADDR | (0xFE & make8(uAddress<<2,2));

   I2CStart();                         // initiate I2C start
   I2CSend(select);                    // send the write chip address
   // send msb first
   I2CSend((char)(0x7F & make8(uAddress,1)));
   // then send lsb
   I2CSend((char)(make8(uAddress,0)));

   for (i=0; i<page; i++){
      I2CSend(*data);                  // send data to FM24C256
      data++;                          // increment data pointer
   }
   I2CStop();                          // initiate I2C stop condition

   output_high(FRAM_WP);               // enable write protection
}

// Write one byte to the FM24C256 Chip
// with a 32-bit address
void write_fram_byte32(int32 uAddress, char data)
{
   unsigned int8 select=0;

   output_low(FRAM_WP);                // disable write protection

   // Chip select a chip for linear addressing method
   select = FRAM_WR_ADDR | (0xFE & make8(uAddress<<2,2));

   I2CStart();                         // initiate I2C start
   I2CSend(select);                    // send the write chip address
   // send msb first
   I2CSend((char)(0x7F & make8(uAddress,1)));
   // then send lsb
   I2CSend((char)(make8(uAddress,0)));

   I2CSend(data);                      // send data to chip
   I2CStop();                          // initiate I2C stop condition

   output_high(FRAM_WP);               // enable write protection
}

// Read one block/page 0f 32bytes size from FM24C256 chip
// with a 32-bit address
void read_fram_block32(int32 uAddress, int8 page, char *data)
{
   unsigned int8 i=0;
   unsigned int8 select=0;

   // Chip select a chip for linear addressing method
   select = FRAM_WR_ADDR | (0xFE & make8(uAddress<<2,2));

   I2CStart();                         // initiate I2C start
   I2CSend(select);                    // send the write chip address
   // send msb first
   I2CSend((char)(0x7F & make8(uAddress,1)));
   // then send lsb
   I2CSend((char)(make8(uAddress,0)));

   I2CRestart();                       // initiate I2C restart
   I2CSend(select | 0x01);             // send the read chip address

   for (i=0; i<(page-1); i++){
      *data = I2CReceive();            // receive data from FRAM chip
      I2CAck();                        // send acknowledge for next char
      data++;                          // increment data pointer
   }

   *data = I2CReceive();               // receive the last data
   I2CNak();                           // send no acknowledge
   I2CStop();                          // initiate I2C stop condition
}

// Read one byte from Ramtron FM24C256 chip
// with a 32-bit address
char read_fram_byte32(int32 uAddress)
{
   unsigned int8 select=0;
   char data;

   // Chip select a chip for linear addressing method
   select = FRAM_WR_ADDR | (0xFE & make8(uAddress<<2,2));

   I2CStart();                         // initiate I2C start
   I2CSend(select);                    // send the write chip address
   // send msb first
   I2CSend((char)(0x7F & make8(uAddress,1)));
   // then send lsb
   I2CSend((char)(make8(uAddress,0)));

   I2CRestart();                       // initiate I2C restart
   I2CSend(select | 0x01);             // send the read chip address

   data = I2CReceive();                // receive data from FRAM
   I2CNak();                           // send no acknowledge
   I2CStop();                          // initiate I2C stop condition
   return(data);                       // return data
}


treitmey



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

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

PostPosted: Mon Aug 08, 2005 8:01 am     Reply with quote

Thanks
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion 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