|
|
View previous topic :: View next topic |
Author |
Message |
Kari Leino Guest
|
Read and Write _ext_eeprom works randomly |
Posted: Sat Oct 26, 2002 10:44 am |
|
|
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
|
Re: Read and Write _ext_eeprom works randomly |
Posted: Sat Oct 26, 2002 11:55 am |
|
|
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 |
Posted: Sat Oct 26, 2002 12:58 pm |
|
|
:=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 |
Posted: Sun Oct 27, 2002 8:30 am |
|
|
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 |
Posted: Sun Oct 27, 2002 9:35 am |
|
|
:=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 |
Posted: Sun Oct 27, 2002 4:10 pm |
|
|
:=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 |
Posted: Mon Oct 28, 2002 5:29 am |
|
|
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 |
Posted: Mon Oct 28, 2002 11:08 am |
|
|
OK, I have checked the list file (I have a limited access for the Net and my resources here in the hospital ).
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 |
Posted: Tue Oct 29, 2002 9:38 am |
|
|
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
|
Re: Read and Write _ext_eeprom works randomly |
Posted: Tue Oct 29, 2002 3:22 pm |
|
|
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! |
Posted: Wed Oct 30, 2002 3:26 am |
|
|
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 |
|
|
|
|
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
|