|
|
View previous topic :: View next topic |
Author |
Message |
TopLoser Guest
|
EEPROM read failure on 16F677 ? |
Posted: Mon Apr 27, 2009 5:22 am |
|
|
Problem is very simple - I can write data to the internal EEPROM with write_eeprom and confirm it has been written correctly using the programmer. No problem with writes.
However, if I try and read the data back then the read_eeprom function only ever returns the last byte of data written.
Code: |
write_eeprom(0,0x10);
write_eeprom(1,0x20);
write_eeprom(2,0x30);
write_eeprom(3,0x40);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
|
The 4 debugging statements all print a data value of 0x40. If I change the order of the write_eeprom lines...
Code: |
write_eeprom(3,0x40);
write_eeprom(2,0x30);
write_eeprom(1,0x20);
write_eeprom(0,0x10);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
|
The 4 debugging statements all print a data value of 0x10.
What am I doing that's stupid? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 27, 2009 11:00 am |
|
|
Post a test program with those statements in main() and a while(1);
at the end. Post the #include statement for the PIC, and the #fuses,
and the #use delay() statement. It should compile with no errors.
Verify that it shows the problem and post it.
Also post your compiler version. |
|
|
TopLoser Guest
|
|
Posted: Mon Apr 27, 2009 12:16 pm |
|
|
Just tried this simple (and complete) program and it fails as described.
Compiler version is PCM 4.085
Code: | #include <16F677.H>
#fuses INTRC_IO , NOWDT , NOBROWNOUT, NOMCLR
#use delay(clock=4000000)
#use rs232(XMIT=PIN_B6, baud=57600)
int main()
{
printf("Hello\n\r");
for (;;) {
delay_ms(1000);
write_eeprom(0,0x10);
write_eeprom(1,0x20);
write_eeprom(2,0x30);
write_eeprom(3,0x40);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
}
return (0);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 27, 2009 1:20 pm |
|
|
I don't have a 16F677, but I do have a 16F690 which is in the same
family. I modified your program to use the hardware UART on the
16F690. I also modified it to just do one pass, and also I zeroed the
eeprom before I wrote data to it, to verify that the code was really
working. I got the result shown below, and it's correct. I compared the
eeprom writing code between the two .LST files and it's the same.
Quote: | Hello
0 00
1 00
2 00
3 00
0 10
1 20
2 30
3 40 |
Code: | #include <16F690.H>
#fuses INTRC_IO , NOWDT , NOBROWNOUT, NOMCLR
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, ERRORS)
void main()
{
printf("Hello\n\r");
write_eeprom(0,0);
write_eeprom(1,0);
write_eeprom(2,0);
write_eeprom(3,0);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
write_eeprom(0,0x10);
write_eeprom(1,0x20);
write_eeprom(2,0x30);
write_eeprom(3,0x40);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
while(1);
} |
|
|
|
TopLoser Guest
|
|
Posted: Mon Apr 27, 2009 5:10 pm |
|
|
We seem to have a problem here. I took your working (on a 16F690) code and compiled it and then programmed it into my 16F677. It's still broken for me.
Code: |
#include <16F677.H>
#fuses INTRC_IO , NOWDT , NOBROWNOUT, NOMCLR
#use delay(clock=4000000)
#use rs232(XMIT=PIN_B6, baud=57600)
void main()
{
printf("Hello\n\r");
write_eeprom(0,0);
write_eeprom(1,0);
write_eeprom(2,0);
write_eeprom(3,0);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
write_eeprom(0,0x10);
write_eeprom(1,0x20);
write_eeprom(2,0x30);
write_eeprom(3,0x40);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
while(1);
} |
Hyperterm output for the above code is
Quote: | Hello
0 00
1 00
2 00
3 00
0 40
1 40
2 40
3 40 |
My PicKit2 programmer reads the correct data from the EEPROM.
Something is broken, do you agree? I can repeat this on multiple samples of the hardware and get the same result. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 27, 2009 6:03 pm |
|
|
Just as a test, change your read operations to load the eeprom data into
a temporary variable. Then give that variable to printf. And also do it
in a loop, just to save typing. Example:
Code: |
int8 c, i;
for(i = 0; i < 4; i++)
{
c = read_eeprom(i);
printf("%X %X\n\r", i, c);
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 28, 2009 2:13 am |
|
|
As a comment though, how long have you been experimenting with the write_eeprom function?. Have you tried at any time without the delay?.
The EEPROM, has a limited 'write' life. If you call a loop, that writes to the EEPROM, it can 'kill' the EEPROM, in under 10 minutes. With the one second delay in your example, this goes up to about a day, but if during your experimentation, you have run without the delay, then I'm afraid the answer may simply be that your EEPROM has been destroyed....
Best Wishes |
|
|
TopLoser Guest
|
|
Posted: Tue Apr 28, 2009 3:20 am |
|
|
I've never run the looping example for more than a couple of iterations, and I'm very sure the EEPROM is ok because I can always read back the written data with my programmer. It's just the read_eeprom function that seems to always returns an invalid result. |
|
|
TopLoser Guest
|
|
Posted: Tue Apr 28, 2009 3:35 am |
|
|
Last night I posted the Hyperterminal output from the board with the last test program in - the read_eeprom was returning the wrong value every time. This morning I turned the hardware on and this time Hyperterminal showed that read_eeeprom was returning the correct values. I hadn't changed anything overnight - it was the same hardware and I hadn't reprogrammed it. All I had done was leave it off overnight and then turn it on again.
To be honest this problem has been manifesting itself in this way for quite a few weeks. I thought I'd managed to isolate it with the simple test program but it looks like it's still there, but intermittent.
At this point I have no idea what the cause might be. Maybe there are some configuration bits not been set by the compiler reliably to set up for reads? The only thing I do know is that writes have ALWAYS worked and reads ALWAYS work when using the programmer.
Many thanks for people input so far. |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 28, 2009 4:18 am |
|
|
One possibility would be that the EEPROM write protection fuse (CPD) had got set. The programmer clears this, and resets it, allowing it to change the values, but then the code inside the chip, wouldn't be able to change the values....
Make sure you have NOCPD in the fuses.
Best Wishes |
|
|
Guest
|
|
Posted: Tue Apr 28, 2009 7:01 am |
|
|
Thanks for the suggestion - I put the fuse in the list and it made no difference to the configuration word value.
This is starting to annoy me now, I might have to bypass the CCS functions and go directly to the hardware. |
|
|
TopLoser Guest
|
|
Posted: Thu Apr 30, 2009 3:25 am |
|
|
Right, back to this ongoing issue.
Below is a little program that uses write_eeprom to successfully write 4 data bytes to successive locations in the 16F677 eeprom. Writing never ever fails.
The same program then uses read_eeprom to read back those 4 locations and display them. I then read the same 4 locations using the hardware registers directly.
read_eeprom has a nasty habit of returning the value of the last byte that write_eeprom was passed as a parameter, regardless of the location! Sometimes it works though, it depsnds which way the wind is blowing. Going directly via the registers always returns the correct value from the requested location.
This occurs on multiple samples of the hardware.
Code: |
#include <16F677.H>
#fuses INTRC_IO , NOWDT , NOBROWNOUT, NOMCLR, NOCPD
#use delay(clock=4000000)
#use rs232(XMIT=PIN_B6, baud=57600)
#BYTE EEADR = 0x10d
#byte EEDAT = 0x10c
#BYTE EECON1 = 0x18c
#BIT EEPGD = 0x18c.7
#BIT RD = 0x18c.0
void main()
{
int8 c, i;
write_eeprom(0,0x10);
write_eeprom(1,0x20);
write_eeprom(2,0x30);
write_eeprom(3,0x40);
printf("0 %X\n\r", read_eeprom(0));
printf("1 %X\n\r", read_eeprom(1));
printf("2 %X\n\r", read_eeprom(2));
printf("3 %X\n\r", read_eeprom(3));
// use suspect read_eeprom
for(i=0; i<4; i++) {
c = read_eeprom(i);
printf("read_eeprom %X %X\n\r", i, c);
}
// now go to direct to the hardware
for (i=0; i<4; i++) {
EEADR=i;
EEPGD=0;
RD=1;
c=EEDAT;
printf("direct %X %X\n\r", i, c);
}
while(1);
}
|
Here is the debugging output from Hyperterminal
Code: |
read_eeprom 00 40
read_eeprom 01 40
read_eeprom 02 40
read_eeprom 03 40
direct 00 10
direct 01 20
direct 02 30
direct 03 40
|
|
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 30, 2009 5:02 am |
|
|
Do two things.
Read the EEPROM into a variable, then print it.
Tell us what your compiler version is.
There was a documented problem with _printf_, some versions ago, where using certain functions directly inside the printf, led to corrupted values.
This is not a read_eeprom problem, but a fault in printf.
I'd suspect that this is what you are seeing.
Best Wishes |
|
|
TopLoser Guest
|
|
Posted: Thu Apr 30, 2009 6:21 am |
|
|
As stated earlier in this thread the compiler is version 4.085, only a few weeks old. I'd try it with 4.092 but that has an issue I don't even want to raise on this board.
In the code sample I gave I am actually reading the eeprom into a variable before printing it - somebody else suggested that a few days ago.
One of the reasons I'm having to try and sort this out is that the original application using read_eeprom was failing to read configuration data correctly from the eeprom - that code didn't have any printf at all.
However, I'm willing to try anything at the moment so how about dispensing with printf altogether....
Code: |
#include <16F677.H>
#fuses INTRC_IO , NOWDT , NOBROWNOUT, NOMCLR, NOCPD
#use delay(clock=4000000)
#use rs232(XMIT=PIN_B6, baud=57600)
#BYTE EEADR = 0x10d
#byte EEDAT = 0x10c
#BYTE EECON1 = 0x18c
#BIT EEPGD = 0x18c.7
#BIT RD = 0x18c.0
void main()
{
int8 c, i;
write_eeprom(0,'A');
write_eeprom(1,'B');
write_eeprom(2,'C');
write_eeprom(3,'D');
// use suspect read_eeprom
for(i=0; i<4; i++) {
c = read_eeprom(i);
putc('0'+i);
putc(c);
putc('\n');
putc('\r');
}
// now go to direct to the hardware
for (i=0; i<4; i++) {
EEADR=i;
EEPGD=0;
RD=1;
c=EEDAT;
putc('0'+i);
putc(c);
putc('\n');
putc('\r');
}
while(1);
}
|
Debugging output
Quote: |
0D
1D
2D
3D
0A
1B
2C
3D
|
Annoying isn't it! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 30, 2009 12:17 pm |
|
|
Tell us about your hardware. Did you build the board yourself, or did
you buy it ? If you bought it, post the manufacturer and model number.
If you built it, describe the circuits and the board in detail. Is it a printed
circuit board ? If so, does it have a ground plane, or gridded ground
tracks ? What voltage regulator is used ? What's the Vdd voltage ?
Do you have a 0.1 uF (100 nF) ceramic capacitor very close to the PIC's
Vdd pin ? Etc. |
|
|
|
|
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
|