|
|
View previous topic :: View next topic |
Author |
Message |
Fabrici
Joined: 11 Feb 2013 Posts: 19 Location: Toulouse - France
|
dsPIC33 I2C interrupt doesn't trigger [solved] |
Posted: Wed Mar 20, 2013 9:46 am |
|
|
Hello,
I use two board, each with a dspic33, and want to establish a communication with i2c between them. My first board use two i2c links, and first link which is used to communicate with other peripherals works fine. But for the second .... I can't communicate with my slave board.
I've deleted all code that is not important for this issue, so you will not see I2C1 communication code (the one that works).
Master program :
Code: | #include <33EP256GP506.h>
#include <string.h>
#include <math.h>
#FUSES ICSP1 // ICD uses PGC1/PGD1 pins
#FUSES NOJTAG // JTAG disabled
#FUSES DEBUG // Debug mode for use with ICD
#fuses NOALTI2C1 // I2C1 mapped to ASDA1/ASCL1 pins
#fuses NOALTI2C2 // I2C2 mapped to ASDA2/ASCL2 pins
#FUSES NOWDT // No watchdog timer
#FUSES FRC_PLL //Internal Fast RC oscillator with PLL
#BUILD (STACK=0x1000:0x1200)
#USE delay (clock=50000000)
#USE I2C(MASTER, I2C1, STREAM=I2CM1)
#USE I2C(MASTER, I2C2, STREAM=I2CM2, slow)
#define SENSOR_1_ADD 0xDE
#define LED_BLINK PIN_A7
/////////////////////////
// Programme principal //
/////////////////////////
void main()
{
byte data;
output_low(PIN_B8); // Alimentation carte slave
do
{
i2c_start(I2CM2);
i2c_write(I2CM2, SENSOR_1_ADD);
i2c_write(I2CM2, 0x00);
i2c_write(I2CM2, 0x55);
i2c_stop(I2CM2);
output_high(LED_BLINK);
delay_ms(250);
output_low(LED_BLINK);
delay_ms(250);
} while (TRUE);
} |
slave program :
Code: | #include <33EP64GP503.h>
#fuses ICSP1 // ICD uses PGC1/PGD1 pins
#fuses NOJTAG // JTAG disabled
#fuses DEBUG // Debug mode for use with ICD
#fuses NOALTI2C2 // I2C2 mapped to SDA2/SCL2 pins
#fuses NOWDT // Watchdog timer enabled/disabled by user software
#FUSES FRC_PLL //Internal Fast RC oscillator with PLL
#USE delay (clock=50000000)
#USE I2C(SLAVE, I2C2, address=0xDE)
#define LED_BLINK PIN_C8
#INT_SI2C
void si2c_interrupt()
{
int i2c_status;
unsigned int8 i2c_value;
output_low(LED_BLINK);
i2c_status = i2c_isr_state();
if(i2c_status<0x80)
{
i2c_value = i2c_read(); //Master is sending a byte
}
if(i2c_status>=0x80)
{
if (i2c_status==0x80)
{
i2c_status=i2c_read(); //throw away the byte
}
i2c_write(0xAA); //Master is requesting data
//We reply to 0x80 with a 'write' as CCS indicates
} //Next status (0x81) will send the real data
}
/////////////////////////
// Programme principal //
/////////////////////////
void main()
{
enable_interrupts(INT_SI2C);
enable_interrupts(INTR_GLOBAL);
output_high(LED_BLINK);
do
{
} while (TRUE);
} |
I use the led to see if interrupt is fired, but nothing happens. This address seems to be a valid one, as I use it to communicate with another peripheral, on I2C1, on master board. I can see I2C signals with my oscilloscope, which seems to be fine.
May be someone could see my error ....
I use CCS PCD C Compiler, Version 4.141, 7054.
Best regards,
Fabrice
Last edited by Fabrici on Thu Mar 21, 2013 7:54 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Wed Mar 20, 2013 1:37 pm |
|
|
Any chip with re-mappable peripherals requires you to tell the compiler what pins you want the peripheral to use, before it'll work. Look at #pin select.
Best Wishes |
|
|
Fabrici
Joined: 11 Feb 2013 Posts: 19 Location: Toulouse - France
|
|
Posted: Thu Mar 21, 2013 5:07 am |
|
|
As always, you were right, Ttelmah. And something seems to have changed in communication :
* I2C master now is freezed when sending I2C trame, with SCL and SDA at low level.
* If I reset the slave board (with pick-it), I2C master restart running, until I launch slave board once again.
* If I change address on one device, Master don't freeze anymore.
* Slave board interrupt isn't triggered at all, in all case
==> This seems to indicate that I2C is running on hardware, and something happens on the slave chip. But for unknown reason, interrupt isn't triggered on slave chip, and slave chip seems to keep SDA and SCL pulled low, which cause master chip to freeze, until SDA and SCL are released.
Best regards,
Fabrice |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Thu Mar 21, 2013 6:36 am |
|
|
One critical (on some chips) thing. The slave must read on state = 0x80, before it writes. Otherwise the address byte is not read, and the clock won't release.
Best Wishes |
|
|
Fabrici
Joined: 11 Feb 2013 Posts: 19 Location: Toulouse - France
|
|
Posted: Thu Mar 21, 2013 7:25 am |
|
|
Thanks for the hint. It seems it is the case. I tested the following code :
Code: | #include <33EP64GP503.h>
#fuses ICSP1 // ICD uses PGC1/PGD1 pins
#fuses NOJTAG // JTAG disabled
#fuses DEBUG // Debug mode for use with ICD
#fuses NOALTI2C2 // I2C2 mapped to SDA2/SCL2 pins
#fuses NOWDT // Watchdog timer enabled/disabled by user software
#FUSES FRC_PLL //Internal Fast RC oscillator with PLL
#USE delay (clock=50000000)
//#USE I2C(SLAVE, I2C2, address=0xDE, stream=I2C2)
#USE I2C(SLAVE, SCL=PIN_B4, SDA=PIN_A8, address=0xDE, stream=I2C2)
#define LED_BLINK PIN_C8
#INT_SI2C
void si2c_interrupt()
{
int i2c_status;
unsigned int8 i2c_value;
//output_low(LED_BLINK);
output_toggle(LED_BLINK);
i2c_status = i2c_isr_state();
if(i2c_status<0x80)
{
i2c_value = i2c_read(); //Master is sending a byte
}
if(i2c_status>=0x80)
{
if (i2c_status==0x80)
{
i2c_status=i2c_read(); //throw away the byte
}
i2c_write(0xAA); //Master is requesting data
//We reply to 0x80 with a 'write' as CCS indicates
} //Next status (0x81) will send the real data
}
/////////////////////////
// Programme principal //
/////////////////////////
void main()
{
int i2c_status;
int8 i2c_data;
enable_interrupts(INT_SI2C);
enable_interrupts(INTR_GLOBAL);
output_high(LED_BLINK);
do
{
i2c_status = i2c_isr_state(I2C2);
i2c_data=i2c_read(I2C2);
if (i2c_status==0x80)
{
output_toggle(LED_BLINK);
}
delay_ms(100);
} while (TRUE);
} |
My master program don't freeze, and I can read :
i2c_data = 0xDE; i2c_status=0x00
i2c_data = 0x00; i2c_status=0x01
i2c_data = 0x55; i2c_status=0x02
That is exactly what master program send, but there are two strange things :
* i2c_status != 0x80 on receiving the address
* interrupt isn't triggered.
Best regards,
Fabrice |
|
|
Fabrici
Joined: 11 Feb 2013 Posts: 19 Location: Toulouse - France
|
|
Posted: Thu Mar 21, 2013 7:49 am |
|
|
I found it !! Thanks very much for your help Ttelmah.
Interrupt SI2C doesn't appear on DSPIC33EP64GP503 datasheet. But it is in CCS .h file.
So, I was waiting for an interrupt that didn't exist.
I replaced it by #INT_SI2C2, and slave program now works as intented.
Here is the modified code :
Code: | #include <33EP64GP503.h>
#fuses ICSP1 // ICD uses PGC1/PGD1 pins
#fuses NOJTAG // JTAG disabled
#fuses DEBUG // Debug mode for use with ICD
#fuses NOALTI2C2 // I2C2 mapped to SDA2/SCL2 pins
#fuses NOWDT // Watchdog timer enabled/disabled by user software
#FUSES FRC_PLL //Internal Fast RC oscillator with PLL
#USE delay (clock=50000000)
#USE I2C(SLAVE, SCL=PIN_B4, SDA=PIN_A8, address=0xDE, stream=I2C2)
#define LED_BLINK PIN_C8
#INT_SI2C2
void si2c_interrupt()
{
int i2c_status;
unsigned int8 i2c_value;
//output_low(LED_BLINK);
output_toggle(LED_BLINK);
i2c_status = i2c_isr_state();
if(i2c_status<0x80)
{
i2c_value = i2c_read(); //Master is sending a byte
}
if(i2c_status>=0x80)
{
if (i2c_status==0x80)
{
i2c_status=i2c_read(); //throw away the byte
}
i2c_write(0xAA); //Master is requesting data
//We reply to 0x80 with a 'write' as CCS indicates
} //Next status (0x81) will send the real data
}
/////////////////////////
// Programme principal //
/////////////////////////
void main()
{
int i2c_status;
int8 i2c_data;
enable_interrupts(INT_SI2C2);
enable_interrupts(INTR_GLOBAL);
output_high(LED_BLINK);
do
{
} while (TRUE);
} |
Do you think I must report this error in .h file to CCS ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Thu Mar 21, 2013 8:07 am |
|
|
SI2C, is the corresponding interrupt for I2C#1.....
Best Wishes |
|
|
Fabrici
Joined: 11 Feb 2013 Posts: 19 Location: Toulouse - France
|
|
Posted: Thu Mar 21, 2013 8:41 am |
|
|
Thanks for the explanation Ttelmah. This compiler is full of hidden tricks, and is really not easy to handle for a first project.
So we have INT_SPI1 for SPI #1, INT_SPI2 for SPI #2, INT_SI2C2 for slave I2C #2 and ... INT_SI2C for slave I2C1 . Good to know.
My index CCS documentation search was indicating : #INT_SI2C, #INT_SI2C1, #INT_SI2C2 (with #INT_SI2C1 that points nowhere). So, I thinked that INT_SI2C was a general interrupt for I2C, responding both to I2C1 and I2C2, while #INT_SI2C1 and #INT_SI2C2 were responding to I2C1 and I2C2, respectively.
One more time, your help has been very valuable. Thanks so much. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Thu Mar 21, 2013 9:11 am |
|
|
It's nice to see someone take hints, and move in the right direction.
Hope the rest of the project goes OK.
Best Wishes |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Jul 28, 2013 6:02 pm |
|
|
Code: | if(i2c_status>=0x80)
{
if (i2c_status==0x80)
{
i2c_status=i2c_read(); //throw away the byte
}
i2c_write(0xAA); //Master is requesting data
//We reply to 0x80 with a 'write' as CCS indicates
} |
i2c_status=i2c_read();// throw away the byte is better replaced by
i2c_value=i2c_read();
i2c_status is an index into the byte being sent by the master or the byte being requested from the slave by the master with a 0x80 offset only for the request. A i2c_status value of 0x80 points to the masters write (device addr+1) aka the read mode request. This read mode byte needs to be discarded before the requested data is sent ( in this case 0xAA ) |
|
|
|
|
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
|