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 support@ccsinfo.com

Read and Write _ext_eeprom works randomly

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Kari Leino
Guest







Read and Write _ext_eeprom works randomly
PostPosted: Sat Oct 26, 2002 10:44 am     Reply with quote

What is wrong in this code? It is only for testing external eeprom.
// Eeprom test 26.10.2002
// 24LC256 has 1k from SDA and SCL to +5V

#include "c:\ohjelm~1\picc\devices\16F873.H"
#byte PORTA = 5
#byte PORTB = 6
#byte PORTC = 7
#bit LED = PORTA.0
#use delay(clock=4000000, RESTART_WDT)
#fuses XT,WDT,PUT,PROTECT,NOLVP,NOBROWNOUT
#use rs232(baud=9600, xmit=PIN_A1, rcv=PIN_A2)
#include "c:\ohjelm~1\picc\drivers\24256.C"

void main (void)
{
int out=0;
int i=0;
long int address=0;
setup_counters (RTCC_INTERNAL, WDT_2304MS);
setup_adc_ports(NO_ANALOGS);
set_tris_a(0b00000100);
set_tris_b(0b00000000);
set_tris_c(0b00011000);
delay_ms(1);
init_ext_eeprom();
//LED=0;
//delay_ms(500);
LED=1;
while(1)
{
i=0;
address=0;
while(i<255)
{
write_ext_eeprom(address,i);
//restart_wdt();
address++;
i++;
}
address=0;
i=0;
while(i<255)
{
out=read_ext_eeprom(address);
printf("IN \%02x, OUT \%02x\r\n",i,out);
//restart_wdt();
address++;
i++;
}
LED=0;
delay_ms(10000);
LED=1;
}
} //main end

This is snipplet from terminal screen:
IN 00, OUT 55
IN 01, OUT 29
IN 02, OUT 29
IN 03, OUT 29
IN 04, OUT 2d
IN 05, OUT 2d
IN 06, OUT 2e
IN 07, OUT 2f
IN 08, OUT 29
IN 09, OUT 59
IN 0a, OUT 29
IN 0b, OUT 29
IN 0c, OUT 2d
IN 0d, OUT 5d
IN 0e, OUT 5e
IN 0f, OUT 5f
IN 10, OUT 35

If I take new Eeprom it works fine few times(IN and OUT are same), but then output becomes crazy. Only 3-4 times is enough. I can read and program Eeproms with my Galep-4 programmer, so they seems be ok. If I read Eeprom programmed with my example code with Galep-4 I can see few errors which have come on writing phase. Most of errors are coming in read sequence.
Eeprom is near Pic (10mm).
PCW version 3.082
Please help.
Kari
___________________________
This message was ported from CCS's old forum
Original Post ID: 8206
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: Read and Write _ext_eeprom works randomly
PostPosted: Sat Oct 26, 2002 11:55 am     Reply with quote

I do not see where you defined the EEPROM_SDA & EEPROM_SCL pins. If they are not defined, the following defaults are used (unless you changed the 24256.h file).

#define EEPROM_SDA PIN_B1
#define EEPROM_SCL PIN_B0

You probably want:

#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3

Also note that your program is an endless loop writing to an eeprom. This is a bad thing since they will eventually where out after 100K-1M writes. Refer to the datasheet for the eeprom to get the typical erase/write cycles.

Mark

