|
|
View previous topic :: View next topic |
Author |
Message |
NWilson
Joined: 30 Jun 2011 Posts: 21 Location: King's Lynn. England
|
I2C Slave problem using a PIC24 |
Posted: Thu Jun 30, 2011 9:42 am |
|
|
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
|
I2C Slave problem using a PIC24 |
Posted: Sun Jul 03, 2011 7:51 am |
|
|
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: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Jul 03, 2011 3:33 pm |
|
|
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
|
|
Posted: Sun Jul 03, 2011 3:43 pm |
|
|
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: 19496
|
|
Posted: Sun Jul 03, 2011 4:05 pm |
|
|
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
|
|
Posted: Mon Jul 04, 2011 1:44 am |
|
|
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
|
|
Posted: Tue Jul 05, 2011 10:06 am |
|
|
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
|
|
Posted: Tue Jul 05, 2011 10:46 am |
|
|
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 |
|
|
|
|
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
|