View previous topic :: View next topic |
Author |
Message |
jaderd
Joined: 26 Jun 2009 Posts: 19
|
Slave response on I2C net between PICs |
Posted: Mon Jul 13, 2009 1:32 pm |
|
|
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! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
jaderd
Joined: 26 Jun 2009 Posts: 19
|
|
Posted: Wed Jul 15, 2009 12:03 pm |
|
|
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
|
|
Posted: Wed Jul 15, 2009 12:48 pm |
|
|
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
|
|
Posted: Wed Jul 15, 2009 5:09 pm |
|
|
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
|
|
Posted: Thu Jul 16, 2009 12:56 pm |
|
|
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
|
|
Posted: Thu Jul 16, 2009 2:20 pm |
|
|
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
|
|
Posted: Thu Jul 16, 2009 2:45 pm |
|
|
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
|
|
Posted: Thu Jul 16, 2009 3:24 pm |
|
|
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
|
|
Posted: Mon Nov 08, 2010 9:50 am |
|
|
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
|
|
Posted: Mon Nov 08, 2010 11:58 pm |
|
|
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
|
|
Posted: Tue Nov 09, 2010 4:42 am |
|
|
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
|
|
Posted: Tue Nov 09, 2010 1:44 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 7:23 am |
|
|
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
|
|
Posted: Fri Nov 12, 2010 8:43 am |
|
|
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... |
|
|
|