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

Software I2C Implementation

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



Joined: 13 Sep 2003
Posts: 87

View user's profile Send private message

Software I2C Implementation
PostPosted: Mon May 03, 2004 4:43 pm     Reply with quote

Hi,

Is it possible to have two I2C channel? One using the MSSP hardware of the PIC and the other using a software based using PortB[5,6] as the SDA and SCL pin for the I2C.

Any suggestions and comments?

Thank u.
Guest








PostPosted: Mon May 03, 2004 5:08 pm     Reply with quote

Yes, but not at the same time. The #use i2c statement would need to be changed for each case:

#use i2c(master,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
// do hardware i2c

#use i2c(master,sda=PIN_B5,scl=PIN_B6)
// do software i2c
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue May 04, 2004 9:00 am     Reply with quote

I've used a 16F87 to be a Slave (using the hardware I2C) while acting as a Master (using bit-banging) to a sensor. It would use software routines to communicate to the sensor and then send that data to a master that was also talking to several other PIC's doing the same thing.

Ronald
Guest








PostPosted: Tue May 04, 2004 4:56 pm     Reply with quote

rnielsen wrote:
I've used a 16F87 to be a Slave (using the hardware I2C) while acting as a Master (using bit-banging) to a sensor. It would use software routines to communicate to the sensor and then send that data to a master that was also talking to several other PIC's doing the same thing.

Ronald


can u share few snippets on this scheme...
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed May 05, 2004 9:15 am     Reply with quote

Here's a little bit for you. This is the Slave code that is talking to a SHT11 or SHT15 RH/Temperature sensor.

Code:

#include <16F87.h>
#use i2c(Slave,fast,sda=PIN_B1,scl=PIN_B4,restart_wdt,address=0x90)

#define XSDA PIN_A2 // sensor I2C data line
#define XSCL PIN_A3 // sensor I2C clock line

#int_SSP   // I2C interrupt service routine
SSP_isr()
{
int8 data;
static int8 state = 0;

   if(SSPOV)// Make sure the buffer has not overflowed
   {
      data= SSPBUF;
      SSPOV=0;  // Clear the register
      return;
   }

   if(STOP)
   {
      return;
   }
   else
   {
      switch(SSPSTAT & 0x2D)
      {
         CASE 0x0C:// Master rx, slave address + 1
               CKP = 0;// hold SCL low, stretch it out
               index = 0;
               SSPBUF = stage[index];
               index++;
               CKP = 1;
            break;
         CASE 0x2C:// Master rx, data with /ack
            CKP = 0;
            SSPBUF = stage[index];
            index++;
            CKP = 1;
            break;
         CASE 0x28:// Master rx, data with not /ack
               sensor = 1;// enable the routine to read the sensor
               status = 1;
            break;
         default:
            break;
      }//end of switch()
   }// end of else

}// end of SSP interupt

////////////////////////
// inserted into main()
////////////////////////

if(sensor)// time to read the sensor
{
   switch(status)
   {
      CASE 1:
         if(send_sense(0x03))// send command to read the Temperature
         {
            status = 0;
            sensor = 0;
            if(++hey > 3)// if the sensor is not ACKing set reset bit
            {
               puked = 1;
               hey = 0;
            }
         }
         else
         {
            status = 2;
         }
         break;
      CASE 2:
         if(!input(XSDA))   // we need to wait until the sensor is finished
         {         // making it's measurement before we try to get
            stemp = read_sense();   // the data from it
            status = 3;
         }
         break;
      CASE 3:
         if(!send_sense(0x05))   // this is the read command for the RH
         {
            status = 4;
         }
         break;
      CASE 4:
         if(!input(XSDA))   // we need to wait for the same thing as the temp
         {
            shumid = read_sense();
            status = 5;
         }
         break;
      CASE 5:
         if((!stemp && !shumid) || (stemp > 0x3FFF || shumid > 0xFFF)) // if the sensor has
         {                                                   // wigged out, cycle the power to it
            if(pwr++ > 10)
            {
               puked = 1;
            }
            cycle_power();
         }
         else
         {
            TEMP = calc_temp(stemp);
            HUMI = calc_rh(shumid);
            stage[0] = (HUMI >> 8) & 0xFF;// storage of data to be sent to Master
            stage[1] = HUMI & 0xFF;
            pwr = 0;
         }
         status = 6;
         break;
      default:
         break;
   }// end of switch()
}// end of if(sensor)

// SUBROUTINES
////////////////////////////////

