|
|
View previous topic :: View next topic |
Author |
Message |
neohimura
Joined: 08 Feb 2011 Posts: 14
|
PIC18F4550 master and DSPIC30F4011 slave i2c problem |
Posted: Mon Feb 20, 2012 1:46 am |
|
|
hi,
I have a project that requires I2C communication between one master (PIC18F4550) and three slave (two PIC18F4550 and one DSPIC30F4011) but the I2C communication does not work. The SCL pin is always 5V and the SDA pin is always 0V.
I tried to run with just the master and one DSPIC30F4011 but it did not work. I also tried changing the DSPIC slave i2c address to 0x52, 0x42, 0x60, 0x62 and 0x12 but none of them worked.
When I run it with only the PIC18F4550 master and two PIC18F4550 slaves over I2C, data is transmitted and received perfectly.
I have attached my coding.
MASTER
Code: |
#include <18F4550.h>
#FUSES HSPLL, NOWDT, NOPROTECT, NOBROWNOUT, STVREN, MCLR ,PLL5,CPUDIV1
#use delay(crystal=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7, bits=8,stream=PORT1)
#use i2c(MASTER,sda=PIN_B0,scl=PIN_B1,force_hw,slow)
unsigned int8 send_usb_data[18],val;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED|T1_DIV_BY_4);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
while(1)
{
// Write to the slave 1 board.(PIC18F4550)
i2c_start();
i2c_write(0x14);
i2c_write('A');
i2c_write('B');
i2c_write('C');
i2c_write('D');
i2c_write('E');
i2c_write('F');
i2c_stop();
// Read from the slave 2 board.
i2c_start();
i2c_write(0x15);
delay_us(10);
send_usb_data[0] = i2c_read();
send_usb_data[1] = i2c_read();
send_usb_data[2] = i2c_read();
send_usb_data[3] = i2c_read();
send_usb_data[4] = i2c_read();
send_usb_data[5] = i2c_read(0);
i2c_stop();
// Write to slave 2 board.(PIC18F4550)
i2c_start();
i2c_write(0x28);
i2c_write('G');
i2c_write('H');
i2c_write('I');
i2c_write('J');
i2c_write('K');
i2c_write('L');
i2c_stop();
// Read from the slave 2 board and display the data.
i2c_start();
i2c_write(0x29);
delay_us(10);
send_usb_data[6] = i2c_read();
send_usb_data[7] = i2c_read();
send_usb_data[8] = i2c_read();
send_usb_data[9] = i2c_read();
send_usb_data[10] = i2c_read();
send_usb_data[11] = i2c_read(0);
i2c_stop();
// Write to slave 3 board.(DSPIC30F4011)
i2c_start();
i2c_write(0x60);
i2c_write('m');
i2c_write('n');
i2c_write('o');
i2c_write('p');
i2c_write('q');
i2c_write('r');
i2c_stop();
// Read from the slave 3 board and display the data.
i2c_start();
i2c_write(0x61);
delay_us(10);
send_usb_data[12] = i2c_read();
send_usb_data[13] = i2c_read();
send_usb_data[14] = i2c_read();
send_usb_data[15] = i2c_read();
send_usb_data[16] = i2c_read();
send_usb_data[17] = i2c_read(0);
i2c_stop();
for (val=0;val<18;val++)
{
fputc(send_usb_data[val], PORT1);
send_usb_data[val]=0;
}
}
}
|
SLAVE 1 (PIC18F4550)
Code: |
#include <18F4550.h>
#FUSES HSPLL, NOWDT, NOPROTECT, NOBROWNOUT, STVREN, MCLR ,PLL5,CPUDIV1
#use delay(crystal=20000000)
#use i2c(SLAVE,sda=PIN_B0,scl=PIN_B1,address=0x14,force_hw)
unsigned int8 send_usb_data[6];
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) send_usb_data[0] = incoming;
if(state == 2) send_usb_data[1] = incoming;
if(state == 3) send_usb_data[2] = incoming;
if(state == 4) send_usb_data[3] = incoming;
if(state == 5) send_usb_data[4] = incoming;
if(state == 6) send_usb_data[5] = incoming;
}
if(state >= 0x80) //Master is requesting data
{
if(state == 0x80)
{
i2c_read();
i2c_write(send_usb_data[0]);
}
if(state == 0x81) i2c_write(send_usb_data[1]);
if(state == 0x82) i2c_write(send_usb_data[2]);
if(state == 0x83) i2c_write(send_usb_data[3]);
if(state == 0x84) i2c_write(send_usb_data[4]);
if(state == 0x85) i2c_write(send_usb_data[5]);
}
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED|T1_DIV_BY_4);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
enable_interrupts(INT_SSP); //enable I2C interrupts
enable_interrupts(GLOBAL);
while(1)
{
}
}
|
SLAVE 2 (PIC18F4550)
Code: |
#include <18F4550.h>
#FUSES HSPLL, NOWDT, NOPROTECT, NOBROWNOUT, STVREN, MCLR ,PLL5,CPUDIV1
#use delay(crystal=20000000)
#use i2c(SLAVE,sda=PIN_B0,scl=PIN_B1,address=0x28,force_hw)
unsigned int8 send_usb_data[6];
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) send_usb_data[0] = incoming;
if(state == 2) send_usb_data[1] = incoming;
if(state == 3) send_usb_data[2] = incoming;
if(state == 4) send_usb_data[3] = incoming;
if(state == 5) send_usb_data[4] = incoming;
if(state == 6) send_usb_data[5] = incoming;
}
if(state >= 0x80) //Master is requesting data
{
if(state == 0x80)
{
i2c_read();
i2c_write(send_usb_data[0]);
}
if(state == 0x81) i2c_write(send_usb_data[1]);
if(state == 0x82) i2c_write(send_usb_data[2]);
if(state == 0x83) i2c_write(send_usb_data[3]);
if(state == 0x84) i2c_write(send_usb_data[4]);
if(state == 0x85) i2c_write(send_usb_data[5]);
}
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED|T1_DIV_BY_4);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
enable_interrupts(INT_SSP); //enable I2C interrupts
enable_interrupts(GLOBAL);
while(1)
{
}
}
|
SLAVE 3 (DSPIC30F4011)
Code: |
#include <30F4011.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES FRC_PLL16
#FUSES NOCKSFSM
#FUSES WPSB1
#FUSES WPSA512
#FUSES NOPUT
#FUSES NOBROWNOUT
#FUSES BORRES
#FUSES LPOL_HIGH
#FUSES HPOL_HIGH
#FUSES NOPWMPIN
#FUSES MCLR
#FUSES NOPROTECT
#FUSES NOWRT
#FUSES NODEBUG
//#FUSES ICSP
#use delay(clock=120000000)
#use i2c(SLAVE,I2C1,address=0x60,force_hw)
unsigned int8 send_usb_data[6];
#INT_SI2C
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) send_usb_data[0] = incoming;
if(state == 2) send_usb_data[1] = incoming;
if(state == 3) send_usb_data[2] = incoming;
if(state == 4) send_usb_data[3] = incoming;
if(state == 5) send_usb_data[4] = incoming;
if(state == 6) send_usb_data[5] = incoming;
}
if(state >= 0x80) //Master is requesting data
{
if(state == 0x80)
{
i2c_read();
i2c_write(send_usb_data[0]);
}
if(state == 0x81) i2c_write(send_usb_data[1]);
if(state == 0x82) i2c_write(send_usb_data[2]);
if(state == 0x83) i2c_write(send_usb_data[3]);
if(state == 0x84) i2c_write(send_usb_data[4]);
if(state == 0x85) i2c_write(send_usb_data[5]);
}
}
void main()
{
setup_spi( FALSE );
setup_timer1(TMR_DISABLED|TMR_DIV_BY_1);
enable_interrupts(INT_SI2C);
enable_interrupts(INTR_GLOBAL);
while(1)
{
}
}
|
I even tried to send and receive just one byte with DSPIC but it did not work. Please help me. Thank you in advance. |
|
|
mateeb4u@gmail.com
Joined: 07 Feb 2012 Posts: 19 Location: pakistan
|
just try |
Posted: Mon Feb 20, 2012 7:05 am |
|
|
Look in the PIC datasheet, Figure 15-7.
What are the pins used for hardware I2C?
They are not the same pins you have defined.
In a slave you must always use the real I2C hardware. For a master it is advised to use the real hardware but sometimes when this is impossible you can have the CCS compiler generate a software emulation for you. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Mon Feb 20, 2012 7:13 am |
|
|
and you do have the correct value pullups on the I2L bus lines right ??? |
|
|
neohimura
Joined: 08 Feb 2011 Posts: 14
|
Re: just try |
Posted: Mon Feb 20, 2012 8:13 am |
|
|
mateeb4u@gmail.com wrote: | Look in the PIC datasheet, Figure 15-7.
What are the pins used for hardware I2C?
They are not the same pins you have defined.
In a slave you must always use the real I2C hardware. For a master it is advised to use the real hardware but sometimes when this is impossible you can have the CCS compiler generate a software emulation for you. |
For PIC18F4550 i used pin number 33 (RB0) for SDA and pin number 34 (RB1) for SCL.
For DSPIC30F4011 i used pin number 26 (RF2) for SDA and pin number 25 (RF3) for SCL.
I checked the datasheet and those are the hardware I2C pins for both PIC.
temtronic wrote: | and you do have the correct value pullups on the I2L bus lines right ??? |
Yes. I have done pullups on SDA and SCL with 4.7kOhm resistor on each lines. Should I change the resistor value? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Mon Feb 20, 2012 9:23 am |
|
|
Unless this is just for debugging purposes, having a main() exec while loop with no statements in it and then having all the work done in the interrupt handler is ineffective programming. In these scenarios there is no need for an interrupt handler. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Feb 20, 2012 10:19 am |
|
|
Seriously, I'd start 'basic'.
Have you verified the 4011, is running, and running at the expected speed?. A simple pin toggle function, and test the output with an LED or scope.
Then most of the latter more complex PICs do need the default stack allocation increased. Normally things like printf, use a lot (which you are not using), but even things like calling an interrupt might give problems, so worth expanding it a bit.
Then progress to the next step, and add a pin toggle function at the start of the I2C interrupt handler. Does this get toggled when you try to talk to the chip?. If not, then probabilities are:
1) An error in the initialisation of the I2C peripheral.
2) An error in the initialisation/handling of the interrupt.
If it does, then I'd be suspicious that possibly I2C_ISR_STATE which normally accesses the MSSP, is not handling the I2C peripheral correctly.
I doubt if many people have played with I2C slave operation on these chips, hence the lack of responses.
On the resistor value, at slow speed, 4.7K, ought to be 'OK', but this does depend on the total capacitance on the lines. The I2C specifications describe how to calculate the max and min values that can be used for a range of speeds capacitances, and voltages. If the slave 4550's, stopped working when the 4011 was attached, then look at this. However if the other chips still work OK, then this is not likely to be the problem.
Best Wishes |
|
|
neohimura
Joined: 08 Feb 2011 Posts: 14
|
|
Posted: Tue Feb 21, 2012 2:46 pm |
|
|
asmallri wrote: | Unless this is just for debugging purposes, having a main() exec while loop with no statements in it and then having all the work done in the interrupt handler is ineffective programming. In these scenarios there is no need for an interrupt handler. |
It is just for debugging.
Ttelmah wrote: |
Seriously, I'd start 'basic'.
Have you verified the 4011, is running, and running at the expected speed?. A simple pin toggle function, and test the output with an LED or scope.
Then most of the latter more complex PICs do need the default stack allocation increased. Normally things like printf, use a lot (which you are not using), but even things like calling an interrupt might give problems, so worth expanding it a bit.
Then progress to the next step, and add a pin toggle function at the start of the I2C interrupt handler. Does this get toggled when you try to talk to the chip?. If not, then probabilities are:
1) An error in the initialisation of the I2C peripheral.
2) An error in the initialisation/handling of the interrupt.
If it does, then I'd be suspicious that possibly I2C_ISR_STATE which normally accesses the MSSP, is not handling the I2C peripheral correctly.
I doubt if many people have played with I2C slave operation on these chips, hence the lack of responses.
On the resistor value, at slow speed, 4.7K, ought to be 'OK', but this does depend on the total capacitance on the lines. The I2C specifications describe how to calculate the max and min values that can be used for a range of speeds capacitances, and voltages. If the slave 4550's, stopped working when the 4011 was attached, then look at this. However if the other chips still work OK, then this is not likely to be the problem.
|
I tested the 4011 by toggling output with LED. It worked fine.
Ttelmah, can you please explain how I can increase the default stack allocation?
I also tested the interrupt handler with pin toggle function and LED. The LED did not toggle. It remained OFF.
I will calculate the max and min resistor value and test the circuit again.
Thank you very much for all your responses guys |
|
|
|
|
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
|