View previous topic :: View next topic |
Author |
Message |
nehallove
Joined: 16 Jan 2008 Posts: 61
|
I2C Slave Tx doesn't work, both data and clock pulled low |
Posted: Fri Mar 08, 2013 3:52 pm |
|
|
I have master PIC18f25k20 and slave 16f1937.
compiler version 4.0139
slave code:
//This is main.h
//#include <16F1825.h>
#include <16LF1937.h>
#device *=16 ICD=TRUE
#device adc=16
//#FUSES LP
#FUSES HS
#FUSES NODEBUG
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
//#use delay(clock=20000000)
#use delay(internal=16mhz)
//this is main.c
//! Library Files
#include <main.h>
#use I2C(SLAVE,sda=PIN_C4,scl=PIN_C3,address=0xB0,SLOW,FORCE_HW)
unsigned int8 address=0, buffer[16];
#INT_SSP
void ssp_interrupt ()
{
unsigned int8 incoming, state;
state = i2c_isr_state();
if((state == 0)||(state == 0x80))
i2c_read();
if(state >= 0x80)
i2c_write(0xAA);
else if(state>0)
buffer[address++] = i2c_read();
//if((address == 17)||(buffer[address-1] =='\r'))
//address = 0;
/*
if(state <= 0x80) //Master is sending data
{
if(state == 0x80)
incoming =i2c_read(2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
else
incoming = i2c_read();
//if(state == 1) //First received byte is address
//address = incoming;
if(state >=2 && state !=0x80) //Received byte is data
buffer[address++] = incoming;
}
if(state >= 0x80) //Master is requesting data
{
i2c_write(buffer[++address]);
}
*/
}
void main ()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE)
{
}
}
Master Code:
try to read from I2C slave
while(1){
i2c_start();
i2c_write(0xB1);
x = i2c_read();
x = i2c_read();
i2c_stop();
}
Result:
if i use only one read operation, it doesn't read right. If i put two read operation then it reads 0xAA. In both condition after one loop cycle, slave pulls both data and clock line low. And both side freezes on #I2C() line.
Does anybody have a clue what is going on? Master write operation works.
nehal _________________ nehal |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri Mar 08, 2013 4:12 pm |
|
|
1) Learn to use the code buttons.
Your code is 99% unreadable.
2) Trim code. We aren't here to read through swathes of stuff that is remmed out. Test programs should be as short as possible.
3) When doing multiple read transactions, the master needs to not ACK the last byte.
4) Time. Do you really think you can send stop, then immediately start as fast as possible, without pausing at all?.
5) As currently written, address will overflow buffer if you write, and will destroy the contents of the RAM.
6) Have you bothered to check for errata?. The 25K20, on older revisions has a completely non working master mode, and on all revisions has problems handling the stop event, which can be triggered by poor pull-ups, or not allowing any delays..... It is actually very difficult to get reliable I2C with this chip. |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Fri Mar 08, 2013 5:34 pm |
|
|
Code: | //Fuses
#include <16LF1937.h>
#device *=16 ICD=TRUE
#device adc=16
#FUSES HS
#FUSES NODEBUG
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=16mhz)
|
Code: | #use I2C(SLAVE,sda=PIN_C4,scl=PIN_C3,address=0xB0,SLOW,FORCE_HW)
unsigned int8 address=0, buffer[16];
#INT_SSP
void ssp_interrupt ()
{
unsigned int8 incoming, state;
state = i2c_isr_state();
if((state == 0)||(state == 0x80))
i2c_read();
if(state >= 0x80)
i2c_write(0xAA);
else if(state>0)
buffer[address++] = i2c_read();
}
void main ()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE)
{
}
}
|
Code: | Master Code:
try to read from I2C slave
while(1){
i2c_start();
i2c_write(0xB1);
x = i2c_read();
x = i2c_read();
i2c_stop();
} |
1) Learn to use the code buttons.
Your code is 99% unreadable.
I would like to apologize for the code. Every time it by default put the code in proper way. So didn't check the preview before posting it. I also trimmed it.
2) Trim code. We aren't here to read through swathes of stuff that is remmed out. Test programs should be as short as possible.
Once again sorry.
3) When doing multiple read transactions, the master needs to not ACK the last byte.
Well if that is the case the case then why only reading one byte doesn't work either.
4) Time. Do you really think you can send stop, then immediately start as fast as possible, without pausing at all?.
I actually have the break point after every master read operation. So I am not doing reading without pausing anyways.
5) As currently written, address will overflow buffer if you write, and will destroy the contents of the RAM.
As I said I am only using the master read operation. I have already verified master write operation works. That buffer check portion of code is already commented.
6) Have you bothered to check for errata?. The 25K20, on older revisions has a completely non working master mode, and on all revisions has problems handling the stop event, which can be triggered by poor pull-ups, or not allowing any delays..... It is actually very difficult to get reliable I2C with this chip.[/code]
Of course I have checked the errata. This is an old product processor. We have already have used this processor as master I2C and ARM as slave I2C without any problem. We also have low pull resistors. This is just a test code so after one operation master always stops at break point.
Even it is only one read operation I don't see any additional clock on the bus. Data collection is wrong and slave pulls the clock and data line low. By resetting the master PIC18F25K20 or clearing RCEN bit doesn't keep the line high. It stays pull low.
I thought it is slave who still stays in some unknown data transmitting state and pull the bus low. I might be wrong but don't know what is going on. I am stuck and brain froze. _________________ nehal |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 08, 2013 7:18 pm |
|
|
Quote: | Well if that is the case the case then why only reading one byte doesn't work either. |
Reading one byte means that single i2c_read() is the "last" one, and it
must do a NACK.
Read this thread about the NACK on the last i2c_read(), including links
to the Philips specification:
http://www.ccsinfo.com/forum/viewtopic.php?t=42965&highlight=nack |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Fri Mar 08, 2013 8:17 pm |
|
|
Thanks PCM Programmer.
By putting i2c_read(0) on the last byte reading stopped the pulling of data and clock bus. But
i2c_start()
x[0] = i2c_read();
x[1] = i2c_read();
x[2] = i2c_read(0);
i2c_stop()
but with above setting first byte x[0] is always 0x62 no matter what i send.
if i use below code the receive byte is also only 0x62
i2c_start()
x[2] = i2c_read(0);
i2c_stop()
Any reason, it seems weird to me. _________________ nehal |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 08, 2013 8:26 pm |
|
|
You don't send the slave's read address in either of those i2c transactions.
How can the slave respond ? It has not been addressed. |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Fri Mar 08, 2013 8:33 pm |
|
|
oh sorry i accidentally cut the line while copying on my reply i do use the address.
i2c_start()
i2c_write(0xB1);
x[0] = i2c_read();
x[1] = i2c_read();
x[2] = i2c_read(0);
i2c_stop()
and
i2c_start()
i2c_write(0xB1);
x[2] = i2c_read(0);
i2c_stop() _________________ nehal |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 09, 2013 3:18 pm |
|
|
Instead of using your programs to test the i2c slave, do this:
Use the CCS example program Ex_Slave.c for the slave PIC:
c:\program files\picc\examples\ex_slave.c
Use the code in this post for the Master PIC:
http://www.ccsinfo.com/forum/viewtopic.php?t=32368&start=3
Note that the master code uses software i2c. It doesn't have FORCE_HW
in the #use i2c() statement. Software i2c master is more reliable than
hardware on many PICs.
What is the Vdd voltage on each PIC ? Is it 5v or 3.3v ? Or are the
PICs running at different Vdd voltages ?
What is the value of the pull-up resistors used on SDA and SCL ?
What is the length of the i2c bus ? (in inches or cm)
Do you have a ground connection between the two PICs ?
(Are they on the same board ?) |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Mon Mar 11, 2013 3:11 pm |
|
|
Hi I used the code in ex_slave.c and use that code modify the routine a little bit since it reads the memory. But still the same thing. First byte is wrong on reading. Even on oscilloscope it show 0x62.
PICs running at different Vdd voltages ?
Both pics are at same voltage.
What is the value of the pull-up resistors used on SDA and SCL ?
Pull up is 1.4 k
What is the length of the i2c bus ? (in inches or cm)
An inch
Do you have a ground connection between the two PICs ?
(Are they on the same board ?)
They are different boards but they have common ground and supply voltage. _________________ nehal |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Mon Mar 11, 2013 3:23 pm |
|
|
I also removed the force hardware on master side. _________________ nehal |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Mar 11, 2013 3:47 pm |
|
|
I notice you have several conflicts in the fuses on the slave device:
The watchdog is specified to be both software enabled, and disabled. Only one can be used at a time. You also have the oscillator set to use a crystal, but the delay setup to use the internal RC. Things like this can lead to unexpected problems. Also, a slave device does not have a speed. Only master devices should specify this.
Best Wishes |
|
|
nehallove
Joined: 16 Jan 2008 Posts: 61
|
|
Posted: Mon Mar 11, 2013 5:04 pm |
|
|
I changed the fuses as below but still the same.
Code: | #include <16LF1937.h>
#device *=16 ICD=TRUE
#device adc=16
#FUSES INTRC_IO
#FUSES NODEBUG
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=16mhz)
|
_________________ nehal |
|
|
|