CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

18F2550 I2C slave keeps SCL low. Why?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
halibatsuiba



Joined: 12 Aug 2009
Posts: 30

View user's profile Send private message

18F2550 I2C slave keeps SCL low. Why?
PostPosted: Wed Aug 12, 2009 7:11 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 12, 2009 9:22 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 12, 2009 9:42 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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