|
|
View previous topic :: View next topic |
Author |
Message |
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
18F2550 I2C slave keeps SCL low. Why? |
Posted: Wed Aug 12, 2009 7:11 pm |
|
|
Howdy
I have two 18F2550s, one as a master and another as a slave.
Master works ok. I have tested it with AMD AD5242 digital potentiometer.
It can write and read without problems.
When I write/read to/from the other 18F2550, writing works ok but for some reason when the slave F2550 transmits data to master, it keeps SCL line low after transmitting..
Master receives data ok but cannot send i2c stop because it is waiting slave to release SCL.
I have checked data transmission both ways with logic analyser and I have serial LCD connected for debugging purposes.
I have tried different pull-up resistors from 1k to 10k but that does not seem to help at all.
Here is the master code:
Code: |
#include <18F2550.H>
#include<stdlib.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use fast_io (C)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,Slow,sda=PIN_B0,scl=PIN_B1,force_hw)
#pragma use fast_io(B)
void init_all(void) {
set_tris_a (0b00000110);
set_tris_b (0b11111111);
set_tris_c (0);
}
void send_i2c_data (byte addr, byte instruction, byte data) {
char teksti[5];
printf("?as");
i2c_start();
itoa(addr,10,teksti);
printf(" a");printf(teksti);
i2c_write(addr); // Device address
itoa(instruction,10,teksti);
printf(" i");printf(teksti);
i2c_write(instruction); // Instruction to device
itoa(data,10,teksti);
printf(" d");printf(teksti);
i2c_write(data); // Data to device
printf(" ");
i2c_stop();
}
void read_i2c_data(byte addr,byte command) {
byte data;
char teksti[5];
printf("?a?js");
i2c_start();
addr |= 0xa1;
itoa(addr,10,teksti);
printf(" a");printf(teksti);
i2c_write(addr); // Device address+1 = read
delay_ms(1);
data = i2c_read(); // Data from device
itoa(data,10,teksti);
printf(" r");printf(teksti);
i2c_stop();
printf(" x");
}
main() {
byte tikitin=0xff;
byte tehty;
char teksti[5];
init_all();
tehty = 0;
while (TRUE) {
output_toggle(PIN_C2); //"I am alive"-led
delay_ms(1000);
printf("?f");
if ((input(PIN_A2) == 1) && (tehty == 0)) {
send_i2c_data(0xa0, tikitin--,input(PIN_C2));
}
if ((input(PIN_A1) == 1) && (tehty == 0)) {
read_i2c_data(0xa0,0xab);
tehty = 1;
}
if ((input(PIN_A1) == 0) && (tehty == 1)) {
tehty = 0;
}
if(tikitin < 0x05)
tikitin = 0xff;
}
}
|
And here comes the slave-code:
Code: |
#include <18F2550.H>
#include<stdlib.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use I2C(slave,Slow,sda=PIN_B0,scl=PIN_B1,address=0xa0,RESTART_WDT,FORCE_HW)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#byte PIR1 = 0x00C
#bit SSPIF = PIR1.3
#use fast_io (B)
#use fast_io (C)
//#BYTE SSPCON2 = 0xFC5
//#DEFINE SEN 0x01
byte data;
#INT_SSP
void ssp_interrupt () // ssp_interupt ()
{
byte rcv_buffer[5],state,address,incoming;
char teksti[5];
printf("?f");
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
rcv_buffer[state - 1] = i2c_read();
itoa(rcv_buffer[state - 1],10,teksti);
printf(" ");printf(teksti);
rcv_buffer[state - 1] = i2c_read();
itoa(rcv_buffer[state - 1],10,teksti);
printf(" ");printf(teksti);
data = rcv_buffer[state - 1];
}
if(state == 0x80) //Master is requesting data
{
i2c_write(0x13);
}
}
void init_all(void) {
setup_adc(NO_ANALOGS);
set_tris_a (0b00000100);
set_tris_b (0b11111111);
port_b_pullups (false);
set_tris_c (0);
printf("?fOk.");
data = 0;
}
main() {
init_all();
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while (TRUE) {
output_toggle(PIN_C2);
delay_ms(200);
}
}
|
Several places recommend changing 18F2550 to some other Pic due to i2c slave problems. I switched it to 18F4331 (happened to find it at my desk) but it has problems too: ICSP does not work. Errata says so too.
So now I am still trying to get this working.
Help? Please no more sleepless nights trying to figure out why this is not working... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 12, 2009 9:22 pm |
|
|
Your code is too complicated for the first try. Instead, I suggest
that you try the simple i2c slave (and master) code shown in this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=39242&start=6
This code should work. If it doesn't work, then you may have a
hardware problem which will need to be fixed. If it does work,
then it's a foundation that you can use to build a larger program. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Wed Aug 12, 2009 9:42 pm |
|
|
PCM programmer wrote: | Your code is too complicated for the first try. Instead, I suggest
that you try the simple i2c slave (and master) code shown in this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=39242&start=6
This code should work. If it doesn't work, then you may have a
hardware problem which will need to be fixed. If it does work,
then it's a foundation that you can use to build a larger program. |
It just looks complicated because there is lots of printfs and other stuff for lcd. Without those it is very simple, almost direct copy of the code behind your link.
I found where the problem was...
I have been banging my head to table with this several days and now it works!
Master's i2c_read()-function needed NACK before slave releases the SCL-line (obviously I need to read i2c-specs again):
Code: |
data = i2c_read(0); // Data from device
|
Now it works like a charm.
I have found lots of valuable information in this forum for my project connecting several (15-20) Pics together.
Thank you anyway and big thanks for the maintainers of this forum. |
|
|
|
|
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
|