|
|
View previous topic :: View next topic |
Author |
Message |
AdamkT1
Joined: 21 Apr 2007 Posts: 44
|
pic16f84 I2C problems with 24LC00 EEPROM |
Posted: Fri May 04, 2007 9:01 am |
|
|
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.
Adam Katana
#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
|
|
Posted: Fri May 04, 2007 10:22 am |
|
|
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
|
|
Posted: Sat May 05, 2007 11:12 am |
|
|
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
|
|
Posted: Sat May 05, 2007 10:42 pm |
|
|
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
|
|
Posted: Sun May 06, 2007 6:06 am |
|
|
Thank you PCM programmer . 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.
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
|
|
Posted: Sun May 06, 2007 6:24 am |
|
|
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
|
|
Posted: Sun May 06, 2007 7:02 am |
|
|
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
|
|
Posted: Sun May 06, 2007 2:30 pm |
|
|
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);
}
} |
|
|
|
|
|
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
|