:=What is wrong in this code? It is only for testing external eeprom.
:=// Eeprom test 26.10.2002
:=// 24LC256 has 1k from SDA and SCL to +5V
:=
:=#include "c:\ohjelm~1\picc\devices\16F873.H"
:=#byte PORTA = 5
:=#byte PORTB = 6
:=#byte PORTC = 7
:=#bit LED = PORTA.0
:=#use delay(clock=4000000, RESTART_WDT)
:=#fuses XT,WDT,PUT,PROTECT,NOLVP,NOBROWNOUT
:=#use rs232(baud=9600, xmit=PIN_A1, rcv=PIN_A2)
:=#include "c:\ohjelm~1\picc\drivers\24256.C"
:=
:=void main (void)
:={
:=int out=0;
:=int i=0;
:=long int address=0;
:=setup_counters (RTCC_INTERNAL, WDT_2304MS);
:=setup_adc_ports(NO_ANALOGS);
:=set_tris_a(0b00000100);
:=set_tris_b(0b00000000);
:=set_tris_c(0b00011000);
:=delay_ms(1);
:=init_ext_eeprom();
:=//LED=0;
:=//delay_ms(500);
:=LED=1;
:=while(1)
:={
:=i=0;
:=address=0;
:=while(i<255)
:={
:=write_ext_eeprom(address,i);
:=//restart_wdt();
:=address++;
:=i++;
:=}
:=address=0;
:=i=0;
:=while(i<255)
:={
:=out=read_ext_eeprom(address);
:=printf("IN \%02x, OUT \%02x\r\n",i,out);
:=//restart_wdt();
:=address++;
:=i++;
:=}
:=LED=0;
:=delay_ms(10000);
:=LED=1;
:=}
:=} //main end
:=
:=This is snipplet from terminal screen:
:=IN 00, OUT 55
:=IN 01, OUT 29
:=IN 02, OUT 29
:=IN 03, OUT 29
:=IN 04, OUT 2d
:=IN 05, OUT 2d
:=IN 06, OUT 2e
:=IN 07, OUT 2f
:=IN 08, OUT 29
:=IN 09, OUT 59
:=IN 0a, OUT 29
:=IN 0b, OUT 29
:=IN 0c, OUT 2d
:=IN 0d, OUT 5d
:=IN 0e, OUT 5e
:=IN 0f, OUT 5f
:=IN 10, OUT 35
:=
:=If I take new Eeprom it works fine few times(IN and OUT are same), but then output becomes crazy. Only 3-4 times is enough. I can read and program Eeproms with my Galep-4 programmer, so they seems be ok. If I read Eeprom programmed with my example code with Galep-4 I can see few errors which have come on writing phase. Most of errors are coming in read sequence.
:=Eeprom is near Pic (10mm).
:=PCW version 3.082
:=Please help.
:=Kari
___________________________
This message was ported from CCS's old forum
Original Post ID: 8207
Kari Leino
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Sat Oct 26, 2002 12:58 pm     Reply with quote

:=I do not see where you defined the EEPROM_SDA & EEPROM_SCL pins. If they are not defined, the following defaults are used (unless you changed the 24256.h file).
:=
:=#define EEPROM_SDA PIN_B1
:=#define EEPROM_SCL PIN_B0
:=
:=You probably want:
:=
:=#define EEPROM_SDA PIN_C4
:=#define EEPROM_SCL PIN_C3
:=
:=Also note that your program is an endless loop writing to an eeprom. This is a bad thing since they will eventually where out after 100K-1M writes. Refer to the datasheet for the eeprom to get the typical erase/write cycles.
:=
:=Mark

I have defined SDA pin_c4 and SCL pin_c3 in 24256.c. Those are actually defaults in my 3.082 version. Code is for testing only, Led is just I can see serial data is done. I never let it run free.
Kari
___________________________
This message was ported from CCS's old forum
Original Post ID: 8208
Tomi
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Sun Oct 27, 2002 8:30 am     Reply with quote

Maybe you have to check the 24256.c file. I don't have 3.082 but some 3.XXX versions have a small error; a line is missing.
If you see something like this:
write_ext_eeprom(.........)
{
..............
// wait for write completion start here; older versions have a delay_ call here
do {
i2c_start();
ack = i2c_write(0xA0); // or something same
} while (ack);
} // end of function

In this case the I2C bus remains opened after the write is done.
Insert the following line:
do {
i2c_start();
ack = i2c_write(0xA0); // or something same
} while (ack);
i2c_stop(); // terminate i2c operation
___________________________
This message was ported from CCS's old forum
Original Post ID: 8216
Kari Leino
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Sun Oct 27, 2002 9:35 am     Reply with quote

:=Maybe you have to check the 24256.c file. I don't have 3.082 but some 3.XXX versions have a small error; a line is missing.
:=If you see something like this:
:=write_ext_eeprom(.........)
:={
:=..............
:=// wait for write completion start here; older versions have a delay_ call here
:=do {
:=i2c_start();
:=ack = i2c_write(0xA0); // or something same
:=} while (ack);
:=} // end of function
:=
:=In this case the I2C bus remains opened after the write is done.
:=Insert the following line:
:=do {
:=i2c_start();
:=ack = i2c_write(0xA0); // or something same
:=} while (ack);
:=i2c_stop(); // terminate i2c operation
:=

Added line as you said but no help. Maybe you can check 24256.c file I've got.

#ifndef EEPROM_SDA

#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3

#endif

#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL)

#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 32768 //this was 16384

void init_ext_eeprom()
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);

}


void write_ext_eeprom(long int address, byte data)
{
short int status;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>8);
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
i2c_stop(); // terminate i2c operation, added 27.10.2002!!!
}


byte read_ext_eeprom(long int address) {
byte data;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>8);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}

Thank you for spending time with my problem.
Kari
___________________________
This message was ported from CCS's old forum
Original Post ID: 8217
Charlie U
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Sun Oct 27, 2002 4:10 pm     Reply with quote

