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

My I2C communication with EEPROM resets or even hangs my PIC

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







My I2C communication with EEPROM resets or even hangs my PIC
PostPosted: Thu Aug 03, 2006 10:20 pm     Reply with quote

I am using a 18F1320 PIC, currently connected to one 24LC512 serial EEPROM. All other tasks perform just fine, except the i2c communication to the EEPROM.
For no particular reason the PIC resets itself or hangs when inside a read / write procedure. To make matters worse, i have detected some communication NACK's in the proccess. Beeing in need of connecting more than one EEPROM and software resolving the communication problems, I have extended the driver supplied with the compiler for this type of memory.

Here follows my code:
Code:
#ifndef EEPROM_SDA

#define EEPROM_SDA  PIN_B0
#define EEPROM_SCL  PIN_A3

#endif

#use delay (clock=20000000)
#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL, fast)

#define EEPROM_ADDRESS long int
#define EEPROM_SIZE    65535

int write_ext_eeprom(byte wraddr, long int address, byte data);
byte read_ext_eeprom(byte wraddr, byte rdaddr, long int address);

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

}

int wr_ee (short int memnr, long int address, byte data)
{
   switch (memnr)                                           // A2 A1 A0
   {
      case 0 : return write_ext_eeprom(0xa0,address,data);  //  0  0  0
      case 1 : return write_ext_eeprom(0xa2,address,data);  //  0  0  1
      case 2 : return write_ext_eeprom(0xa4,address,data);  //  0  1  0
      case 3 : return write_ext_eeprom(0xa6,address,data);  //  0  1  1
      case 4 : return write_ext_eeprom(0xa8,address,data);  //  1  0  0
      case 5 : return write_ext_eeprom(0xaa,address,data);  //  1  0  1
      case 6 : return write_ext_eeprom(0xac,address,data);  //  1  1  0
      case 7 : return write_ext_eeprom(0xae,address,data);  //  1  1  1
      default : return 0;
   }
}

int write_ext_eeprom(byte wraddr, long int address, byte data)
{
   short int status = 1;
   int defreeze = 0;

   while (status==1 && defreeze++<100) // defreeze++<100>>8);
      if (status==1) { i2c_stop(); delay_ms(6); continue; }
      status=i2c_write(address);
      if (status==1) { i2c_stop(); delay_ms(6); continue; }
      status=i2c_write(data);
      i2c_stop();
      if (status==1) delay_ms(6);
   }
   if (status==1) return 0;
   defreeze = 0;
   while(status==1)
   {
      i2c_start();
      status=i2c_write(wraddr);
      i2c_stop();
   }
   return 1;
}

byte rd_ee (short int memnr, long int address)
{
   switch (memnr)                                          // A2 A1 A0
   {
      case 0 : return read_ext_eeprom(0xa0,0xa1,address);  //  0  0  0
      case 1 : return read_ext_eeprom(0xa2,0xa3,address);  //  0  0  1
      case 2 : return read_ext_eeprom(0xa4,0xa5,address);  //  0  1  0
      case 3 : return read_ext_eeprom(0xa6,0xa7,address);  //  0  1  1
      case 4 : return read_ext_eeprom(0xa8,0xa9,address);  //  1  0  0
      case 5 : return read_ext_eeprom(0xaa,0xab,address);  //  1  0  1
      case 6 : return read_ext_eeprom(0xac,0xad,address);  //  1  1  0
      case 7 : return read_ext_eeprom(0xae,0xaf,address);  //  1  1  1
      default : return 0x00;
   }
}

byte read_ext_eeprom(byte wraddr, byte rdaddr, long int address)
{
   byte data = 0x00;
   short int status = 1;
   int defreeze = 0;

   while (status == 1 && defreeze++ < 100) // defreeze++<100>>8);
      if (status==1) { i2c_stop(); delay_ms(6); continue; }
      status=i2c_write(address);
      if (status==1) { i2c_stop(); delay_ms(6); continue; }
      i2c_start();
      status=i2c_write(rdaddr);
      if (status==1) { i2c_stop(); delay_ms(6); continue; }
      data=i2c_read(0);
      i2c_stop();
   }
   return data;
}


So things got a little better after modifying the standard library. But, albitrary, the pic still resets or hangs. Especially (but not only) during long operation, like clearing the memory (this process completes succesfully only 2/10 of times).
I have used both 2k2 and 10k pullups on SDA and SCL. The board is plugged to 5 V and clock is taken from an external crystal oscillator running at 20 MHz. All ports (A and B) are operated on standard_io with no tris specified.
Could anyone give me a suggestion to help work out my issues ? It can be an improvement if I can find out the source of my troubles - hardware or software ?
Thank you. Regards.
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Thu Aug 03, 2006 11:01 pm     Reply with quote

