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

External EEPROM - Simple program anyone

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 10, 2003 1:55 pm     Reply with quote

Here is a schematic. Make sure you have the pullup resistors as
shown. Vcc should be +5 volts. The SCL pin on the 24LC256 should
be connected to Pin C3 on your PIC. The SDA pin goes to Pin C4.




Here is a test program. I know it works, because I ran it just now
on my demo board. Just wire your board to match the schematic,
and the instructions above, and then run this program.

This program is for a 16F877, so you'll have to change the #include
line. The crystal frequency below, is 4 MHz. If you're using a
different freq, then change the #use delay line. Also if your crystal
is faster than 4 MHz, you should change the #fuse from XT to HS.

To see the output messages of this program, you'll need a terminal
window on your PC, running at 9600 baud. And, of course a RS232
cable between the PC and your demo board.

Code:
// 24lc256.c -- Test program for the 24LC256 (32kb) eeprom from Microchip.

//-------------------------------------------------------------------------
// INCLUDE FILES

#include <16F877.h>
#device *=16

//------------------------------------------------------------------------
// DEFINES

#define EEPROM_PAGE_LEN     64           // Page length in bytes
#define EEPROM_PAGE_COUNT  512           // Nunber of pages in eeprom
#define EEPROM_I2C_WRITE_ADDR  0xA0
#define EEPROM_I2C_READ_ADDR   0xA1

//---------------------------------------------------------------------------
// COMPILER DIRECTIVES and HARDWARE CONFIGURATION

#fuses XT, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use Delay(Clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)     // Software i2c
//#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW)   // Hardware i2c
#zero_ram

//--------------------------------------------------------------------------
// GLOBALS

char random_byte;
char page_write_buffer[EEPROM_PAGE_LEN];
char page_read_buffer[EEPROM_PAGE_LEN];

//---------------------------------------------------------------------------
// FUNCTION PROTOTYPES

void write_eeprom_byte(long addr, char data);
char read_eeprom_byte(long addr);
void write_eeprom_block(long addr, char block_len, char* in_buffer);
void read_eeprom_block(long addr, char block_len, char* out_buffer);
void erase_eeprom_page(long page);
void erase_eeprom(void);
void power_up_init(void);
char rand(void);
void srand(char seed);
void fill_page_buffer(char *ptr, char count);
//=========================================

void main()
{
char i;
long addr;
char value_read;
char random_value;
long page;

power_up_init();

printf("Erasing\n\r");
erase_eeprom();

// Verify that the eeprom was erased.
printf("\n\rVerify erase\n\r");

addr = 0;

for(page = 0; page < EEPROM_PAGE_COUNT; page++)
   {
    read_eeprom_block(addr, EEPROM_PAGE_LEN, page_read_buffer);

    for(i = 0; i < EEPROM_PAGE_LEN; i++)
       {
        value_read = page_read_buffer[i];

        if(value_read != 0)
           printf("addr %lx wrote %02x  read %02x\n\r", addr +i, 0, value_read);
       }

    addr += EEPROM_PAGE_LEN;

    // Display an activity dot every 8 pages.
    if((page % 8) == 0)
       putc('.');

   }

//---------------------------------------------
// Fill the entire EEPROM with random data.

printf("\n\rWriting\n\r");

// Init the random seed.
srand(0x55);

addr = 0;

for(page = 0; page < EEPROM_PAGE_COUNT; page++)
   {
    fill_page_buffer(page_write_buffer, EEPROM_PAGE_LEN);

    write_eeprom_block(addr, EEPROM_PAGE_LEN, page_write_buffer);
    addr += EEPROM_PAGE_LEN;

    // Display an activity dot every 8 pages.
    if((page % 8) == 0)
       putc('.');

   }

//-----------------------------------
// Read the data back and verify it.

printf("\n\rReading\n\r");

// Reset the randomizer.
srand(0x55);

addr = 0;

for(page = 0; page < EEPROM_PAGE_COUNT; page++)
   {
    fill_page_buffer(page_write_buffer, EEPROM_PAGE_LEN);
    read_eeprom_block(addr, EEPROM_PAGE_LEN, page_read_buffer);

    for(i = 0; i < EEPROM_PAGE_LEN; i++)
       {
        random_value = page_write_buffer[i];
        value_read = page_read_buffer[i];

        if(value_read != random_value)
           printf("addr %lx wrote %02x  read %02x\n\r", addr +i, random_value, value_read);
       }

    addr += EEPROM_PAGE_LEN;

    // Display an activity dot every 8 pages.
    if((page % 8) == 0)
       putc('.');

   }



printf("\n\rTest Done\n\r");

while(1);

}

//=======================================

void power_up_init(void)
{
output_float(PIN_C3);    // Set both i2c pins as inputs
output_float(PIN_C4);

output_float(PIN_C7);    // Set RS-232 Rx pin as an input
output_high(PIN_C6);     // Set RS-232 Tx pin as an output
}

//-----------------------------------------------------------------------------
void write_eeprom_byte(long addr, char data)
{
i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);
i2c_write(data);
i2c_stop();
delay_ms(6);  // Wait enough time for the write to occur
}

//-------------------------------------------------------------------------------
// This will write a block of bytes.  The length can be from 1 to the page length.
// If the starting address and count are such that the bytes extend past the page,
// then the eeprom will internally wrap the address ptr around, and overwrite the
// bytes at the start of the page.

void write_eeprom_block(long addr, char block_len, char* in_buffer)
{
char i;

if(block_len == 0)
   return;

i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);

for(i = 0; i < block_len; i++)
   {
    i2c_write(*in_buffer++);
   }

i2c_stop();
delay_ms(6);  // Wait enough time for the write to occur
}

