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

24LC16B problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guest








24LC16B problem
PostPosted: Thu Oct 25, 2007 10:12 am     Reply with quote

I've been facing a very weird problem. I've a PIC16F648A and a 24LC16B. the EEPROM is connected to the PIN_A3 and the PIN_A2 of the 648A. The two lines (SDA and SCL) have a pull-up resistor of 10K.

So the code is as follows:

Code:
 
#include <16F648A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES PROTECT
#FUSES PUT                      //Power Up Timer

#define EEPROM_SCL  PIN_A2
#define EEPROM_SDA  PIN_A3

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

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

BOOLEAN ext_eeprom_ready()
{
   int1 ack;
   i2c_start();            // If the write command is acknowledged,
   ack = i2c_write(0xa0);  // then the device is ready.
   i2c_stop();
   return !ack;
}

void write_ext_eeprom(long int address, BYTE data)
{
   while(!ext_eeprom_ready());
   i2c_start();
   i2c_write((0xa0|(BYTE)(address>>7))&0xfe);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}


BYTE read_ext_eeprom(long int address)
{
   BYTE data;

   while(!ext_eeprom_ready());
   i2c_start();
   i2c_write((0xa0|(BYTE)(address>>7))&0xfe);
   i2c_write(address);
   i2c_start();
   i2c_write((0xa0|(BYTE)(address>>7))|1);
   data=i2c_read(0);
   i2c_stop();
   return(data);
}

void main(void)
{
    int i = 0;
   int j = 0;
   int x = 0;
   int16 pos_eeprom = 0;
   int16 pos_eeprom_aux = 0;
   x = 0x41;
   pos_eeprom = 2;
   pos_eeprom_aux = pos_eeprom;
   init_ext_eeprom();
    while(TRUE)
    {
         for (i = 0; i < 500; i++)
         {
         for (j = 0; j < 3 ; j++)
         {
            write_ext_eeprom(pos_eeprom++, x+j);
            delay_ms(5);
         }
         for (j = 0; j < 3; j++)
         {
            if (x+j != read_ext_eeprom(pos_eeprom_aux++))
            {
               write_eeprom(i, 0x40);
                                        delay_ms(5);
            }
         }
         }
    }
}
 


And all the code runs perfectly well, but when the pos_eeprom reaches the value of 0x28 it stops, it does nothing more... why?
But if I test the same code with the internal eeprom I have no error, what is the problem?
Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 25, 2007 11:56 am     Reply with quote

I don't know what your code is supposed to be doing, but there are
a few errors.

Quote:
int i = 0;

for (i = 0; i < 500; i++)


There is a problem with this loop.
In CCS an 'int' is an 8-bit unsigned integer. It can only hold a value
from 0 to 255. If you want to hold 500, then you must use an 'int16'.


Quote:
write_eeprom(i, 0x40);

In your code, you mostly access the external eeprom. Then in this
line, you access the internal eeprom. It that your intention ?
Also the internal eeprom in the 16F648A is only 256 bytes. The address
can only be from 0 to 255. Your loop tries to go from 0 to 499.


If you have any more problems, please post your compiler version.
Also, write a more simple test program.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu Oct 25, 2007 3:03 pm     Reply with quote

I would not have a resistor value higher than 4.7K. A higher value will most likely cause the bus to not work.

Ronald
ralph79



Joined: 29 Aug 2007
Posts: 87

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 7:35 am     Reply with quote

To PCM Programer:

I think I've assigned my first post because but for some reason it was not signed.
First of all thanks for your reply.
The code I posted here is a very small portion of a bigger code.
This part of code:
Code:

int i = 0;

for (i = 0; i < 500; i++)
 


was a small test code do determine if the it were any errors in write/read external eeprom.
At the beginning it was a int16, then a long int, an finally a int from 0 to 255. I've made an error in my post.
The internal write memory that is in my code, should only occur any there is an error in the write/read external eeprom.

My compiler version is 4.038

To rnielsen:

I've tried to change my pull-ups resistors from 10K, 4.7K but still no luck

Any other advice?

Best thanks
amcfall



Joined: 20 Oct 2005
Posts: 44

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 8:39 am     Reply with quote

PCM programmer wrote:

If you have any more problems, please post your compiler version.
Also, write a more simple test program.


Do as he asked if you want further help.

Avery
ralph79



Joined: 29 Aug 2007
Posts: 87

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 10:00 am     Reply with quote

Ok this is my simplest code:

Code:

#include <16F648A.h>

