![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
16F1829 Master/Slave |
Posted: Mon Feb 24, 2014 4:16 pm |
|
|
Hi All,
I am working on a 16F1829, which I would like to setup with two separate I2C busses. One for a local sensor, and the other to have the pic serve as a slave.
I can get both portions working separately, but not together.
To do a quick check, I am using an arduino as an I2C scanner. With no #use i2c master declaration I can find the slave pic. When I add the master line, I cannot find the device, and it appears that there is no activity on the bus
I had looked through the errata for the chip, but cannot seem to find information relating to this particular scenario.
Any ideas?
Code: |
#include <16F1829.h>
#fuses HS,NOWDT
#use delay(crystal = 20mhz)
//#use i2c(MASTER, I2C2, stream = i2cMaster) //This causes the bus to not work
#use i2c(MASTER, SDA = PIN_B4, SCL = PIN_B6, FAST = 100000, stream = i2cMaster) //As does this one.
#use i2c(SLAVE, SCL = PIN_B6, SDA = PIN_B4, address=0x50, stream = i2cSlave)
//#include <HSCMLibrary.c>
unsigned int8 state, address, Data, buffer[10];
#INT_SSP
void ssp_interrupt(){
state = i2c_isr_state(); //Read the interrupt state
if(state < 0x80) //master is sending data
{
if((state == 0)) //Returns the I2C address
{
i2c_read(i2cSlave); //Read to get rid of the address, dont care about it
}
if(state == 1){ //
address = i2c_read(i2cSlave); //
//read that actual data as the address
}
if(state == 2){
buffer[address] = i2c_read(i2cSlave);
}
}
if(state == 0x80) //master is requesting data
{
i2c_read();
i2c_write(i2cSlave, buffer[address]); //Write data to the master
}
}
void main ()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
buffer[0x00] = 0x10; //
buffer[0x01] = 0x11; //
buffer[0x02] = 0x12; //
buffer[0x03] = 0x13; //These are the data registers
buffer[0x04] = 0x14; //
buffer[0x05] = 0x15; //
buffer[0x06] = 0x16; //
buffer[0x07] = 0x17; //
buffer[0x08] = 0x18; //
buffer[0x09] = 0x19; //
buffer[0x10] = 0x20; //
while (TRUE)
{
if(buffer[0x00] == 0xFF){
buffer[0x00] = 0;
output_high(PIN_C3);
delay_ms(500);
output_low(PIN_C3);
delay_ms(500);}
else(delay_ms(500));
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 24, 2014 4:44 pm |
|
|
Quote: | #use i2c(MASTER, SDA = PIN_B4, SCL = PIN_B6, FAST = 100000, stream = i2cMaster) //As does this one.
#use i2c(SLAVE, SCL = PIN_B6, SDA = PIN_B4, address=0x50, stream = i2cSlave)
I would like to setup with two separate I2C busses
|
You are using the same pins for both of the "separate" busses.
The 16F1829 has two separate MSSP (i2c) hardware controllers in it.
Why not use one for the Master and the other one for the Slave ?
These are:
MSSP1: Pins B4 and B6 (I2C1)
MSSP2: Pins B5 and B7 (I2C2) |
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Mon Feb 24, 2014 6:08 pm |
|
|
Every damn time I post here I make stupid mistake!
That is actually a typo. I am using I2C1 for slave and I2C2 for master, I had tried declaring #use i2c a few different times and the last time I made that typo. If you take a peek at the commented #use i2c declaration you can see I2C2.
Problem is even with the correct declarations I cannot get it to work. Any ideas? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Mon Feb 24, 2014 7:43 pm |
|
|
Compiler version is 5.016. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 24, 2014 8:40 pm |
|
|
Your i2c slave isr code is different from the Ex_slave.c example which
is in this folder: c:\program files\picc\examples\ex_slave.c
It handles state == 0x80 differently than you are doing it.
Code: | if(state == 0x80)
incoming = i2c_read(2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
else
incoming = i2c_read();
|
Try using that example as a model and convert it to use streams.
That example file comes with vs. 5.016. |
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Tue Feb 25, 2014 10:38 am |
|
|
I modified EX_SLAVE.c to use streams. I2C1 as stream i2cS. With:
Code: | #use i2c(SLAVE, I2C1, address=0xA0, stream = i2cS) |
the code runs correctly. If i add
Code: | #use i2c(MASTER, I2C2,stream = i2cM) |
the same issue I was having with my code occurs.
Could it be that the master has to be on I2C1, and the slave has to be on I2C2?
Thanks! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 25, 2014 11:54 am |
|
|
Quote: |
unsigned int8 state, address, Data, buffer[10];
buffer[0x00] = 0x10; //
buffer[0x01] = 0x11; //
buffer[0x02] = 0x12; //
buffer[0x03] = 0x13; //These are the data registers
buffer[0x04] = 0x14; //
buffer[0x05] = 0x15; //
buffer[0x06] = 0x16; //
buffer[0x07] = 0x17; //
buffer[0x08] = 0x18; //
buffer[0x09] = 0x19; //
buffer[0x10] = 0x20; //
|
Here's another bug in your original program. Your array is defined as
length 10 (decimal), which means it has elements with indexes from
0 to 9. Then in your code above, you write to index 0x10 (decimal 16)
which is not part of the array.
After you fix that and test your program, if it doesn't work then post your
latest test program. I want to see all the modifications that you did.
Also, post some more details about how your complete test setup.
What are you using for an i2c Master, to talk to the 16F1829 slave ?
Tell the details. Post the code for the Master device, assuming it's a PIC. |
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Tue Feb 25, 2014 2:06 pm |
|
|
I didnt notice that! Woops. Thanks!
I'm still using the modified version of EX_Slave.c Code is below.
For the master, I am using an arduino, its a little easier to interface to the serial port. The program in the arduino scans through all possible i2c addresses, looking for an ack. When it sees an ack, it reports the address.
I've included a waveform capture for you to see its operation. This capture is for when #use i2c MASTER (I2C2) is disabled.
Code: |
///////////////////////////////////////////////////////////////////////////
//// EX_SLAVE.C ////
//// ////
//// This program uses the PIC in I2C slave mode to emulate the ////
//// 24LC01 EEPROM. You can write to addresses 00h to 0Fh with it. ////
//// ////
//// This program is to be used in conjunction with the ex_extee.c ////
//// sample. Use the "#include <2402.C>" or "#include <2401.c>". ////
//// Only 16 bytes of address space are implemented, however. ////
//// ////
//// If using a compiler version before 2.639 add "*0x14 = 0x3E;" to ////
//// the begining of main(), and add "NOFORCE_SW" as the last ////
//// parameter in the #use i2c directive. ////
//// ////
//// Jumpers: ////
//// PCM,PCH pin C7 to RS232 RX, pin C6 to RS232 TX ////
//// ////
//// This example will work with the PCM and PCH compilers. The ////
//// following conditional compilation lines are used to include a ////
//// valid device for each compiler. Change the device, clock and ////
//// RS232 pins for your hardware if needed. ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
#if defined(__PCM__)
#include <16F1829.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined (__PCD__)
#include <24FJ128GA006.h>
#fuses PR,HS,NOWDT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_F3, rcv=PIN_F2)
#endif
#use i2c(MASTER, I2C2,stream = i2cM)
#use i2c(SLAVE, I2C1, address=0x88, stream = i2cS)
unsigned int8 address, buffer[16];
#if defined(__PCD__)
#INT_SI2C
void si2c_interrupt()
#else
#INT_SSP
void ssp_interrupt ()
#endif
{
unsigned int8 incoming, state;
state = i2c_isr_state(i2cS);
if(state <= 0x80) //Master is sending data
{
if(state == 0x80)
incoming = i2c_read(i2cS, 2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
else
incoming = i2c_read(i2cS);
if(state == 1) //First received byte is address
address = incoming;
else if(state >= 2 && state != 0x80) //Received byte is data
buffer[address++] = incoming;
}
if(state >= 0x80) //Master is requesting data
{
i2c_write(i2cS, buffer[address++]);
}
}
void main ()
{
#if defined(__PCD__)
enable_interrupts(INTR_GLOBAL);
enable_interrupts(INT_SI2C);
#else
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
#endif
while (TRUE)
{
}
} |
![](http://i.imgur.com/XQ0qGZR.png) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 25, 2014 2:26 pm |
|
|
Your timing diagram says "Setup write to [0x10] + NAK".
What does this mean ?
Are you attempting to write to slave address 0x10 ? Your slave address
is 0x88, according to your code.
Or, does it mean you're attempting to write to index 0x10 of the buffer
array ? Because if it does, then you are again over-writing past the end
of the array. You buffer is defined with only 16 elements and in C,
arrays start at index 0 (not 1 as in Basic).
Quote: | unsigned int8 address, buffer[16]; |
Also, I don't like the Arduino master because I have no idea what it's
doing. A PIC master, yes. I could look at the code. Arduino ? |
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Tue Feb 25, 2014 2:35 pm |
|
|
The program checks for an ack at each address. The screen shot shows the check at address 0x10 and 0x12, this continues sequentially until 0xEE.
I will try a PIC version. |
|
![](templates/subSilver/images/spacer.gif) |
demedeiros
Joined: 27 Dec 2013 Posts: 71
|
|
Posted: Tue Feb 25, 2014 3:00 pm |
|
|
Looking through the #use i2c preprocessor definition, I found NO_STRETCH, which disables clock stretching. This appears to have solved the issue!
Any idea why the slave would be holding the clock?
Thanks! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|