//-------------------------------------------------------------------------------
char read_eeprom_byte(long addr)
{
char data;
i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);

i2c_start();
i2c_write(EEPROM_I2C_READ_ADDR);

data = i2c_read(0);
i2c_stop();

return(data);
}

//-----------------------------------------------------------------------------
void read_eeprom_block(long addr, char block_len, char* out_buffer)
{
char i;
char count;

if(block_len == 0)
   return;

i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);

i2c_start();
i2c_write(EEPROM_I2C_READ_ADDR);

count = block_len -1;
for(i = 0; i < count; i++)
   {
    *out_buffer++ = i2c_read();
   }

*out_buffer = i2c_read(0);   // Last byte read must have no ACK

i2c_stop();

}
//--------------------------------------------------------------------------------
// Erase one page (64 bytes) of the eeprom.  The page can be from 0 to 511.
// The page is filled with zeros.

void erase_eeprom_page(long page)
{
char i;
long addr;

addr = (page << 6);     // Convert page address to a byte address (multiply by 64)

i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);

for(i = 0; i < EEPROM_PAGE_LEN; i++)
   {
    i2c_write(0);                // Fill page with all zeros
   }

i2c_stop();
delay_ms(6);
}

//--------------------------------------------------------------------------------
// Erase the entire eeprom by filling it with zeros.

void erase_eeprom(void)
{
long page;

for(page = 0; page < EEPROM_PAGE_COUNT; page++)
   {
    erase_eeprom_page(page);

    // Display an activity dot every 8 pages.
    if((page % 8) == 0)
     {
      putc('.');
     }

   }

}

//-----------------------------------------------------------------------------
// This function returns a random number.
// The sequence repeats after 255 calls.
// The srand() function should be called once, before starting
// a series of calls to this function.
//
// To create a random number, we calculate the parity on
// a byte that has been ANDed with 0xb4.  We then shift that
// parity bit into the LSB of the byte.

char rand(void)
{
char sum;

sum = 0;

// This calculates parity on the selected bits (mask = 0xb4).
if(random_byte & 0x80)
   sum = 1;

if(random_byte & 0x20)
   sum ^= 1;

if(random_byte & 0x10)
   sum ^= 1;

if(random_byte & 0x04)
   sum ^= 1;

random_byte <<= 1;

random_byte |= sum;

return(random_byte);
}


//------------------------------------------------------------------------------
// Set the randomizer's seed value.

void srand(char seed)
{
random_byte = seed;
}

//-------------------------------------------------------------------------------
// Fill the page buffer with random data.

void fill_page_buffer(char *ptr, char count)
{
char i;

for(i = 0; i < count; i++)
   {
    *ptr++ = rand();
   }
}

// end of program
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

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

PostPosted: Wed Dec 10, 2003 2:27 pm     Reply with quote

I will first try it on the picdem 2 plus board, the demo board from microchip, if I get in to any problems I will write back if thats OK.

Sorry to sound like a thicky, am i correct in thinking the random number being created is the number being put into the memory location so I could change iot to put FF in every address or 00, it happens that in this program a random value is created?

So you initially get a set of bytes together (a page) in a temporary buffer (fill_page_buffer), once you have filled the page you store the page to External EEprom (write_eeprom_block) and then use that buffer again for the next page of data and so on, uintil you have reached the maximum number of pages.


why is it
write_eeprom_block(addr, EEPROM_PAGE_LEN, page_write_buffer);
and not
write_eeprom_block(addr, EEPROM_PAGE_LEN, fill_write_buffer);

and

in the READ back section why are you using the fill_page_buffer again. Actually I am not entirely sure about the read section of main at all, a bit more detailled description would be really useful

Thanks for your help and sorry about this, I haven't felt this stupid since kindergarden

Shocked
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 10, 2003 2:57 pm     Reply with quote

Quote:
Am I correct in thinking the random number being created is the number being put into the memory location so I could change it to put FF in every address or 00, it happens that in this program a random value is created?

Using random numbers is a more thorough way to test the EEPROM.
If you write the same thing to every location, then how do know if
there is a stuck or shorted address line inside the EEPROM ?

Granted, the random numbers don't test every bit. You might want
to combine the random number test with another test that first writes
0x55 and reads it back, then writes 0xAA on the next pass. This would
test all bits, and check for shorts between adjacent bits.

Quote:
So you initially get a set of bytes together (a page) in a temporary buffer (fill_page_buffer), once you have filled the page you store the page to External EEprom (write_eeprom_block) and then use that buffer again for the next page of data and so on, uintil you have reached the maximum number of pages.

No. A new buffer of random data is created for each page.
The write data is diffferent for each EEPROM page. Doing it this
way makes the test much more robust. What if the paging mechanism
inside the EEPROM was defective ? If you wrote the same data to
each page, you would never know it. The EEPROM could be broken
and only have one page. You would never know it, unless you do it
my way, or some similar way.

Quote:
why is it
write_eeprom_block(addr, EEPROM_PAGE_LEN, page_write_buffer);
and not
write_eeprom_block(addr, EEPROM_PAGE_LEN, fill_write_buffer);

I'm not sure what you're asking here. "fill_write_buffer" is the name
of a function, not an array. The 3rd parameter required for the
write_eeprom_block() function is the address of the write data array.

Quote:
In the READ back section why are you using the fill_page_buffer again.

Each page of the EEPROM gets different random data written to it.
So, when I read back the EEPROM, and I want to compare it to the
original data that was written to it, I must re-calculate that data.
So, that's why I make a call the the fill_page_buffer() function each time.

On a PC, it would be easy to have a 32KB buffer. Then I wouldn't have
to re-calculate the data for each page. But on a PIC, I much less RAM.
So, I have to do it this way.
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