|
|
View previous topic :: View next topic |
Author |
Message |
mateeb4u@gmail.com
Joined: 07 Feb 2012 Posts: 19 Location: pakistan
|
I2c Theoretical Idea Problem |
Posted: Thu Feb 23, 2012 6:05 am |
|
|
I'm trying to communicate two pics 18f452 via I2c. I successfully achieve it after a lot of time with hit and trial method even i read about it allot.
Problem is transaction from master to slave & Slave to master Addressing:
In literature I read first byte, you write it as combination of address and least significant bit you which specify, to show your direction from master to slave or slave to master:
May master code is this:
This tell us slave address is 0x60 and adding least significant bit 1 (high) tell us master is writing and slave is reading. Slave address we specify should be 0x60
But with this it is not working.
When I use use slave code which i posted down below in which i specify 0xc0, it works, so it does not fulfill the condition of literature.
Code: |
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x60)
|
Code: |
#include <18F452.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,address=0x60)
void main ()
{
while(1)
{
i2c_start();
i2c_write(0xc0);
delay_ms(1000);
i2c_write(0x2);
output_a(0x2);
delay_ms(1000);
i2c_write(0x3);
output_a(0x3);
delay_ms(1000);
i2c_write(0x4);
output_a(0x4);
delay_ms(1000);
i2c_write(0x5);
output_a(0x5);
delay_ms(1000);
i2c_stop();
}
}
|
Slave:
Code: |
#include <18F452.h> // #include <18F458.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xC0)
BYTE datar;
#INT_SSP
void ssp_interupt ()
{
BYTE state;
//printf("*/n");
state = i2c_isr_state(); //0 - Address match received with R/W bit clear
//1-0x7F - Master has written data; i2c_read() will immediately return the data
//0x80 - Address match received with R/W bit set; respond with i2c_write()
//0x81-0xFF - Transmission completed and acknowledged; respond with i2c_write()
if(state == 0x00)
{
datar=i2c_read();
//printf("Adress match:%x\n",datar);
output_a(datar);
}
else if(state > 0 && state < 0x80)
{
datar= i2c_read();
//printf("Bytes:%x\n",datar);
//datar=0x00;
output_a(datar);
}
else if(state == 0x80)
{
i2c_write(dataw);
//printf("Data write on Master:%x\n",dataw);
}
else if(state > 0x80 && state < 0x100)
{
//printf("Data has been acknowledged\n");
}
}
void main ()
{
//port_b_pullups(TRUE);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Thu Feb 23, 2012 7:45 am |
|
|
just some quick comments.
1) You should think of the least significant bit as how the MASTER deals with 'data'. The Master either reads from or writes to a SLAVE. The MASTER is in control, not the slave.
2) In your master program, while you specify the address of the slave to be 0x60, you don't use the variable 'address' when communicating to the slave. You use....
i2c_start();
i2c_write(0xc0);
And the 0xc0 is the I2C address that you are writing( communicating) to.
you should try....
i2c_write(address); and see what happens... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Thu Feb 23, 2012 10:34 am |
|
|
If you look again, his slave is address 0xC0.
However he is specifying an address for the master. _Master devices don't have an address_. This needs to be removed.
I think he is confusing the LSb with the MSb.
Then get rid of the delays. These _will_ cause problems.
Then look again at what happens with state=0x80. This particular state _requires_ you to first read the byte from the I2C register, and then write the data you want to send back. You get here when the address is _received_ for an I2C read by the master. Not reading the byte will mean the bus is not released.
Then there is a problem with the final test. A byte can never be 0x100 (8 bits only). so the test must be:
else if(state > 0x80)
You have already tested for all lower state values...
and, this _must_ write a byte.
If you want to delay, then _stop_, delay, and start again. So:
Code: |
#include <18F452.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3)
#define READ_ADDRESS 0x61
#define WRITE_ADDRESS 0x60
void main (void) {
int8 ctr, dummy;
while(1) {
//Write four bytes at 1 second intervals
for (ctr=2;ctr<5;ctr++) {
i2c_start();
i2c_write(WRITE_ADDRESS);
i2c_write(ctr);
i2c_stop();
output_a(ctr);
delay_ms(1000);
}
//Now read four bytes at 1 second intervals - get back ctr*2
for (ctr=2;ctr<5;ctr++) {
i2c_start();
i2c_write(WRITE_ADDRESS);
i2c_write(ctr); //send ctr to slave
i2c_write(READ_ADDRESS); //This is an I2C _restart_ used to change
//bus direction so you can _write_ a register number to retrieve
//and then read back the contents
dummy=i2c_read(); //get reply from slave
i2c_stop();
output_a(dummy);
delay_ms(1000);
}
}
}
Slave:
#include <18F452.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x60)
BYTE datar;
#INT_SSP
void ssp_interupt (void) {
BYTE state;
static int8 reg_num_sent;
int8 dummy;
state = i2c_isr_state();
if (state == 0x00) {
//Here _address_ has been received, not data.
dummy=i2c_read();
}
else if(state > 0 && state < 0x80) {
datar= i2c_read();
output_a(datar);
//First data byte received is normally used as the 'register address'
//to say what you want to read/write back
if (state==1) reg_num_sent=datar;
}
else if(state == 0x80) {
dummy=i2c_read();
i2c_write(reg_num_sent*2);
}
else if(state > 0x80) {
i2c_write(reg_num_sent*2);
}
}
void main (void) {
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {}
}
|
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Thu Feb 23, 2012 10:44 am |
|
|
hmmm.. I thought the 'address' definition meant the default address of the slave he would talk to.
Easy to get confused when you cut your own drivers and think everyone else does what you do... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Thu Feb 23, 2012 3:20 pm |
|
|
Yes. Having 'address' at the start of the master code had me confused as well. Then 'twigged' what was going on. As I say confusing the MSb with LSb, so he is trying to use 0x60, and 0xC0 for read/write.... :(
Aargh!.
Best Wishes |
|
|
|
|
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
|