|
|
View previous topic :: View next topic |
Author |
Message |
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
Pic to Pic with I2C |
Posted: Fri May 12, 2006 12:28 am |
|
|
Sorry for my English,
I have connected 2 pic with i2c, master and slave.
I have used the code:
MASTER (similar 2401.C)
Code: | #ifndef EEPROM_SDA
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#endif
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL,RESTART_WDT)
#define EEPROM_ADDRESS BYTE
#define EEPROM_SIZE 128
void init_ext_eeprom() {
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
BOOLEAN ext_eeprom_ready() {
int1 ack;
i2c_start(); // If the write command is acknowledged,
ack = i2c_write(0xa0); // then the device is ready.
i2c_stop();
return !ack;
}
void write_ext_eeprom(BYTE address, BYTE data) {
while(!ext_eeprom_ready());
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_write(data);
i2c_stop();
}
BYTE read_ext_eeprom(BYTE address) {
BYTE data;
while(!ext_eeprom_ready());
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
buffer_i2c[0] = data;
return(data);
}
void read_ext_eeprom_n(byte address_start, byte n)
{
BYTE data;
BYTE contatore;
if (n <= LEN_BUFFER_I2C)
{
while(!ext_eeprom_ready());
i2c_start();
i2c_write(0xa0);
i2c_write(address_start);
i2c_start();
i2c_write(0xa1);
if(n>1) // se n non � valio o se vale 1
{
for(contatore=0; contatore <=(n-1); contatore ++)
{
buffer_i2c[contatore] = i2c_read(1);
}
buffer_i2c[n] = i2c_read(0);
}
else
{
buffer_i2c[0] = i2c_read(0);
}
i2c_stop();
}
}
void main()
{
int8 data;
int8 address;
init();
lcd_init();
init_ext_eeprom();
lcd_putc("\f");
while(1)
{
lcd_putc("\f");
address = 0xB8;
data = 0xBB;
write_ext_eeprom(address,data);
delay_ms(6000);
data = read_ext_eeprom(address);
PutHex_lcd(data);
delay_ms(500);
}
}
|
SLAVE:
Code: |
//SLAVE INTERRUPT HANDLER..............
#INT_SSP
interrupt_ssp()
{
int bo,dummy;
bo=0;
if (bit_test(SSPCON,OVERFLOW_BIT))
{
// clear the buffer
dummy = SSPBUF;
// Clear the register
bit_clear(SSPCON,OVERFLOW_BIT);
}
// we are done since we got a stop
else if (bit_test(SSPSTAT,STOP_BIT))
{
// since we are done, lets just reset everything
// pData = 0;
// data = 0;
}
else
{
bo=0;
switch(SSPSTAT & 0x2D)
{ // Keep only bits D/A, S, R/W, BF
case STATE1 :
// Master write operation, address byte in SSPBUF
// Clear the data buffer
//for(rindex=0;rindex < 16; rindex++)
//rbuf[rindex]=0;
rindex = 0;
SSPOV = 0; // Clear address overflow flag, could be set from last
// time because after not /ack, SSPBUF was still full.
addrbyte = SSPBUF; // Dummy read to clear BF (read only bit)
break;
case STATE2 :
// Master write operation, data byte in SSPBUF
// Get data byte (also clears BF)
SSPOV = 0;
// sbuf[sindex++]=SSPBUF; // rbuf[rindex++]=SSPBUF;
rbuf[rindex++]=SSPBUF;
if (rindex == 2)
{
bo = 0; // break =????
}
break;
case STATE3 :
// Master has begin new read operation by initiating a START or RESTART
// then sending Slave address (read) byte (now in SSPBUF).
// Looks like clock enable bit CKP cleared on interrupt, so must
// set it again to allow Master to clock data byte out
// SCL held low, Master can be kept waiting here if necessary
sindex = 0; // Reset buffer index
// SSPBUF = sbuf[sindex++]; // Load 1st byte from data buffer
// SSPBUF = lati_longi[sindex++];
SSPBUF = *rbuf[0]++;
CKP = 1; // Enable SCL for Master to shift byte out
break;
case STATE4 :
// Master read operation, last byte was data, SSPBUF empty
// Move next byte to SSPBUF and SSPSR
// Same comment for CKP bit as in STATE3
// SSPBUF = sbuf[sindex++]; // Get next byte from data buffer
// SSPBUF = lati_longi[sindex++]; SSPBUF = *rbuf[0]++;
CKP = 1; // Enable SCL for Master to shift byte out
break;
case STATE5 :
// A not /ack (high) was received from Master in response to data
// byte received from Slave (last byte). Slave i2c logic is reset,
// and waits for next Master operation.
bo=0;
break;
default:
// Error, trap here. Watchdog will reset pic (must be enabled, and
//watchdog timer cleared in other loops)
//while(1);
icbus_init();
break;
}
}
}
|
the reading from master to Slave is corrected also sequential reading
but I do not succeed in writes an address in the Slave
task lacks a code in interrupt Slave
Thanks in advance |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Fri May 12, 2006 8:35 am |
|
|
You need to make sure that the Slave has enough time to service the interrupt before the Master tries to continue sending more i2c commands or else it might hang. It takes a bit for the Slave to save everything and get to the isr.
Try having a pin pulse, in the Slave isr routine, and put a scope on it. Monitor your i2c bus as well and look at the timing between the commands and the pulse signal. If the pulse occurs _after_ the Master starts sending the next i2c_write(), i2c_read() or i2c_stop() then you will need to put a delay between the commands to ensure the Slave has the time to do it's thing.
I've, also, had to monitor the SSPSTAT register and output it to a port, with LED's connected, to see what the Slave was seeing so I could tell what conditions to look for. I would have the Master single step it's commands when I did this.
Ronald |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Fri May 12, 2006 9:59 am |
|
|
Thanks,
task is not poblema of speed,
if, from the master I read one location (address) in the Slave, it works well.
I use ICD2.
I do not understand in the ruotine of interrupt where I can find the address and the data when use the masyer for write an address in the Slave
CODE MASTER:
Code: |
void write_ext_eeprom(BYTE address, BYTE data) {
while(!ext_eeprom_ready());
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_write(data);
i2c_stop();
} |
in that point of the routine interrupt Slave I find address and data sending
by master ?
Code: |
//SLAVE INTERRUPT HANDLER..............
#INT_SSP
interrupt_ssp()
{
int bo,dummy;
bo=0;
if (bit_test(SSPCON,OVERFLOW_BIT))
{
// clear the buffer
dummy = SSPBUF;
// Clear the register
bit_clear(SSPCON,OVERFLOW_BIT);
}
// we are done since we got a stop
else if (bit_test(SSPSTAT,STOP_BIT))
{
// since we are done, lets just reset everything
// pData = 0;
// data = 0;
}
else
{
bo=0;
switch(SSPSTAT & 0x2D)
{ // Keep only bits D/A, S, R/W, BF
case STATE1 :
// Master write operation, address byte in SSPBUF
// Clear the data buffer
//for(rindex=0;rindex < 16; rindex++)
//rbuf[rindex]=0;
rindex = 0;
SSPOV = 0; // Clear address overflow flag, could be set from last
// time because after not /ack, SSPBUF was still full.
addrbyte = SSPBUF; // Dummy read to clear BF (read only bit)
break;
case STATE2 :
// Master write operation, data byte in SSPBUF
// Get data byte (also clears BF)
SSPOV = 0;
// sbuf[sindex++]=SSPBUF; // rbuf[rindex++]=SSPBUF;
rbuf[rindex++]=SSPBUF;
if (rindex == 2) // ho ricevuto indirizzo e dato da scrivere ?
{
bo = 0;
}
break;
case STATE3 :
// Master has begin new read operation by initiating a START or RESTART
// then sending Slave address (read) byte (now in SSPBUF).
// Looks like clock enable bit CKP cleared on interrupt, so must
// set it again to allow Master to clock data byte out
// SCL held low, Master can be kept waiting here if necessary
sindex = 0; // Reset buffer index
// SSPBUF = sbuf[sindex++]; // Load 1st byte from data buffer
// SSPBUF = lati_longi[sindex++]; // qui scrivo il byte che voglio rimandare indietro
SSPBUF = *rbuf[0]++; // leggo il contenuto della locazione richiesta
CKP = 1; // Enable SCL for Master to shift byte out
break;
case STATE4 :
// Master read operation, last byte was data, SSPBUF empty
// Move next byte to SSPBUF and SSPSR
// Same comment for CKP bit as in STATE3
// SSPBUF = sbuf[sindex++]; // Get next byte from data buffer
// SSPBUF = lati_longi[sindex++]; // se la richiesta � una lettura sequenziale continuo
SSPBUF = *rbuf[0]++;
CKP = 1; // Enable SCL for Master to shift byte out
break;
case STATE5 :
// A not /ack (high) was received from Master in response to data
// byte received from Slave (last byte). Slave i2c logic is reset,
// and waits for next Master operation.
bo=0;
break;
default:
// Error, trap here. Watchdog will reset pic (must be enabled, and
//watchdog timer cleared in other loops)
//while(1);
icbus_init();
break;
}
}
}
|
sorry and thanks |
|
|
|
|
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
|