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

I2C Slave problem using a PIC24

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



Joined: 30 Jun 2011
Posts: 21
Location: King's Lynn. England

View user's profile Send private message

I2C Slave problem using a PIC24
PostPosted: Thu Jun 30, 2011 9:42 am     Reply with quote

I2C Slave problem using a PIC24

Info: PIC16F876A I2C Master to a PIC24FJ64GA006
Compiler PCWHD Version 1.122
Slave address 0x12

Problem: I’m about to design a sensor that communicates with a control box using I2C. This is the first time I have used I2C, I normally use SPI.

To get myself going I built one ‘Master Test Jig’ with an RS232 interface, so that I could display the received values using HyperTerminal and one ‘Slave Test Jig’ both jig’s use PIC16F876A’s, and both appear to work perfectly.

I have now built a new ‘Slave’ using a PIC24FJ64GA006 but no matter how hard I try, I cannot get it to work, the slave seems to lock up when sending the requested data back to the master.


Master Code
Code:

//*****************************************************************
// PIC16F876A I2C Master test program
// main.c
// Rev         : 1.00
// Start Date  : 30th June 2011
// Author      : N. Wilson.
//*****************************************************************

#include <16F876A.h>  // PIC16F876 definitions (include before anything else)

#case
#device adc=8

#fuses HS,NOWDT,BROWNOUT,PUT,NOLVP

#use delay(clock=18432000, restart_wdt)
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)

#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13

// Global variables
unsigned int8 g_msb, g_lsb, g_chk;

//*************************************************************************
// Function    : main program function
//**************************************************************************
void main(void)
{
   for(;;)
   {
      // Write to the slave
      i2c_start ();
      i2c_write (SLAVE1_WRT_ADDR);         // Device address is the top seven bits. The bottom bit sets the direction
      i2c_write ('b');                     // Send command 'b' to the slave
      i2c_stop ();
     
      // Read from the slave
      i2c_start ();                        // Change direction (read)
      i2c_write (SLAVE1_READ_ADDR);         // Slave device address, direction = read
      g_msb = i2c_read();                  // Read msb from slave
      g_lsb = i2c_read();                  // Read lsb from slave
      g_chk = i2c_read(0);                  // Read simple checksum from slave
      i2c_stop();
      
      putc(27);putc(91);putc(50);putc(74);   // Clear Hyperterminal screen = esc[2J
      
      printf("PIC16F876A I2C Master Test Jig.\n\r\n\r");
      printf("Data received  MSB  LSB  ChkSum\n\r\n\r");     
      printf("               %u   %u   %u", g_msb, g_lsb, g_chk);
      delay_ms(1000);
   }
}
//********************** End of main loop ************************************


Slave that seems to work ok

Code:

//*****************************************************************
// PIC16F876A I2C Slave test program
// main.c
// Rev         : 1.00
// Start Date  : 30th June 2011
// Author      : N. Wilson.
//*****************************************************************

#include <16F876A.h>  // PIC16F876 definitions (include before anything else)
#device adc=10
#device icd=true

#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP

#use delay(clock=18432000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)

#define COMMAND   0x00

// Global variables
unsigned int16 g_Send_Value = 0xc22;
unsigned int8 rcv_buffer[8], send_buffer[8];
unsigned int8 g_Data_Received = FALSE;

//*************************************************************************
// Function    : Interrupt service routine
//*************************************************************************

#INT_SSP
void ssp_interupt (void)
{
   BYTE state;
   
   state = i2c_isr_state();

   if((state== 0 ) || (state== 0x80))        // Address match received
      i2c_read();                            // Read I2C address

   if(state >= 0x80)                         // Transmission completed and acknowledged
      i2c_write(send_buffer[state - 0x80]);  // Preload the transmit buffer for next read by master

   else if(state > 0)                        // Master has writen data
   {
      rcv_buffer[state - 1] = i2c_read();    // Read data sent by master and put into receive buffer
      g_Data_Received = True;
   }
}


//*************************************************************************
// Function    : main program function
//*************************************************************************

void main()
{
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   
   for(;;)
   {
      restart_wdt();
      if (g_Data_Received == TRUE)
      {
         g_Data_Received = FALSE;
         
         switch (rcv_buffer [COMMAND])
         {
            case  'b'   :  send_buffer [0] = make8 (g_Send_Value, 1);                  // msb
                           send_buffer [1] = make8 (g_Send_Value, 0);                  // lsb
                           send_buffer [2] = (send_buffer[0]+send_buffer[1]) & 0xff;   // checksum
                           break;
            default     :  send_buffer [0] = 0;
                           break;
         }
      }
   }
}
 //********************** End of main loop ********************************



Slave that doesn't work

Code:


//*****************************************************************
// PIC24FJGA006 I2C Slave test program
// main.c
// Rev         : 1.00
// Start Date  : 30th June 2011
// Author      : N. Wilson.
//*****************************************************************

#include <24FJ64GA006.h>
#device ICD=TRUE

#FUSES DEBUG                     //Debug mode for use with ICD
#FUSES WDT32                     //Watch Dog Timer PreScalar 1:32 = 1mS
#FUSES WPOSTS12                  //Watch Dog Timer PostScalar 1:2048 WDT times out every 2.048 Seconds
#FUSES WDT
#FUSES ICSP1                     //ICD uses PGC1/PGD1 pins
#FUSES NOJTAG                    //JTAG disabled
#FUSES NOCKSFSM                  //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES FRC_PLL                   //Internal Fast RC oscillator with PLL
#FUSES NOIESO                    //Internal External Switch Over mode disabled
#FUSES OSCIO                     //OSC2 is general purpose output

#use delay (clock=32M, internal=8M,RESTART_WDT )

