|
|
View previous topic :: View next topic |
Author |
Message |
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
Help with external EEPROM code |
Posted: Sat May 14, 2005 8:09 pm |
|
|
hi, ive been trying to get some example code working and i cant quite get there. Ive had a play with some simpler code and got it working, but now when i re-wrote it with multi-read it doesnt work even though i have used the same 'bones'.
heres the code and the serial output to look at:
--------------===========Main Code=========----------
Code: |
#include <18F458.h>
#fuses HS, NOWDT, NOPROTECT, PUT, NOBROWNOUT, NOLVP, NOWRT
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS, FORCE_SW, INVERT)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,force_hw)
#include "24x512 Driver.c"
void init_ext_eeprom()
{
setup_adc_ports(ADC_OFF);
setup_comparator(NO_ANALOGS);
Setup_CCP1(CCP_OFF);
Setup_CCP2(CCP_OFF);
output_float(PIN_C4);
output_float(PIN_C3);
}
void main(void) {
char test[20];
char returned[20];
int testsize,i;
init_ext_eeprom();
delay_ms(500);
strcpy(test,"This is a test!!!");
testsize = sizeof(test);
printf("\n\rWriting to EEPROM: %S, Size = %u",test,testsize);
delay_ms(6);
printf("\n\r%u",WriteExtMem(1,test,testsize,1));
delay_ms(6);
printf("\n\r%u",WriteExtMem(1,test,testsize,2));
delay_ms(6);
printf("\n\r%u",WriteExtMem(1,test,testsize,3));
delay_ms(6);
printf("\n\rReading....");
delay_ms(6);
printf("\n\r%u",ReadExtMem(1,returned,testsize,1));
printf("\n\rData returned: %S",returned);
delay_ms(6);
printf("\n\r%u",ReadExtMem(1,returned,testsize,2));
printf("\n\rData returned: %S",returned);
delay_ms(6);
printf("\n\r%u",ReadExtMem(1,returned,testsize,3));
printf("\n\rData returned: %S",returned);
delay_ms(6);
}
|
----------=============24x512 Driver===========-----------
Code: |
//------------------------------------
// Write to External EE-Prom
//------------------------------------
int WriteExtMem(int16 Address, char *data, int16 length, int chip_number)
{
int i;
disable_interrupts(global);
i2c_start();
switch (chip_number)
{
case 1: if(i2c_write(0b10100000)) return 2; //Write to Chip 1
else break;
case 2: if(i2c_write(0b10100010)) return 3; //Write to Chip 2
else break;
case 3: if(i2c_write(0b10100100)) return 4; //Write to Chip 3
else break;
}
if (i2c_write(make8(Address,1)) || i2c_write(make8(Address,0))) return 5;
for (i=0; i<length; i++)
{
if(i2c_Write(*Data++)) Return 6;
}
i2c_stop();
enable_interrupts(global);
return 1;
}
//------------------------------------
// Read to External EE-Prom
//------------------------------------
int1 ReadExtMem(int16 Address, char *data, int16 length, int chip_number)
{
int i;
disable_interrupts(global);
i2c_start();
switch (chip_number)
{
case 1: if(i2c_write(0b10100000)) return 2; //Write to Chip 1
else break;
case 2: if(i2c_write(0b10100010)) return 3; //Write to Chip 2
else break;
case 3: if(i2c_write(0b10100100)) return 4; //Write to Chip 3
else break;
}
if (i2c_write(make8(Address,1)) || i2c_write(make8(Address,0))) return 5;
i2c_start();
switch (chip_number)
{
case 1: if(i2c_write(0b10100001)) return 6; //Read from Chip 1
else break;
case 2: if(i2c_write(0b10100011)) return 7; //Read from Chip 2
else break;
case 3: if(i2c_write(0b10100101)) return 8; //Read from Chip 3
else break;
}
for( i = 0; i < length-1 ; i++) *Data++ = i2c_read(1); //read all but last data byte
*Data = i2c_read(0); //read last data byte (with NoACK)
i2c_stop();
enable_interrupts(global);
return 1;
}
|
----------------===========Terminal Ouput=======---------
Code: |
\0A
Writing to EEPROM: This is a test!!!, Size = 20\0A
1\0A \0D
1\0A\0D
1\0A\0D
Reading....
|
============-------------------------================
as you can see it seems to hang, just as it starts reading.
any ideas?????
cheers, phil |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 15, 2005 1:27 am |
|
|
I didn't try to analyze your entire code and find out what's wrong with it,
but in scanning it I did notice a couple things.
1. Your routines are declared to return an "int1", but within the routines,
you're returning all sorts of non-boolean values. You need to change
the routines so they return an "int8".
2. In your R/W routines, you've declared an "int i", which is an unsigned
8-bit value in CCS. Then later in the routines, you're comparing
this 8-bit value to a 16-bit "length" variable. That's not right.
3. Your EEPROM chips have addresses of 0, 1, and 2, but you're
passing chip addresses of 1, 2, and 3 to the routines.
There may be other errors.
-----------
If you want to find out where something is locking up, one quick way
is to insert putc() statements after every important line of code in
your routine. See the lines shown in bold below. Your terminal
window may show something like ABCDEFG, and then you know
that it's locking up at the line after the "G". Then you can investigate
why.
int1 ReadExtMem(int16 Address, char *data, int16 length, int chip_number)
{
int i;
putc('A');
disable_interrupts(global);
putc('B');
i2c_start();
putc('C');
switch (chip_number)
{
case 1: if(i2c_write(0b10100000)) return 2; //Write to Chip 1
else break;
case 2: if(i2c_write(0b10100010)) return 3; //Write to Chip 2
else break;
case 3: if(i2c_write(0b10100100)) return 4; //Write to Chip 3
else break;
}
putc('D');
if (i2c_write(make8(Address,1)) || i2c_write(make8(Address,0))) return 5;
putc('E');
i2c_start();
putc('F');
switch (chip_number)
{
case 1: if(i2c_write(0b10100001)) return 6; //Read from Chip 1
else break;
case 2: if(i2c_write(0b10100011)) return 7; //Read from Chip 2
else break;
case 3: if(i2c_write(0b10100101)) return 8; //Read from Chip 3
else break;
}
putc('G');
for( i = 0; i < length-1 ; i++)
*Data++ = i2c_read(1); //read all but last data byte
putc('H');
*Data = i2c_read(0); //read last data byte (with NoACK)
putc('I');
i2c_stop();
putc('K');
enable_interrupts(global);
putc('L');
return 1;
} |
|
|
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
|
Posted: Sun May 15, 2005 7:21 am |
|
|
Hi, thanks for the reply. Although i have now changed the things you suggested, without the changes, it still worked. whether thats ccs compensating or it never happened to clash i dont know. But just to be sure ;-)
As for the last point, I looked at the chips as "chip number 1" etc. but it just so happened that chip number 1 had an address of 0, chip number two had an address of 1 etc. there a switch select routine in the driver to decide which chip to send it to.
what i did do was put the putc('A') stuff in and i finally managed to find that for some reason, when i took the first chip out of the routines, chips 2 and 3 then suddenly worked perfectly.
i then thought that the wiring was wrong, but it was fine, so the chip must be a dud. wrong again. i swapped a working chip for that and it didnt work again.
basically, whenever i set the address to 000 then it wouldnt work. WHY?????? the datasheet mentions nothing about this fact and says that it should be able to handle 8 address, i.e. 0->7.
does anyone know why?? because i was planning on using as many chips as i possibly could, and it would be silly not to be able to use address 0.
Thanks Mr. Programmer
Phil |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 15, 2005 2:03 pm |
|
|
You're right about the case stuff. I was looking a little too hard for bugs.
1. If you put in the code for Chip 0, at what line does it lock-up ?
2. Have checked the hardware for Chip 0 ? Are all three of the
address lines grounded ? Does it have power and ground ?
Have you accidently write-protected the device by tying the
WP pin to Vcc ? |
|
|
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
|
Posted: Sun May 15, 2005 4:01 pm |
|
|
hi again, yeah ive checked the hardware, and its fine. it works as long as i change it to binary 011.
it locks up just before the second start bit ie. i2c_start(); or in your code, point E.
inccidently, why do i have to do the second start bit??? and the second address code???
cheers. this ones baffled me.
phil |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 15, 2005 4:21 pm |
|
|
Quote: | inccidently, why do i have to do the second start bit??? and the second address code???
cheers. this ones baffled me. |
It's your driver. I was just giving tips on coding problems
that I saw in it.
It appears that you're trying to do some sort of Ack polling at
the start of your write routine. But it doesn't wait in a loop
until you get an Ack, it just bails immediately if you don't get one.
You should look at how CCS does it in their write routine:
Code: | 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();
// Wait until the write operation is finished. Do this by "Ack Polling".
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
} |
|
|
|
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
|
Posted: Sun May 15, 2005 6:18 pm |
|
|
ok, good point, i was looking to do this in a later revision, so thats why i put all the delays in the main() code, so i dont have to take the polling into consideration. And obviously it isnt foolproof, since it just might not work, but this doesnt take into account the fact that the first chip didnt work, the others did, change the address and vuala.
Moving on the actual polling though, would i have to 'poll' every write? or just at the end of all the writes since the ccs driver doesnt write multi-byte's and does the same go for the read?? because again, the ccs version doesnt include polling (in the read)??
cheers again,
phil |
|
|
|
|
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
|