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 CCS Technical Support

I2C Problems with SCL SDA lines

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



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

I2C Problems with SCL SDA lines
PostPosted: Fri Aug 11, 2006 6:55 am     Reply with quote

I have written a simple program to verify the storage and retrieval of data from a PIC16C57 to a 24LC16B EEProm. The code will loop through and store a value in the EEprom that is equal to the loop counter “i” times 10 plus the address. It will store the values in successive locations in the EEProm starting with address 1. After it stores the information it will then read a value from the EEprom that is at a location as selected by the variable “loc”.

If it runs properly after its 3 loops I should have the following:

data1 = 12
data2 = 22
data3 = 33

When I run the program and use my picmaster ICE to watch the values in the data registers I get different numbers almost every time. After I run the program sometimes data1 = data2 = data3 = 12. Occasionally data1 =12, data2 = 255, and data3 = 255

When I watch the SDA and SCL lines with my digital o-scope I see an occasional error when it loops back around and sends the new I2C_START(); command. I have noticed that the SDA line is low and when I come into this command and the SCL line goes from high to low the SCL line is already low so it does not give the correct Start sequence to the EEPROM. It does the same thing occasionally on the I2C_STOP(); command. The SCL will go from low to high but the SDA will stay low.

Is there a command I am missing that lets the SDA line return to a state it needs to be in prior to sending a Start of Stop command?

I have 10K pullups on the the SDA and SCL pins.

The delay_cycles(1); commands are used as NOPs so I can put a breakpoint in my code to step through the program.
Code:

#include <16C57.h>
#device *=8,
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=4000000)
#use I2C(master, SDA=PIN_B7,  SCL=PIN_B6)
#define EEPROM_SDA  PIN_B7
#define EEPROM_SCL  PIN_B6
// #include <2416.c>

int   data, i, data1, data2, data3, data4, data5, loc;

void main()
{
   loc = 2;
   while (1==1)
   {
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);
   i=0;
   data1=0;
   data2=0;
   data3=0;
   data4=0;
   data5=0;
   while (i<3)
   {
      i++;
      output_float(EEPROM_SCL);
      output_float(EEPROM_SDA);
      I2C_START();
      delay_cycles(1);
      I2C_WRITE(160);
      delay_cycles(1);
      I2C_WRITE(1);
      delay_cycles(1);
      I2C_WRITE(1+i*10);
      delay_cycles(1);
      I2C_WRITE(2+i*10);
      delay_cycles(1);
      I2C_WRITE(3+i*10);
      delay_cycles(1);
      I2C_STOP();
      delay_cycles(1);

      switch(i)
      {
         case 1:
            output_float(EEPROM_SCL);
            output_float(EEPROM_SDA);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(160);
            delay_cycles(1);
            I2C_WRITE(LOC);
            delay_cycles(1);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(161);
            delay_cycles(1);
            data1 = I2C_READ();
            break;
         case 2:
            output_float(EEPROM_SCL);
            output_float(EEPROM_SDA);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(160);
            delay_cycles(1);
            I2C_WRITE(LOC);
            delay_cycles(1);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(161);
            delay_cycles(1);
            data2 = I2C_READ();
            break;
         case 3:
            output_float(EEPROM_SCL);
            output_float(EEPROM_SDA);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(160);
            delay_cycles(1);
            I2C_WRITE(LOC);
            delay_cycles(1);
            I2C_START();
            delay_cycles(1);
            I2C_WRITE(161);
            delay_cycles(1);
            data3 = I2C_READ();
      }
      delay_cycles(1);
      I2C_STOP();
   }
   delay_cycles(1);   
   }
}
Ttelmah
Guest







PostPosted: Fri Aug 11, 2006 8:12 am     Reply with quote

The obvious answer is that the write has not finished. You need to either pause for 5mSec after writing the data, or use acknowledge polling, to find out when the chip has actually finished. Till the write has finished, it won't ACK, and further commands won't work.

Best Wishes
edbfmi1



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

PostPosted: Fri Aug 11, 2006 9:05 am     Reply with quote

Thanks for the input,

I changed all of the delay_cycles(1) to delay_ms(10) and re-ran the code. I figured adding the 10ms delay would be a quick way to see if you cornered the gremlin. Unfortunatley I get the same problems. I will incorporate acknowledge polling but I think the 10ms delay should have cleared up the problem?

Thanks,
Ed
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Aug 11, 2006 9:09 am     Reply with quote

The output_float() command only needs to be done once in the main() body before your main while() loop.

Your program is going to be writing to the eeprom as fast as it can and you will probably wear it out fairly quickly. Eeproms have a maximum number of times that it can be written to and then it dies. Your program has no control on how often it writes data.

I made a test program and I got the results of:
11
21
31
as the data that would be written.

Try something around 4K for your pull-ups.

You are writing three numbers into your eeprom but only allowing one to be read from the eeprom, in your switch(). This should not keep it from working though. It's just that you write all three numbers for each variable read back.

Ttelmah is correct, you need to poll the eeprom to see if it's finished the writing cycle. Look at the spec. sheet and it will tell you what to do. You could put a small delay in but the best way is to see if the eeprom will ACK back before you try to read the data back.

Ronald
__________________________
You know you're a parent when you realize you're brushing your teeth with your kid's acne [spam].
edbfmi1



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

PostPosted: Fri Aug 11, 2006 9:27 am     Reply with quote

Hi Ronald,

The program is something quick to familiarize myself with the I2C EEprom. (I put a breakpoint in my ICE after I complete the 3 write loops to prevent it from writing indefinitely). In the actual application I am working on the program will probably only write to the Eeprom once or twice a week. I changed the pullups to 4.7K. Still have the same problems.

Thanks to everyone for helping me get up to speed on this.
Ed
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 11, 2006 2:53 pm     Reply with quote

You're also leaving out the NAK at the end of the last i2c_read().
This is in the data sheet for the 24LC16B, and it's in the sample
CCS drivers. Since you have three separate read operations,
and one i2c_read() is done in each one, then you need to do a
NAK in each of them. This is done by adding a 0 parameter to
the statement. Example:
Quote:

data1 = I2C_READ(0);
break;
edbfmi1



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

PostPosted: Mon Aug 21, 2006 9:30 am     Reply with quote

Thanks PCM programmer!!!
That is what I was needing.
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