#define EEPROM_SCL  PIN_A2
#define EEPROM_SDA  PIN_A3
#define OFF         0
#define ON         1

#include <2416.c>

#FUSES NOWDT,INTRC_IO,NOPROTECT,NOBROWNOUT,NOMCLR,NOCPD,PROTECT,PUT

#use delay(clock=4000000)

void Blink_Led_0(void)
{
   output_high(PIN_A0);
   delay_ms(500);
   output_low(PIN_A0);
   delay_ms(500);
}

void Blink_Led_1(void)
{
   output_high(PIN_A1);
   delay_ms(50);
   output_low(PIN_A1);
   delay_ms(50);
}

void main(void)
{
    int16 pointer, pos_eeprom, pos_eeprom_aux;
   int8 value, j;
   int1 write_accomplish;

   value = 0x41;   // "A"
   pos_eeprom_aux = pos_eeprom = 2;
   write_accomplish = OFF;
   
   init_ext_eeprom();

    while(TRUE)
    {
         if (!write_accomplish)
         {
          for (pointer = 0; pointer < 500; pointer++)
          {
            for (j = 0; j < 3 ; j++)
            {
               write_ext_eeprom(pos_eeprom++, (value + j));
            }
            for (j = 0; j < 3; j++)
            {
               if ( (value + j) != read_ext_eeprom(pos_eeprom_aux++) )
               {
                  Blink_Led_0();
               }
            }
            Blink_Led_1();
          }
         write_accomplish = ON;
         }
    }
}


For some reason, which I don't know what is, several times the 16F648A fails the write/read operation and hangs. In other words it stops in time and the any way to make it work again is make an hardware reset.
My question is: does anybody have ever had a similar problem? If so how he/she accomplish to make it to work.

I even tried to put a small delay of 1ms after each read or write operation but I keep getting the same problem

I've changed also the pull-up resistors values, the microcontroller and also the EEPROM. So, my guess is, the problem is on the software, but I don't know where.

Best regards,
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 11:03 am     Reply with quote

1. Did you build this board or did you buy it ? If you bought it, what's
the manufacturer and model number ? If you built it, do you have
a 100 nF (0.1 uF) ceramic capacitor between the PIC's Vdd pin and
ground (placed very close to the pins, with short leads) ?

2. Do you have a 10K or 47K pull-up resistor on the MCLR pin ?
(10K for most applications, 47K if you're using the CCS ICD-U40).

3. You should add the NOLVP fuse. I looked at the .LST for vs. 4.038
and it sets the NOLVP fuse by default. That's unusual for CCS.
But you should specify it anyway.

4. What's the Vdd voltage on your board ? Is it +5v or +3.3v ?
Does it come from a voltage regulator ?

5. If you built the board, is it an actual board, or is it a 3M-style
protoboard where all the connections are made with jumper wires ?
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 3:13 pm     Reply with quote

Is that the actual code that you have compiled and tried? If it is, you are missing all of the initializing statements at the beginning of main() like:

Code:
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
   port_a_pullups(TRUE);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ);


I don't know if these work for the PIC you are using. I simply grabbed it from the project I currently have open.

Ronald
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 3:47 pm     Reply with quote

Those lines are put in by the CCS IDE Wizard. In the code you posted,
the Wizard is enabling various modules that are used by your program.

In the typical case, the Wizard puts in many lines of code to disable
the PIC's peripheral modules. Example:
Code:
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_spi(FALSE);
setup_vref(FALSE);
setup_comparator(NC_NC_NC_NC);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_WDT(WDT_OFF);

These lines are not needed. They turn off modules that are disabled
by default, upon power-on reset. Or in the case of the comparators,
the compiler already puts in start-up code that turns them off.
Also, it puts in start-up code to make the analog pins become digital i/o.

In some cases, when a new PIC is added to the compiler, CCS doesn't
do the start-up code correctly. Then you might need to turn off the
comparators as shown above. Or, that line might not work, and you
need to put in code to write directly to the CMCON register.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Oct 26, 2007 5:18 pm     Reply with quote

I understand that some of that code may not be needed but I've learned that you can't always trust the compiler to set things up properly 'by default'. That is one that will bite you in the butt. I always put these instructions in to ensure that everything is set up and configured properly. Never 'assume' (and you know what that means) anything, especially when it comes to software meshing with hardware. Wink

Ronald
ralph79



Joined: 29 Aug 2007
Posts: 87

View user's profile Send private message

PostPosted: Sat Oct 27, 2007 3:44 am     Reply with quote

