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

Slave response on I2C net between PICs

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



Joined: 26 Jun 2009
Posts: 19

View user's profile Send private message Send e-mail

Slave response on I2C net between PICs
PostPosted: Mon Jul 13, 2009 1:32 pm     Reply with quote

Hi. I am making a net between PICs, using routines in CCS Compiler. But, I can't send response of the Slave to the Master. In the slave interruption, I test if the command is 0x10, if yes, the slave send 0x0A to Master, that enable a output (with a LED) if verify the correct response.

Someone have a example of this network type? Thanks! Wink
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 13, 2009 2:00 pm     Reply with quote

See the i2c slave demo code that I have posted in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=39242

This is a 2-page thread.
jaderd



Joined: 26 Jun 2009
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Wed Jul 15, 2009 12:03 pm     Reply with quote

OK! Really the code is correct! Thanks for the help!!!

But, I would like to know how make to request (Master) and send (Slave) a frame of the 8 bytes from a buffer in the Slave? The example shows the request of only 1 byte per request. Thanks!
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Jul 15, 2009 12:48 pm     Reply with quote

One thing to know, the Master controls all of the data transfers. It simply tells the Slave if data will be going in or coming out of the slave. I2C is only able to transfer one byte (8 bits) at a time. You have to transfer one byte then there needs to be an ACK bit which tells the master or slave (depending on the direction the data is going) that the byte was transmitted correctly. If you have multiple bytes to be transferred then you will need to read or write every one of them.

Now, with that being said, you don't need to address the slave every time you want to transfer a byte. Once the slave has been addressed you can transfer multiple bytes before a stop is sent. Also, remember that when the master is reading data, you need to have the last read command send a NOACK which will tell the slave that you're finished reading data.

Hope that cleared things up a little. (probably just muddied it up a bit)

Ronald
PROCRASTINATORS UNITE!............. tomorrow
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 15, 2009 5:09 pm     Reply with quote

Here's a sample program that will read 8 bytes from the slave PIC.
This is the output, displayed on a terminal window.
Quote:
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF


You didn't say how the 8 data bytes are created. Presumably you
want to read one block of 8 valid bytes. Then the slave can update
the buffer, so it's ready for the master to read. Somehow the master
needs to know if a new set of 8 bytes is ready. You can invent a method
to do this.

Master:
Code:
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)

   
#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13

#define BUF_SIZE 8

//====================================
void main()
{
int8 i;
int8 data[BUF_SIZE];

while(1)
  {
   i2c_start();
   i2c_write(SLAVE1_READ_ADDR);

   for(i = 0; i < 7; i++)
      {
       data[i] = i2c_read();  // Read first 7 bytes
      }
   
   data[7] = i2c_read(0); // Do a NACK on last byte read
   i2c_stop();

   // Display the data.
   for(i = 0; i < BUF_SIZE; i++)
       printf("%X ", data[i]);
   printf("\n\r");

   delay_ms(1000);
  }

}


Slave:
Code:
#include <16F877.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)


int8 buffer[8] = {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF};
int8 index;


#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;

state = i2c_isr_state();
   
if(state < 0x80)     // Master is sending data
  {
   incoming = i2c_read(); 
  }

if(state >= 0x80)   // Master is requesting data from slave
  {
   index = state & 7;  // Lower 3 bits of state = the index
   i2c_write(buffer[index]);
  }

}

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

while(1);
}


-------------

Edit:
Changed the PROTECT fuse to NOPROTECT. There is no need for code
protection in a test program.


Last edited by PCM programmer on Sun Aug 16, 2009 12:19 pm; edited 1 time in total
jaderd



Joined: 26 Jun 2009
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Jul 16, 2009 12:56 pm     Reply with quote

I need know how to configure the tris_b using I2C, but the examples does not have tris_b configuration, and on my project I'm using other pin of the portb with input, and when I configure the tris_b, the I2C bus is stopped and none data is sent or received. Somebody know which to configure? Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 16, 2009 2:20 pm     Reply with quote

Take the Master and Slave programs shown above, run them, verify that
they work, then add your set_tris_b() statements to them. Verify that
they now fail. Then post the programs. They must be compilable.

