View previous topic :: View next topic |
Author |
Message |
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);
}
} |
|
|
|
|