I've my own board, not a prototype board but a actual PCB board.
The distance between the micro controller and the EEPROM pins is less than one inch. Both the pins SDA, SCL have pull-up resistors.
The board has an voltage regulator (78L05) that feeds the micro controller and the EEPROM. Both (EEPROM and micro) have an ceramic capacitor of 100nF between the Vdd and the Vss to filter the commutation spikes from the chips.
The MCLR pin has an pull-up resistor of 10K.

I will try the NOLVP fuse again, I think that I've already tried but with no luck.
The only thing I didn't really tried is to turn off all the modules I don't use.
In my real code, the one that has been killing my head, because of this strange error I've a little more initialization than I posted here:

Initialization of comport:
Code:

#use rs232(baud=1200, parity=N, xmit=PIN_B2, rcv=PIN_B1, bits=8, errors)

Initialization of timers and others:
Code:

        disable_interrupts(INT_TIMER1);
   disable_interrupts(INT_RDA);
   disable_interrupts(INT_TIMER0);

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  // div_by_1=128us
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);        // div_by_2=131ms
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
        // .....................
       init_ext_eeprom();
       // ........................

And the routines that grab the interrupts are:
Code:

#int_RDA   // rs232 receive data available
void RDA_isr(void)
{
    /*
       ......................
       .....................
   */
}
#int_TIMER0
void TIMER0_isr(void)
{
   /*
       ......................
       .....................
   */
}
#int_TIMER1
void TIMER1_isr(void)
{
   /*
       ......................
       .....................
   */
}

I even tried to make a:
Code:

disable_interrupts(GLOBAL);

and a:
Code:

enable_interrupts(GLOBAL);

Each time I've made an read write operation to the external EEPROM but with no effect.

What is killing my head is if I change:
Code:

write_ext_eeprom(pos_eeprom++, (value + j));

to
Code:

write_eeprom(pos_eeprom++, (value + j));

and
Code:

read_ext_eeprom(pos_eeprom_aux++);

to
Code:

read_eeprom(pos_eeprom_aux++); 

Knowing of course that my internal eeprom have only 256bytes... But I don't have any error. Neither the microcontroller hangs, fails or stopps.
It seems to me that I need vacancies...

Any help would appreciate.

Best regards
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Oct 27, 2007 10:02 am     Reply with quote

I have a question.

Does your "simplest code" that you posted above actually show
the problem, when you run it ?

Or, do you only see the problem when you run your complete large
program ?
ralph79



Joined: 29 Aug 2007
Posts: 87

View user's profile Send private message

PostPosted: Sat Oct 27, 2007 10:35 am     Reply with quote

In my "simplest code", only from time to time shows the problem, but it happens.

In my real code, the error happens always from the moment I have 130/140 bytes in my eeprom and I want to write and read a few more.
Until the moment I have only 100/120 bytes in the eeprom I've never noticed any error.
I even tried a small delay (1ms) between each read/write operation but when I get to the position 130/140 it just bangs.
Another test that I've made... Rather begin reading/writing the eeprom from the position zero,what about begin from the position, let's say 100 or 200, and gets what... it bangs.
Do you any clue for this error?
Maybe I'm doing something wrong, but I don't know what is.
If I have an error inside my code, when I work with the internal eeprom I should see the error, but I never did.
My guess is that there is something about the I2C communication. Or some include or define that I should do when I have interrupts or functions /modules in my code.
Might the I2C routine have any code that in some cases could lead to this error?

Thanks for all your patience and feedback.

But I really don't have a clue for this problem-

Best regards
newguy



Joined: 24 Jun 2004
Posts: 1904

View user's profile Send private message

PostPosted: Sat Oct 27, 2007 12:04 pm     Reply with quote

Running fine while while the address (number of bytes) is < 128 and hanging when it gets above this may indicate a problem with the most significant address bit. Whether that problem is internal to the PIC or is internal to the external EEPROM has to be determined.

Can you replace the EEPROM to see if the issue goes away?
ralph79



Joined: 29 Aug 2007
Posts: 87

View user's profile Send private message

PostPosted: Sat Oct 27, 2007 12:44 pm     Reply with quote

I've already replace it and still didn't work.
Unless all the eeproms I have.... have a problem.... which I doubt....
The problem should be in the way the PIC communicates to the eeprom, but I'm not absolute sure.

Does anybody have or had a problem like this?
I just want to see if a determined number of bytes (in a sequential order) is on eeprom and if not the PIC should write that sequence in the eeprom. It should easy.
But I guess not...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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