View previous topic :: View next topic |
Author |
Message |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
I2C connection problem |
Posted: Sun Aug 30, 2020 1:28 pm |
|
|
Hello guys !
I have an I2C network containing one master and 3 slaves by pic18f25K80. They work correctly but sometimes one of slaves pulled down SDA pin. So master hang or reset regularly by WDT. This problem continues until the faulty slave is reset manually.
Please help me. I'm so confused.
Why does one of the slaves pull down SDA and doesn't pull up it ? |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Sun Aug 30, 2020 1:33 pm |
|
|
Is it always the SAME PIC slave that does this ? If so, remove and retest to confirm which unit.
I'm assuming the 3 PICs have the identical, same program running in them as well as all PCB components ?
When you have it, inspect the PCB very, very carefully for any I2C trace issues like wrong pullups, solder whiskers, poor solder connections.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
|
Posted: Mon Aug 31, 2020 12:34 am |
|
|
Hello dude
Thanks for your quick response.
My 3 slaves are different in PCB. But i2c slave program (lNT_SSP) is
similar. This problem is happening just for one of the slaves. Other slaves work without problem.
When this problem occurs, the slave PIC works normally but pulls down the SDA pin. When i disconnect it from the bus, problem is solved and master works normally. When l power on the boards all of them work correctly but after few minutes, master hangs. That is because of the fault from same slave. Even when I replaced the PIC and checked connections. But i can't find a problem.
Please help me I'm very confused!!!!!! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Mon Aug 31, 2020 2:01 am |
|
|
Some detail in the master code that talks to this slave, or in the slave
code is probably wrong.
Post the master code that talks to this slave, and the I2C handler code
for the slave.
A difference, like a different number of bytes in the 'frame' for this PIC,
and then the slave not actually reading the right number of bytes, or the
master not setting NACK on the last byte read if reading from the device,
would be the 'classics' for hanging the bus.
How long is the bus?.
Is this the last device on the bus?.
What voltage are you running (3.3/5v),
What bus speed?.
What pull-up resistors are used. |
|
![](templates/subSilver/images/spacer.gif) |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
|
Posted: Mon Aug 31, 2020 9:55 am |
|
|
Bus long is nearly 40 Cm
This slave is last device
Voltage is 5 volts
Master pic18f45k80
Slaves are pic18f25k80
Pull up resistors are 1.5K
Pull down caps 100pF
Bus speed is slow
MASTER CODE:
Code: |
#include <18F45K80.h>
#use delay(crystal=16M,restart_wdt)
#fuses hsh
#FUSES SOSC_LOW //Low-power SOSC circuit is selected
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOBROWNOUT //No brownout reset
#fuses wdt256
#use i2c(master,slow,sda=PIN_C4,SCL=PIN_C3,force_hw)
void main()
{
setup_wdt(WDT_ON);
I2C_Speed (1000);
while(true)
{
//slave #1
i2c_start();
i2c_write(0x10);
i2c_write(out_up);
i2c_write(out_do);
i2c_stop();
delay_ms(1);
i2c_start();
i2c_write(0x11);
ma_up=i2c_read(1);
ma_do=i2c_read(0);
i2c_stop();
delay_ms(1);
// last slave faulty slave (add : 0x40)
i2c_start();
i2c_write(0x41);
pos_up=i2c_read(1);
pos_do=i2c_read(0);
i2c_stop();
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
|
Posted: Mon Aug 31, 2020 9:59 am |
|
|
Slave code:
Code: |
#include <18F25K80.h>
#DEVICE ADC=12
#use delay(oscillator=16M)
#fuses hsh
#fuses nowdt
#use i2c(slave,sda=PIN_C4,scl=PIN_C3,address=0x40,force_hw)
int8 state=0,rcv_buffer[10];
int8 send_buffer[10];
#INT_SSP
void ssp_interrupt()
{
state=i2c_isr_state();
if(state>=0x80){i2c_write(send_buffer[state-0x80]);}
else {rcv_buffer[state-1]=i2c_read();}
}
void main()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
setup_adc_ports(sAN1);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
while(TRUE)
{
set_adc_channel(1);
ta+=read_adc();
i++;
if(i>=loop)
{
restart_wdt();
anin=ta/loop;
p=anin&0xFF00;
send_buffer[0]=p>>8;
send_buffer[1]=anin;
ta=0;
i=0;
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 31, 2020 1:52 pm |
|
|
Quote: | while(true)
{
//slave #1
i2c_start();
i2c_write(0x10);
i2c_write(out_up);
i2c_write(out_do);
i2c_stop();
delay_ms(1);
i2c_start(); // **** Is this Slave #1 or #2 ?
i2c_write(0x11);
ma_up=i2c_read(1);
ma_do=i2c_read(0);
i2c_stop();
delay_ms(1);
// last slave faulty slave (add : 0x40)
i2c_start();
i2c_write(0x41);
pos_up=i2c_read(1);
pos_do=i2c_read(0);
i2c_stop();
} |
Post the #use i2c statements for Slaves #1, #2, and #3.
I want to make sure you are using the correct slave address for each one. |
|
![](templates/subSilver/images/spacer.gif) |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
|
Posted: Mon Aug 31, 2020 5:50 pm |
|
|
Slave #1 address is 0x10
For writing to it address is 0x10
For reading from it address is 0x11
Slave #3 address is 0x40
For writing to it address is 0x40
For reading from it address is 0x41
Slave #2 address is 0x20
For writing to it address is 0x20
For reading from it address is 0x21 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Sep 01, 2020 1:22 am |
|
|
What do you mean by "Pull down caps 100pF "?.
You don't want caps on an I2C bus.
Bus capacitance is what limits the distance and frequency you can operate.
It wants to be as low as possible.
<https://www.allaboutcircuits.com/technical-articles/i2c-design-mathematics-capacitance-and-resistance/>
This may well be what is causing the problem.
The code you post, has a major problem. On state 0x80, the slave must
read then write. You are not doing this. This can hang the bus.
Code: |
#INT_SSP
void ssp_interrupt()
{
int8 dummy;
state=i2c_isr_state();
if (state==0x80)
{
dummy=i2c_read(2); //special code to not release bus
}
if(state>=0x80)
{
i2c_write(send_buffer[state-0x80]);
}
else
{
rcv_buffer[state-1]=i2c_read();
}
}
|
If this is not done, the I2C peripheral can become hung. |
|
![](templates/subSilver/images/spacer.gif) |
Mojtaba-s
Joined: 30 Aug 2020 Posts: 6
|
|
Posted: Tue Sep 01, 2020 3:07 pm |
|
|
Hello dear "Ttelmah".
Thanks a lot for your quick response.
I tested your INT_ssp codes. But it was wrong and data transmission completely disabled.
My code in INT_SSP was correct.
I shoot pull down capacitors and change master code like below.
FORCE_HW not need in Master. Its better to add SMBUS.
When you connect to a slave for change between write and read just use i2c_start again. Do not use i2c_stop. When you want to connect to another slave or you want to stop connecting use i2c_stop, like:
Code: |
i2c_start();
i2c_write(0x10);
i2c_write(out_up);
i2c_write(out_do);
i2c_start();
i2c_write(0x11);
ma_up=i2c_read(1);
ma_do=i2c_read(0);
i2c_stop(); |
At last my problem go away .
Thanks GOD !
Thanks Ttelmah!
I love you all.
I🤣🤣🤗🤗🤗🤗🤗❤❤❤❤❤❤❤ |
|
![](templates/subSilver/images/spacer.gif) |
|