#use i2c(SLAVE, SDA=PIN_G3, SCL=PIN_G2,  address=0x12)

#define COMMAND   0x00

// Global variables
unsigned int16 g_Send_Value = 0xc22;
unsigned int8 rcv_buffer[8], send_buffer[8];
unsigned int8 g_Data_Received = FALSE;

//*************************************************************************
// Function    : Interrupt service routine
//*************************************************************************

#INT_SI2C
void SI2C_isr (void)

   unsigned int8 state;
   
   state = i2c_isr_state();

   if((state== 0 ) || (state== 0x80))        // Address match received
      i2c_read();                            // Read I2C address

   if(state >= 0x80)                         // Transmission completed and acknowledged
      i2c_write(send_buffer[state - 0x80]);  // Preload the transmit buffer for next read by master

   else if(state > 0)                        // Master has writen data
   {
      rcv_buffer[state - 1] = i2c_read();    // Read data sent by master and put into receive buffer
      g_Data_Received = TRUE;
   }
   return;
}

//*************************************************************************
// Function    : main program function
//*************************************************************************
           
void main()
{
   enable_interrupts(INT_SI2C);               // I2C2 interrupt from master control box
   enable_interrupts(INTR_GLOBAL);
   
   for(;;)
   {
      restart_wdt();
      if (g_Data_Received == TRUE)
      {
         g_Data_Received = FALSE;
         
         switch (rcv_buffer [COMMAND])
         {
            case  'b'   :  send_buffer [0] = make8 (g_Send_Value, 1);                  // msb
                           send_buffer [1] = make8 (g_Send_Value, 0);                  // lsb
                           send_buffer [2] = (send_buffer[0]+send_buffer[1]) & 0xff;   // checksum
                           break;
            default     :  send_buffer [0] = 0;
                           break;
         }
      }
   }
}
 //********************** End of main loop ********************************


As you can see they are nearly identical.
Any ideas,

Regards Neil
NWilson



Joined: 30 Jun 2011
Posts: 21
Location: King's Lynn. England

View user's profile Send private message

I2C Slave problem using a PIC24
PostPosted: Sun Jul 03, 2011 7:51 am     Reply with quote

Any useful help would be appreciated . In addition to the above post, the master (PIC16) has 1k8 pull-ups on both I2C lines and is running at +5V whilst the slave (PIC24) is running of +3.3V. Am I right in assuming that the I2C on the slave is +5V tolerant? also I'm not totally sure about the fuses on the PIC24 although the device seems to be running ok. If there is no obvious coding errors could this be a bug with my CCS compiler?
Regards
Neil
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jul 03, 2011 3:33 pm     Reply with quote

My gut says that BOTH PICs must be either 5 volt or 3.3 volt. The 3 volt PIC won't be able to go high enough for the 5 volt PIC to see a logic one.
As well the 5 volt PIC could 'overdrive' the 3 volt PIC...

If true(others will know for sure) then either you'll have to add 'level translators' to the PIC24.... OR get a 3V(LF) version of the host PIC.

I'll assume you've run the basic 'Hello World' program on the 24 PIC to verify 'all is ok' ??
NWilson



Joined: 30 Jun 2011
Posts: 21
Location: King's Lynn. England

View user's profile Send private message

PostPosted: Sun Jul 03, 2011 3:43 pm     Reply with quote

Hi temtronic, thanks for replying. I don't think the PIC24 running from 3.3V should be a problem because of the 1k8 pull-up resistors. I am concerned about whether it is 5 volt tolerant on these pins though. The data sheet is not very clear. I have connected a 2 x 16 character lcd display the PIC24 for diagnostics and that is working ok.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Sun Jul 03, 2011 4:05 pm     Reply with quote

According to the data sheet, the 5v input tolerance, does not apply to the I2C (silly I know....). Look at parameter D128, in table 26-8.

Best Wishes
NWilson



Joined: 30 Jun 2011
Posts: 21
Location: King's Lynn. England

View user's profile Send private message

PostPosted: Mon Jul 04, 2011 1:44 am     Reply with quote

Hi Ttelmah, I must admit that I was cautious about using SDA2 and SLA2 (Pins 31 and 32) in my design because of the extra functionality on these pins, however I thought that SDA1 and SLA1 would be ok as they appear to be digital I/O pins with ST buffers.
I have noticed that on some device datasheets, that Microchip have started to shade +5.5V tolerant pins in the pin diagrams. I just wish that they had done that with this one. Back to the drawing board then.
Regards
Neil
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Jul 05, 2011 10:06 am     Reply with quote

Whenever I have devices that use different voltages for supplies I _always_ use a voltage level translator like the MAX 3371. I've been bitten with that one before so I always design on the side of caution.

One thing to be aware of, both your master and slave are running at the same clock speed. Your master code is spitting out commands as fast as it can. Now, the slave needs a certain amount of time to process each command it receives and could miss one, or more, of the commands the master is sending. Try placing delays between each command and see if that makes things work better. Better yet, get an o-scope and look at the signals to see what's going on.

Ronald
NWilson



Joined: 30 Jun 2011
Posts: 21
Location: King's Lynn. England

View user's profile Send private message

PostPosted: Tue Jul 05, 2011 10:46 am     Reply with quote

Hi Ronald,

After reading Ttelmah reply and after doing further research on Microchips website, I suspect that I may have, to put it politely , broken my PIC24. It appears that the I2C is not 5V tolerant and in hindsight I should have used some level translation between the two Pics.
I've decided to base my sensor (slave) on one of the faster PIC18 series chips and keep it all 5V.
Out of interest does anyone know if CCS's compiler supports 'Clock Stretching' so that I don't have to worry too much about delays in the master?

Regards Neil
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