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

I2C slave receives address instead of data

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



Joined: 29 Apr 2013
Posts: 13

View user's profile Send private message

I2C slave receives address instead of data
PostPosted: Fri Apr 25, 2014 8:36 am     Reply with quote

hi all !

I'm trying to send/read data to/from slave board.

Master is a 18F47J53 based board, slave is a 16F1828 based board.

Slave address is 0xBA and i'm using pins that are shown in the datasheet as scl1 sda1 (slave) and scl2 sda2 (master)

The slave board has 8 led that show the byte received in binary.

What happen is the follow: instead of showing 00000001 (0x01) sent from master, it shows 10111010 (0xBA) which is the address of the slave...

I don't know how to fix this problem...

Master code:
Code:

#include <scheda_principale_test.h>
#include <usb_cdc.h>

void main()
{
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   
   usb_cdc_init();
   usb_init();
   
   delay_ms(3000);
 
   int16 lux;
   int16 Temp;
   output_float(PIN_D0);
   output_float(PIN_D1);
   
   int z=1;
   
   while(1)
   {
      lux = read_lux();
      Temp = onboard_temperature();
      printf(usb_cdc_putc,"\r\nluminosita = %Lu",lux);
      printf(usb_cdc_putc,"\r\ntemperatura = %Ld",Temp);
     
      i2c_start(OUT);
      i2c_write(OUT,0xba);
      i2c_write(OUT,z);
      i2c_stop(OUT);
      delay_ms(50);
     
      i2c_start(OUT);
      i2c_write(OUT,0xbb);
      z=i2c_read(OUT,0);
      i2c_stop(OUT);
      delay_ms(50);
       
      printf(usb_cdc_putc,"\r\ni2c effettuata risposta %u", z);
      delay_ms(2000);
     
      z++;
   }

}


and slave code is:
Code:

#include <scheda_led_test.h>

int8 value = 5;
int8 g = 0;

#INT_SSP
void i2c_isr()
{
   output_high(LED7);
   BYTE state;
   state=i2c_isr_state();
   
   if(state < 0x80)                           //Master is sending data
   {
     value = i2c_read();
   }
   
   if(state >= 0x80)                     //Master is requesting data
   {
      i2c_write(value);   
   } 
   
   delay_ms(10);
   output_LOW(LED7);
}


void main()
{
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);

   while (1)
   {
      output_C(value);
      delay_ms(50);
   }
}


settings of i2c in master are:
Code:
#use i2c(master, sda=PIN_D1, scl=PIN_D0, stream=OUT, FORCE_HW, FAST=200000)
#use i2c(master, sda=PIN_B5, scl=PIN_B4, stream=ON_BOARD, FORCE_HW)


and in slave are:
Code:
#use i2c(Slave,sda=PIN_B4,scl=PIN_B6,address=0xba, FORCE_HW, FAST=200000)


When master reads data from slave everything is ok but when master sends data to slave it receives 0xBA instead of 1 (z)
after when master read slave responds with 0xBA (obviously)...
What's the problem ?
Thanks everybody Smile


Last edited by antosci on Fri Apr 25, 2014 11:00 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 9:40 am     Reply with quote

Comments/problems:

1) On state 0x80, the slave must _read_ and then write. This is required, and failure to do so can cause all sorts of problems on some PIC's.
2) The first byte received will always be the address. This is when isr_state ==0. You should not display the value till you get to state==1.

Best Wishes
antosci



Joined: 29 Apr 2013
Posts: 13

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 11:05 am     Reply with quote

do you mean i should write something like this ?

Code:
#INT_SSP
void i2c_isr()
{
   output_high(LED7);
   BYTE state;
   state=i2c_isr_state();
   
   if(state < 0x80)                           //Master is sending data
   {
     if(state == 0x00) {i2c_read();}
     else{ value = i2c_read();}
   }
   
   if(state >= 0x80)                     //Master is requesting data
   {
      if (state == 0x80)
      {
            i2c_read();
      }else
      {
           i2c_write(value);
       }
   } 
   
   delay_ms(10);
   output_LOW(LED7);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 11:11 am     Reply with quote

Not quite.
State 0x80, needs to read then write.
Look at the slave example. If you look at it carefully, you will see it does both on this one state.
antosci



Joined: 29 Apr 2013
Posts: 13

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 12:04 pm     Reply with quote

slave example is:

Code:
#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)                     //First received byte is address
         address = incoming;
      if(state == 2)                     //Second received byte is data
         buffer[address] = incoming;
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(buffer[address]);
   }
}


i write something similar now:
Code:
#INT_SSP
void i2c_isr()
{
   output_high(LED7);   
   
   BYTE incoming, state;

   state = i2c_isr_state();
   
   if(state <= 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
      if(state == 1)                     //First received byte is address
         value = incoming;
      if(state == 2)                     //Second received byte is data
         g = incoming;
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(value);
   }
   delay_ms(10);
   output_LOW(LED7);
}


now "value" is always 5 (as declaration) and LEDs are 0 0 0 0 0 1 0 1.
this mean nothing is received from master.
when master attempt to read, slave respond with 118 (0x76) O.o

i forgot to say i'm using 10K pull-up resistor. could it be a wrong value ??
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 1:23 pm     Reply with quote

You need two resistors. One on each line. 10K should be OK if the line is short, but 4K7 is more commonly a good starting point.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Apr 25, 2014 6:47 pm     Reply with quote

10K might be just a wee bit too high.....

4k7 should work fine...

3k3 has always worked for me....

jay
antosci



Joined: 29 Apr 2013
Posts: 13

View user's profile Send private message

PostPosted: Tue Apr 29, 2014 11:07 am     Reply with quote

thanks a lot for help. i solved...

change 10K pull-up resistor in 3.9K
but it didn't work.

so i thought: maybe slave can receive first byte (which is the address)
and even not the second byte (which is the data) cause there's a delay on interrupts entering operation.
Deleting the
Code:
output_high(LED7);
[...]
delay_ms(10);
output_LOW(LED7);


and declaring
Code:
BYTE incoming,state;

out of interrupt (i know, this was unnecessary Very Happy )
everything works fine.
thanks again
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