View previous topic :: View next topic |
Author |
Message |
denis_11
Joined: 13 Jul 2010 Posts: 45
|
routine I2C and 16f84 |
Posted: Tue Jul 13, 2010 8:10 am |
|
|
Hello I am working with this program written with CCS to write or read a byte on a small EEPROM... yet it is only experimental work then I will use larger memory eeprom... firmware works with a PIC16F84, but when I go to try the program happens that the byte is not written in eeprom... where am I wrong? I do not want to use the library of CCS but I want to use that I posted because I want to understand precisely how it works ...
Last edited by denis_11 on Tue Jul 13, 2010 12:35 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue Jul 13, 2010 9:05 am |
|
|
The first obvious thing is that your ACK/NACK handling is wrong.
It is the receiver that acknowledges. When sending, you simply generate an extra clock, and _read_ what is coming from the other chip, to find out if it acknowledged. You are outputting a bit here - don't. The logic is also reversed. an _ACK_, is low from the receiving device. A 'NACK', is high from the receiving device. The only time the master generates either ACK or NACK, is when it is the receiving device, and it then acknowledges the bytes, and _must_ NACK the last byte in the transfer.
This may be the main problem....
Obvious comments apply about 'have you got the pull up resistors on the lines'. Something like 2K2R.
Best Wishes |
|
|
denis_11
Joined: 13 Jul 2010 Posts: 45
|
|
Posted: Tue Jul 13, 2010 9:13 am |
|
|
So I use two 10k resistors on the lines as pull-up... then you say to solve the problem so?
Code: |
void random_write(byte mem_adr, byte dat)
{
i2c_start();
i2c_out_byte(0xa0);
i2c_ack();
i2c_out_byte(mem_adr); // high byte of memory address
i2c_ack();
i2c_out_byte(dat); // and finally the data
i2c_nack();
i2c_stop();
delay_ms(25); // allow for the programming of the eeprom
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue Jul 13, 2010 9:37 am |
|
|
_NO_....
For your byte writes, _you_ never generate either an ACK, or NACK. The slave chip does this. Your byte write routine, needs something like:
Code: |
int1 i2c_out_byte(byte o_byte) {
byte n;
int1 ACK;
for(n=0; n<8; n++)
{
if(o_byte&0x80)
{
i2c_high_sda();
}
else
{
i2c_low_sda();
}
i2c_high_scl(); //Are you sure the chip can accept only 1uSec here...
i2c_low_scl();
o_byte = o_byte << 1;
}
i2c_high_scl();
SDA_DIR=1; //You _must_ leave the line floating
i2c_low_scl(); //Now generate a ninth clock
delay_us(2)
ACK=SDA_PIN; //read the ACK
i2c_high_scl(); //You must release both clock and data at the end
//of every transaction....
return ACK;
}
|
Your code needs to check that ACK was low (this is the 'ACK').
When you are reading bytes, you again need to generate the ninth clock, pulling the data line low, except for the last byte, when you then let the SDA line go high (NACK).
Best Wishes |
|
|
|