void rst_i2c(void)   // resets the sensor's I2C bus
{
int8 track;

   strt_i2c();
   for(track = 0; track < 9; track++)
   {
      output_high(XSCL);
      delay_cycles(2);
      output_low(XSCL);
      delay_cycles(2);
   }
   busy = 0;
}// end of rst_i2c()

void strt_i2c(void)       // I2C start signal for the sensor.  the sensor needs a slightly
{                                    // different start signal than the standard I2C protocol
   output_high(XSCL);         // calls for.
   delay_cycles(1);
   output_low(XSDA);
   delay_cycles(1);
   output_low(XSCL);
   delay_cycles(3);
   output_high(XSCL);
   delay_cycles(1);
   output_high(XSDA);
   delay_cycles(1);
   output_low(XSCL);
}// end of strt_i2c()

unsigned int1 send_sense(int8 address)
{
unsigned int1 ack;

   strt_i2c();
   ack = write_i2c(address);

   return(ack);
}

unsigned int16 read_sense(void)
{
unsigned int8 value1, value2;
unsigned int16 clipboard;

   value1 = read_i2c(1);
   value2 = read_i2c(0);
   clipboard = make16(value1, value2); // combine the two bytes together
   return(clipboard);
}

unsigned int8 read_status(void)
{
unsigned int8 statreg;

   statreg = read_i2c(0);
   return(statreg);
}

// use pins A0, A6, A7 and B7 to select address

void get_add(void)   // possible combinations
{// base address is 0x90   0x90 92 94 96 98 9A 9C 9E A0 A2  BASE:1001 0000

   if(input(PIN_A0))      //     0  1  0  1  0  1  0  1  0  1
   {
      bit_set(SLAVE_ADDR, 1);
   }

   if(input(PIN_A7))//        0  0  1  1  0  0  1  1  0  0
   {
      bit_set(SLAVE_ADDR, 2);
   }

   if(input(PIN_A6))//        0  0  0  0  1  1  1  1  0  0
   {
      bit_set(SLAVE_ADDR, 3);
   }

   if(input(PIN_B7))//        0  0  0  0  0  0  0  0  1  1
   {
      bit_clear(SLAVE_ADDR, 4);
      bit_set(SLAVE_ADDR, 5);
   }
}// end of get_add()



Ronald
ritchie



Joined: 13 Sep 2003
Posts: 87

View user's profile Send private message

PostPosted: Thu May 06, 2004 5:14 pm     Reply with quote

Hi,

I modified the code from this link http://www.ccsinfo.com/wwwboard/messages/725.html for my hardware I2C application. However, in this hardware I2C I use 8 momories for my storage thus, I have no room for additional I2C chip.

But my application needs an I2C based RTC chip like the X1226 and with the dilema I don't have any room for adding the X1226 to the existing hardware I2C setup that my application have.

So, my last option is to implement a software-based I2C using PortB as my data and clock.

My question is: would it be possible to use both hadrware I2C and software I2C taking into consideration that for my hardware I2C I never use the built-in CCS I2C function instead I make my own routines base from the URL link above?

Need your comments and suggestions...

Thanx
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Thu May 06, 2004 5:37 pm     Reply with quote

I did that once, I used CCS' #use I2C to implement a software I2C, and I tweaked the MSSP registers manually to use the hardware I2C module at the same time.
However the second post on this page offers an easier solution.
ritchie



Joined: 13 Sep 2003
Posts: 87

View user's profile Send private message

PostPosted: Thu May 06, 2004 6:26 pm     Reply with quote

Haplo wrote:
I did that once, I used CCS' #use I2C to implement a software I2C, and I tweaked the MSSP registers manually to use the hardware I2C module at the same time.
However the second post on this page offers an easier solution.


Got ur point...

My hardware I2C setup use the FRAM chip at a clock of 1Mhz and I don't think the #use i2c by CCS support this clock speed.. maybe it operates at 400K the most.... this is the reason why I opted for a registry tweak for my hardware I2C....

For X1226 is I guess a 100K or 400K clock speed....

Anyway, thank u for the info.... I will try this method...
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Thu May 06, 2004 6:53 pm     Reply with quote

I may be mistaken, but according to the PIC16F87 datasheet it seems the hardware I2C module of this PIC only supports 100KHz and 400KHz speeds.
ritchie



Joined: 13 Sep 2003
Posts: 87

View user's profile Send private message

PostPosted: Thu May 06, 2004 7:04 pm     Reply with quote

Haplo wrote:
I may be mistaken, but according to the PIC16F87 datasheet it seems the hardware I2C module of this PIC only supports 100KHz and 400KHz speeds.


I modified the code from the link above for my PIC18F452 microcontroller... this microcontroller supports 1MHz clock for I2C...
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