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 support@ccsinfo.com

16F1829 Master/Slave

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



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

16F1829 Master/Slave
PostPosted: Mon Feb 24, 2014 4:16 pm     Reply with quote

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));
   }
}   
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 24, 2014 4:44 pm     Reply with quote

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)
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Mon Feb 24, 2014 6:08 pm     Reply with quote

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?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 24, 2014 7:26 pm     Reply with quote

Post your CCS compiler version. It's given at the top of the .LST file.

Example of version numbers:
http://www.ccsinfo.com/devices.php?page=versioninfo
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Mon Feb 24, 2014 7:43 pm     Reply with quote

Compiler version is 5.016.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 24, 2014 8:40 pm     Reply with quote

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.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 10:38 am     Reply with quote

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!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 11:54 am     Reply with quote

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.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 2:06 pm     Reply with quote

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)
   {
   }
}


PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 2:26 pm     Reply with quote

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 ?
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 2:35 pm     Reply with quote

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.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 3:00 pm     Reply with quote

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!
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