Also post your compiler version.
jaderd



Joined: 26 Jun 2009
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Jul 16, 2009 2:45 pm     Reply with quote

I think that you dont understand my problem. If I set the tris_b, the I2C is not run, and if I dont set the tris_b, only use the I2C configuration, the I2C is run.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 16, 2009 3:24 pm     Reply with quote

I understand you completely. I want to see the set_tris_b() statement
that causes the i2c to "not run". Just post it.
Oblivion



Joined: 23 Sep 2010
Posts: 13

View user's profile Send private message

PostPosted: Mon Nov 08, 2010 9:50 am     Reply with quote

Hello... I have the same master and slave codes shown above. But the master can read from the slave only for once. After the first turn it always reads "1". I guess i cannot trigger the interrupt after the first turn. I've been searching at the forum but all i tried have failed. What may the problem be? Can anyone help me to find a solution or a clue to fix this?

Thanks for your concern...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 08, 2010 11:58 pm     Reply with quote

Are you using the exact same code as shown earlier in the thread, with
no changes ? Are you using the same type of PICs ?

How are you testing this ? Are you testing it in hardware or in Proteus ?
I don't think Proteus is 100% reliable.

Do you have 4.7K pull-up resistors on SDA and SCL ?

Do you have a ground connection between the 2 PIC boards ?

What is your compiler version ?
Oblivion



Joined: 23 Sep 2010
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 09, 2010 4:42 am     Reply with quote

Thanks for your concern...

I am using 16F877a and my clock is 20M. These are the only differences... I tested it in proteus but as i realized and as you said proteus is not reliable, so i tested in hardware. I put the proper resistors and connections and but the result is the same...

When i want to read from the slave there is no problem. I can read the address and state values from slave everytime. But master does not read anything from the slave after the first turn...

My compiler version is 4.110

Edit: I've found that; from the start of the second turn, none of the bits is acknowledged including the address bit. So the master only gets "1".
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 09, 2010 1:44 pm     Reply with quote

I duplicated your test setup as closely as possible and I was able to make
it work. I didn't have two 16F877A's, so I used a 16F877 for the master
and a 16F877A for the slave. I installed compiler vs. 4.110. I installed
20 MHz crystals on both the master and slave boards. I connected SCL
to SCL, and SDA to SDA, and Ground to Ground, between the two boards.
The boards each have built-in 4.7K pullups, so the effective pullup size is
2.35K on each signal (SDA and SCL), but that's OK.

Also, both of these programs were compiled in "Release" mode in MPLAB.

Here are some problems that I had to fix just now, to make it work.

1. I accidently put two of the jumper wires on pins B3 and B4 on one
board, by mistake. I discovered this error and fixed it. I changed them
to pins C3 and C4.

2. The PicDem2-Plus boards that I use, have 3 PIC sockets, 40pin, 28pin
and 18pin. On one board, I had left a 18pin PIC installed. This stopped
the ICD2 from recognizing the 16F877A chip. I discovered the mistake
and removed the 18pin PIC and then the ICD2 could find the 16F877A.

3. I ran the test and I only got FF FF FF FF FF FF FF FF. I then pulled the
ICD2 cable from the slave board, and it started working. Here is the
output on the terminal window. You can see that it started working when
I removed the ICD2 cable. MPLAB was not running and was shut down
when this happened.
Quote:

FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF
01 23 45 67 89 AB CD EF


My guess is that you have some simple error in your test setup, just like
I did. You need to discover it, and then the project will work.
Oblivion



Joined: 23 Sep 2010
Posts: 13

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 7:23 am     Reply with quote

Thank you for your concern...

I wished you won't say something like that... I am trying the codes with different pics but i keep failing. I checked the hardware at least for 100 times. I guess i have a problem with the soft. I believe i cannot trigger the interrupt after one time.
Oblivion



Joined: 23 Sep 2010
Posts: 13

View user's profile Send private message

PostPosted: Fri Nov 12, 2010 8:43 am     Reply with quote

After a week i finally make it....


In slave
Quote:

.....
if((state >= 0x80)&&(state <= 0x87)) // Master is requesting data from slave
.....


I changed the code like this. And now it is working...
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