CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

dsPIC33 I2C interrupt doesn't trigger [solved]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Fabrici



Joined: 11 Feb 2013
Posts: 19
Location: Toulouse - France

View user's profile Send private message

dsPIC33 I2C interrupt doesn't trigger [solved]
PostPosted: Wed Mar 20, 2013 9:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 20, 2013 1:37 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 5:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 6:36 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 7:25 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 7:49 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 8:07 am     Reply with quote

SI2C, is the corresponding interrupt for I2C#1.....

Best Wishes
Fabrici



Joined: 11 Feb 2013
Posts: 19
Location: Toulouse - France

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 8:41 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 21, 2013 9:11 am     Reply with quote

It's nice to see someone take hints, and move in the right direction. Smile
Hope the rest of the project goes OK.

Best Wishes
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Sun Jul 28, 2013 6:02 pm     Reply with quote

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 )
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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