|
|
View previous topic :: View next topic |
Author |
Message |
snowbell Guest
|
i2c works for breadboard but not on pcb |
Posted: Wed Feb 17, 2010 2:02 am |
|
|
Hi,
I have tested I2C by sending from master to slave on both breadboard and PCB. However, it works only on the breadboard. I tried receiving from slave on the PCB too and it works. Anyone can help? Below is the code I used to send a byte from master to slave and slave will light a LED appropriately.
Also, the master needs to write to the internal register (0x00 in this case), but how do we actually identify the register? Thanks alot for the help.
Master:
Code: |
#if defined(__PCH__)
#include <18F2620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3)
#define SLAVE1_WRT_ADDR 0x12 //LSB=0
#define SLAVE1_READ_ADDR 0x13 //LSB=1
//====================================
void main()
{
int8 cmd = 0x01;
while(1)
{
if(cmd == 0x00)
{
cmd = 0x01;
output_high(PIN_B4);
}
else
{
cmd = 0x00;
output_low(PIN_B4);
}
delay_ms(1000);
i2c_start();
i2c_write(SLAVE1_WRT_ADDR);
i2c_write(0x00);
i2c_write(cmd);
i2c_stop();
}
} |
Slave:
Code: |
#if defined(__PCH__)
#include <18F2620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=12000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)
int8 data;
BYTE address, buffer[0x10];
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
{
address = incoming;
data = incoming;
}
if(state == 2) //Second received byte is data
{
buffer[address] = incoming;
//data = incoming;
}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(buffer[address]);
}
}
//======================================
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
//set_tris_c(0x01);
while(1)
{
if (data == 0x01)
output_high(PIN_C5);
if (data == 0x00)
output_low(PIN_C5);
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 17, 2010 3:15 am |
|
|
In I2C, there are normally really two 'addresses'. The device 'address', and the register 'address'.
The standard packet for a write, is:
START
DEVICE ADDRESS
REGISTER ADDRESS
DATA to the required register....
STOP
Then for read, you use:
START
DEVICE ADDRESS (still the _write_ address)
REGISTER ADDRESS
START (this is called a 'restart')
DEVICE ADDRESS (the read one this time)
DATA from the selected register....
STOP
What is done, is you start just like a write transaction, including _writing_ the required device address, and then issue another start, followed by the command to turn the bus round to read, and the required read(s).
So in your 'master', to read back the byte you have sent:
Code: |
i2c_start();
i2c_write(SLAVE1_WRT_ADDR);
i2c_write(0x00); //You have now selected 'address 0' in the slave
i2c_start(); //Issue the 'restart'
i2c_write(SLAVE_READ_ADDR); //Say we want to read
val=i2c_read(); //and get the data
i2c_stop();
|
If you modify the slave code, so that all states, 2 and above (up to 7F) put the data into the addressed byte, and then _increment_ the address., and all ones over 80, write the byte, and then increment the address, you can perform multiple writes one after the other, sending several bytes, and do the same when reading, getting several bytes back, after the initial 'setup'.
Ideally add limit checks to 'address', so it can't accidentally go outside the data array beng used.....
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 17, 2010 3:58 am |
|
|
On the breadboard versus PCB, you just need to start with standard debugging. Really careful inspection for solder whiskers, verify if the processors are working (flash an LED), and at the right rate. Then try just programming each of the lines as an input on one processor, and then setting the other to move it high/low. verify it does go up/down properly, and adjacent lines do not. You almost certainly have:
1) A whisker.
2) A break.
3) A wrong connection.....
Best Wishes |
|
|
snowbell Guest
|
|
Posted: Wed Feb 17, 2010 11:55 pm |
|
|
Thanks Ttelmah. I have tried to check all the connections, and they are correct.
The difference I realised between my breadboard and PCB is that I'm using internal oscillator at 8MHz for the breadboard and HS oscillator at 12MHz for the PCB. Indeed, when I tried 8MHz internal osc on the PCB to run I2C, it worked.
Are there any possible reasons for this besides the crystal being spoilt, as I don't have access to an oscilloscope now. Thanks. |
|
|
Ttelmah Guest
|
|
Posted: Thu Feb 18, 2010 3:24 am |
|
|
Too much capacitance round the oscillator pins. Typically ground plane too close to the oscillator tracks.
Wrong loading capacitors (typically something between 18, and 27pF would be required for most crystals).
Wrong crystal type (PIC requires a parallel resonant type).
A whisker on one of the oscillator pins.
etc.....
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
|