This may or may not be the cause, but it's something that's vexed me before.....

Do you have the watchdog enabled? If it's set for the quickest (18 ms), it may be resetting the PIC while it's waiting for the EEPROM to reply.

I had this same issue and it was the watchdog doing it. I stuck some watchdog resets in the i2c_write() and read() routines, and no problems since.
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri Aug 04, 2006 8:31 am     Reply with quote

If you change this:
#use delay (clock=20000000)

To this:
#use delay (clock=20000000, restart_wdt)
the watch dog timer will be reset in the delay_ms(6) functions.
_________________
David
Vyperin
Guest







Thanks for your prompt posts, but...
PostPosted: Fri Aug 04, 2006 2:08 pm     Reply with quote

... but, I've decided not to use the watchdog because I'm quite inexperienced with this method of self-deblock.

This is my init sequence:
Code:
setup_adc_ports(NO_ANALOGS|VSS_VDD);
      setup_adc(ADC_OFF|ADC_TAD_MUL_0);
      setup_wdt(WDT_OFF);
      setup_oscillator(OSC_NORMAL);
      setup_timer_0(RTCC_EXT_L_TO_H);
      setup_timer_1(T1_DISABLED);
      setup_timer_2(T2_DISABLED,0,1);
      setup_timer_3(T3_EXTERNAL|T3_DIV_BY_1);


And theese are my fuses:
Code:
#FUSES NOWDT                    //No Watch Dog Timer
//#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOBROWNOUT               //No brownout reset
//#FUSES BORV20                   //Brownout reset at 2.0V
//#FUSES NOPUT                    //No Power Up Timer
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES NOMCLR
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOCPB                    //No Boot Block code protection


Any other idea would be dully appreciated.
Thank you.
Mark



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

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

PostPosted: Fri Aug 04, 2006 10:03 pm     Reply with quote

Do you have pullups on the lines?
Vyperin
Guest







The EEPROM has pullups to VCC.
PostPosted: Sat Aug 05, 2006 4:18 am     Reply with quote

I have used both 2K2 and 10K pullups to VCC (5 V) - as specified in documentation. Whatsoever, no significant change occured when I switched over the values.

Because the PIC's clock is 20 MHz and communication is fast, I believe 2K2 is more appropriate than 10K. The distance from the pic's connection to SDA and SCL on the memory is around an inch.
However, my main problem is not solved.

I have tried to include in the #use i2c - force_hw -> and the read / write performs slower and the pic is reseting / blocking much faster.

If you got any other ideas that could solve my problem, please post here.
Thank you. Regards.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Aug 05, 2006 12:46 pm     Reply with quote

Quote:
I am using a 18F1320 PIC, currently connected to one 24LC512 serial EEPROM.
For no particular reason the PIC resets itself or hangs when inside a read / write procedure.

This should work. Currently you are trying to fix it by putting band-aids
on the driver. That's the wrong way to solve the problem.

The way I would work on this problem is:

1. Remove all external circuits (chips) except for the EEPROM.
Check all connections. Are you running at +5v or a lower voltage ?

2. Go back to the original, unmodified CCS driver.

3. Get rid of FAST mode in the #use i2c() statement.

4. I would change to a 4 MHz crystal. Possibly you can do this one later.

5. I would write a very simple, very short test program that only reads
from the EEPROM. This could be a loop that sequentially reads all
data within the eeprom. You could send a '.' to the terminal window
on the PC, once per pass, to indicate that the program is still running.
Let that run for 24 hours. See if it locks up. Or, instead of a dot,
you could output a pass-count value (use a 32-bit variable).
Be aware that the terminal program's buffer may have overflowed
when you come in the following morning. You may need to re-start
the terminal program to see if the PIC program is still producing
output.

6. If that works, then do the same thing except use write operations.

7. If that works, then do a full eeprom test program, in which you
write pseudo-random data to the eeprom, and then reload the seed,
and read back the data while comparing it to what was written.

8. If successful, then try going to FAST mode and so on.

In other words, start at the most simple level, get it working there,
and then slowly add complexity.

-------------

Also, post your compiler version. This will be a number such as 3.191,
3.236, 3.249, etc.
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