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

pic16f84 I2C problems with 24LC00 EEPROM

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



Joined: 21 Apr 2007
Posts: 44

View user's profile Send private message

pic16f84 I2C problems with 24LC00 EEPROM
PostPosted: Fri May 04, 2007 9:01 am     Reply with quote

Below is my code in CCS for saving data.

Before the function "write_ext_eeprom(5,data);", every thing goes fine but it seems that in this function, the program gets hooked up and never return and I find myself in the middle of "no-where"

I am using Proteus for the simulation.

Can any body correct me Pls. Question

Adam Katana Crying or Very sad


#include <16f84.h>
#define EEPROM_SCL PIN_A0
#define EEPROM_SDA PIN_A1
#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL)
#define EEPROM_ADDRESS byte
#define EEPROM_SIZE 256
//EEPROM = 24LC00, it can be any model.
// Configure PIC to use: XT clock, no code protection
// Disable Power Up Timer, no Watchdog Timer,
#fuses XT, NOPROTECT, NOPUT, NOWDT
// tell compiler clock is 4MHz. This is required for DELAY_MS()
// and for serial I/O, all of which use software delay loops.
#use delay (clock=4000000)

// declare that we'll manually establish the data direction of
// each I/O pin on ports A&B.
#use fast_io ( a )
#use fast_io ( b )

#byte PORT_A = 5 /* set variable that maps to memory */
#byte PORT_B = 6 /* set variable that maps to memory */

void init_ext_eeprom(void)
{
output_low(eeprom_scl);
output_high(eeprom_sda);
}

void write_ext_eeprom(byte address, byte data)
{
i2c_start();
i2c_write(0xa0);
PORT_B=0; // to debug, program never execyte this statemen.
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(11);
}

byte read_ext_eeprom(byte address)
{
byte data;
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}

void main(void)
{
byte data;

set_tris_a (0b00000000); /* set up I/O's */
set_tris_b (0b00000000); /* set up I/O's */

PORT_A=0;
PORT_B=0;

init_ext_eeprom();

while(1)
{
data=0xff; //just to debug

PORT_B=data;

delay_ms(500);

write_ext_eeprom(5,data);

PORT_B=0; //just to debug

data= read_ext_eeprom(5);

PORT_B=data;

delay_ms(500);
}
}
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri May 04, 2007 10:22 am     Reply with quote

Well, I'm no expert, by any means, but I have worked with I2C quite a bit.

Quote:
#define EEPROM_ADDRESS byte

The word 'byte' is already defined in the 16f84.h file. Change this.

Quote:
#use fast_io ( a )
#use fast_io ( b )

You're setting up the tris manually. I'm not sure if the i2c routines will override this. They need to switch from input to output and back. There's really no need to select fast_io in this simple routine.

I've never used Proteus so I don't know what other items might be needed.

Ronald
Guest








PostPosted: Sat May 05, 2007 11:12 am     Reply with quote

What I have been facing is:
How to make the program get out of the write function. Many ways come to mind for doing this including a timer interrupt routine. But what bothers me in that case that the write operation would not have been completed by then. So how would the data be written to the EPROM.?

Thanks for all the help.


rnielsen wrote:
Well, I'm no expert, by any means, but I have worked with I2C quite a bit.

Quote:
#define EEPROM_ADDRESS byte

The word 'byte' is already defined in the 16f84.h file. Change this.

Quote:
#use fast_io ( a )
#use fast_io ( b )

You're setting up the tris manually. I'm not sure if the i2c routines will override this. They need to switch from input to output and back. There's really no need to select fast_io in this simple routine.

I've never used Proteus so I don't know what other items might be needed.

Ronald
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 05, 2007 10:42 pm     Reply with quote