:=What is wrong in this code? It is only for testing external eeprom.
:=// Eeprom test 26.10.2002
:=// 24LC256 has 1k from SDA and SCL to +5V
:=
I'm not certain, but the 1k pullups may be a bit stiff. The 24LC256 is only spec'd at 3ma pullup current and the 1k will provide on the order of 5ma. I usually operate with a minimum resistance around 2.2k. This may not help, but give it a try.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8226
Kari Leino
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Mon Oct 28, 2002 5:29 am     Reply with quote

Have tried with 10k and 2,2k but problem isn't that.

:=:=What is wrong in this code? It is only for testing external eeprom.
:=:=// Eeprom test 26.10.2002
:=:=// 24LC256 has 1k from SDA and SCL to +5V
:=:=
:=I'm not certain, but the 1k pullups may be a bit stiff. The 24LC256 is only spec'd at 3ma pullup current and the 1k will provide on the order of 5ma. I usually operate with a minimum resistance around 2.2k. This may not help, but give it a try.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8232
Tomi
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Mon Oct 28, 2002 11:08 am     Reply with quote

OK, I have checked the list file (I have a limited access for the Net and my resources here in the hospital Smile ).
If you want to use the built-in HW for i2c then insert the option "NOFORCE_SW" (unfortunately CCS C uses bit-banged I/O unless you say explicitly to use HW, if I good remember there is an equivalent option "FORCE_HW"):
#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL,NOFORCE_SW)

If you already replaced 1k resistors to 2.2kohms then leave them in place; Charlie's note about it is absolutely correct.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8237
Kari Leino
Guest







Re: Read and Write _ext_eeprom works randomly
PostPosted: Tue Oct 29, 2002 9:38 am     Reply with quote

Hi, I think my hardware is ok now. Replaced pullups with 2.2k, added FORCE_HW in #use I2c... and added line "i2c_stop();" in 24256.c file. Writing is Ok - no errors. I've checked it with my programmer. If I've programmed eeprom locations 0-255 all with value for example 0x97 or 0xBB or... output is ok. If programmed value in all locations is 0x96, when reading everything else is ok but location 0xBF value is 0x97??? Data content has something to do with reading errors. My first example was writing value 0-254 to locations 0-254. If I only write those and read them with my programmer, they are ok. Trying to read them makes locations 0x00-0x7E value added with 0x40. 0x33 becomes 0x73 and so on. Weird thing is that reading locations 0-254 causes location 0x80 value change from 0x80 to 0x84 truly. Checked with my programmer.
Really dont know what to do. Must be sofware problem.

Someone please post really working driver for 24LC256.

Kari Leino
___________________________
This message was ported from CCS's old forum
Original Post ID: 8274
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: Read and Write _ext_eeprom works randomly
PostPosted: Tue Oct 29, 2002 3:22 pm     Reply with quote

Here is a complete test program for the Microchip 24LC256
eeprom. I installed PCM vs. 3.082 and tested this with
the hardware, and it works fine. If you try this program,
the only things you might have to change are the clock
speed (I'm using 8 MHz) and the oscillator fuse (I'm using HS).

If this program doesn't work for you, then there's probably
a hardware problem. I would check grounding, and if the
address lines on the eeprom have been left floating, and
whether the +5v on the PIC and the eeprom is stable and
without any noise.


<pre>
<font face="Courier New" size=2>

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

// Using CCS's MSSP hardware routines.


// i2c clock speed with PCM vs. 2.734 (16F877 at 8 MHz):

// Software i2c
// SLOW: 62.5 KHz
// FAST: 62.5 KHz (same as slow speed)

// Hardware i2c
// SLOW: 98 KHz
// FAST: 362 KHz

// Note that with H/W i2c, the clock has an inverted duty cycle.
// This violates the i2c spec.

//-------------------------------------------------------------------------
// 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 HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use Delay(Clock=8000000)
#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, NOFORCE_SW) // Hardware i2c
#zero_ram

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

char random_byte;

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

#byte SSPCON = 0x14
#byte SSPADD = 0x93

//---------------------------------------------------------------------------
// 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;
char k;
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 (for 10 passes).

for(k = 0; k < 10; k++)
{

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_high(PIN_C1); // Do this for a test. See if running i2c sets this low somehow.

output_low(PIN_C2); // Set the EEPROM's write protect pin low (write enabled)

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

___________________________
This message was ported from CCS's old forum
Original Post ID: 8281
Kari Leino
Guest







Re: Read and Write _ext_eeprom works randomly - Solved!
PostPosted: Wed Oct 30, 2002 3:26 am     Reply with quote

It was hardware problem. My stupid mistake. I've 50pcs ready made printed circuit boards(my design) grounded pin1 on Eeprom when it should be pin4. My luck, it's easy to fix. Too much thinking about problem - can't see straight anymore :-)

Thank you all have spend time with this.
Kari Leino
___________________________
This message was ported from CCS's old forum
Original Post ID: 8285
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