If your code hangs in the i2c_write() statement, it's because its stuck
in the clock stretching loop. This is a small loop in the CCS library code
that tests if the SCL line is low. If it's low, the code stays in a loop until it
goes high. (There's no timeout). This is part of the i2c protocol. Slow
slave devices are allowed to hold the clock line low until they're ready
to proceed.

For newbies, this normally happens if you forget to put in the pull-up
resistors. Add a 4.7K pull-up on both the SDA and the SCL lines.


Also, as said in prior posts, you should not be inventing your own init
code. CCS shows how to do it in their eeprom driver files. They set
both i2c lines as inputs ("float"). Do it that way. Don't set them low, etc.
Code:
void init_ext_eeprom()
{
 output_float(EEPROM_SCL);
 output_float(EEPROM_SDA);
}
AdamkT1



Joined: 21 Apr 2007
Posts: 44

View user's profile Send private message

PostPosted: Sun May 06, 2007 6:06 am     Reply with quote

Thank you PCM programmer Laughing . I have gone through a number of your suggestions on the topic to various people in trouble. I really appreciate your efforts and consistancy. Thanks alot to you and others for their help. Wink

With the addition of the two resistors, the programs does not hang any more.

The problem now is that it does not as I want it to.
The algo. is :
1) A varaible is initialized dat_W=0xff
2) To write 0xff in the EPROM at the mem_adr = 0x0700.
3) Read this value from the same location of EPROM and store in the variable dat_R.
4) Put this read value of dat_R on port b for display.
5) Toggle the value of dat_W from oxff to 0x00 or from 0x00 to 0xff depending upon its value.
6)Go through all the steps from 1 to 6.

The problem now is that I dont get the required display on Port b.

Below is the modified code. I request for valueable suggestions from all.

===============================================
#include <16f84.h>
#include <string.h>
#include <defs_f84.h>

#define EEPROM_SCL PIN_A0
#define EEPROM_SDA PIN_A1

#use delay (clock=4000000)

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

#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 65535

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

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();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
}

BYTE read_ext_eeprom(long int address)
{
BYTE data;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>8);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}


void main(VOID)
{
LONG mem_adr;
char dat_W, dat_R;

set_tris_b (0b00000000); /* set up I / O's */

dat_W=0xff;
dat_R=0;
mem_adr = 0x0700;
delay_ms(500);

WHILE (1)
{
write_ext_eeprom (mem_adr, dat_W);

dat_R = read_ext_eeprom (mem_adr);

delay_ms (500);
if(dat_W==0xff)
{
dat_W=0x00;
}
else
{
dat_W=0xff;
}

PORTB=dat_R;
delay_ms(500);
}//end while
}
faizanbrohi



Joined: 20 Sep 2006
Posts: 19

View user's profile Send private message

PostPosted: Sun May 06, 2007 6:24 am     Reply with quote

Hello everyone , I don't think PIC16F84 Supports Hardware I2C , and you are trying to use Hardware I2C with a device which does not have it. Try to build your own Software I2C Driver for this IC.
Ttelmah
Guest







PostPosted: Sun May 06, 2007 7:02 am     Reply with quote

faizanbrohi wrote:
Hello everyone , I don't think PIC16F84 Supports Hardware I2C , and you are trying to use Hardware I2C with a device which does not have it. Try to build your own Software I2C Driver for this IC.


The CCS I2C library, generates _software_ I2C, unless you tell it otherwise.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 06, 2007 2:30 pm     Reply with quote

Quote:
The problem now is that it does not as I want it to.
//EEPROM = 24LC00

In your first post, you said you're using a 24LC00. But in your latest
code, the driver is not for a 24LC00. It's for a larger EEPROM.


Here's the write routine from your first post. Notice that the address
parameter is only one byte. That's correct for a 24LC00.
Quote:
void write_ext_eeprom(byte address, byte data)
{
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(11);
}


Here's the write routine from your latest post. It's different. Notice
that the address parameter is now two bytes. The code shown below
will not work with a 24LC00. It will fail. You must use the correct
driver code for the eeprom type. (This also applies to the read routine).
Quote:
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();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
}
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