
Called from main.c

extern unsigned char transmit_bytes[];
extern unsigned char MAX_NUMBYTE_TX[];

transmit_bytes[0]=0x03;
MAX_NUMBYTE_TX[0] = 0; //Transmit 1 data byte
i2c_init(0x20, 0); //Set to master with address of 0x20, no general call
i2c_transmit(0x77);
while (i2c_getstatus() & I2C_BUSY);	// wait until complete

transmit_bytes[0]=0x03; transmit_bytes[1]=0x04;
MAX_NUMBYTE_TX[0] = 1; //Transmit 2 data bytes
i2c_init(0x20, 0); //Set to master with address of 0x20, no general call
i2c_transmit(0x77);
while (i2c_getstatus() & I2C_BUSY);	// wait until complete

transmit_bytes[0]=0xfe; transmit_bytes[1]=0x04; transmit_bytes[2]=0x05;
MAX_NUMBYTE_TX[0] = 2; //Transmit 2 data bytes
i2c_init(0x20, 0); //Set to master with address of 0x20, no general call
i2c_transmit(0x77); 
while (i2c_getstatus() & I2C_BUSY);	// wait until complete


Called fromo i/o.c

extern uchar transmit_bytes[];
extern unsigned char MAX_NUMBYTE_TX[];


I2C_master.c

// SFR description needs to be included
#include "reg936.h"
#include "i2c.h"
// MODULE INTERNAL VARIABLES
static unsigned char slaveaddress;// internal copy of slave address
static unsigned char i2cstatus;	// I2C transfer status
static unsigned int bytenum; // current number of byte transferred
unsigned char MAX_NUMBYTE_TX[] = {0};
unsigned char transmit_bytes[] = {0,0,0,0,0,0,0};	//Holds I2C data bytes
								    				//only
								    				//Not address



//======================================================================
// MASTER CALLBACK FUNCTIONS
//======================================================================
unsigned char i2c_master_getbyte(unsigned int bytenum)					
{
  return transmit_bytes[bytenum];  // Points to data array byte to send
  								   // via I2C 
  return 0;
}
//======================================================================
void i2c_master_receivedbyte(unsigned int bytenum, unsigned char value){
  unsigned char t1, t2;
  t1=bytenum;
  t2=value;}
//======================================================================
unsigned char i2c_master_islasttxbyte(unsigned int bytenum){
  bytenum++;
  if (bytenum > MAX_NUMBYTE_TX[0]) bytenum = 0;//Max I2C data bytes  
  if (bytenum == 0) return 1;  //Checks if it should keep transmitting
  return 0;}
//======================================================================
unsigned char i2c_master_islastrxbyte(unsigned int bytenum){
  if (bytenum == 1) return 1;
  return 0;}
//======================================================================
void i2c_transfer_finished(void){
}
//======================================================================
// MODULE INTERNAL FUNCTIONS
//======================================================================
void i2c_isr(void) interrupt 6 using 3{
  unsigned char status;

  status = I2STAT & 0xF8;

  switch(status)
  {
    case 0x08:
    case 0x10:
 	  I2DAT = slaveaddress;
      STA = 0;
	  STO = 0;
	  bytenum = 0;
	  break;

	// MASTER TRANSMITTER
  	// ACK for slave address + W
	case 0x18:
	  I2DAT = i2c_master_getbyte(bytenum);
	  //I2DAT = 0xAA;
	  STA = 0;
	  STO = 0;
	  break;
	// no ACK for slave address + W
	case 0x20:
	  // stop condition
	  STA = 0;
	  STO = 1;
      i2cstatus = I2C_ERROR;
	  i2c_transfer_finished();
      break;
	// ACK for data byte
  	case 0x28:
	  if (i2c_master_islasttxbyte(bytenum))
	  {
	    // stop condition
	    STA = 0;
	    STO = 1;
        i2cstatus = I2C_OK;
  	    i2c_transfer_finished();
	  }
	  else
	  {
  	    bytenum++;
	    I2DAT = i2c_master_getbyte(bytenum);
		STA = 0;
		STO = 0;
	  }
	  break;
	// no ACK for data byte
	case 0x30:
	  // stop condition
	  STA = 0;
	  STO = 1;
      i2cstatus = I2C_ERROR;
	  i2c_transfer_finished();
	  break;
	// arbitration lost
	case 0x38:
	  // start condition - try again
	  STA = 1;
	  STO = 0;
	  break;

	// MASTER RECEIVER
    // ACK for slave address + R
	case 0x40:
	  STA = 0;
	  STO = 0;
	  if (i2c_master_islastrxbyte(bytenum))
	  {
  	    // return NACK for data byte
	    AA = 0;
	  }
  	  else
	  {
	    // return ACK for data byte
	    AA = 1;
	  }
	  break;
	// no ACK for slave address + R
	case 0x48:
	  STA = 0;
	  // stop condition
	  STO = 1;
      i2cstatus = I2C_ERROR;
	  i2c_transfer_finished();
	  break;
    // ACK for data byte
	case 0x50:
	  i2c_master_receivedbyte(bytenum, I2DAT);
      bytenum++;
	  STA = 0;
	  STO = 0;
	  if (i2c_master_islastrxbyte(bytenum))
	  {
	    // return NACK for next data byte
	    AA = 0;
	  }
	  else
	  {
  	    // return ACK for next data byte
 	    AA = 1;
	  }
	  break;
    // no ACK for data byte
	case 0x58:
	  i2c_master_receivedbyte(bytenum, I2DAT);
	  STA = 0;
	  // stop condition
	  STO = 1;
      i2cstatus = I2C_OK;
      i2c_transfer_finished();
      break;

	

    // unknown state
	default:
      i2cstatus = I2C_ERROR;
      STA = 0;
	  STO = 0;
      // go back to slave mode waiting to be addressed
	  AA = 1;
      i2c_transfer_finished();
	  break;
  }

  // clear interrupt flag
  SI = 0;  
}
//======================================================================
void i2c_init
  (
  unsigned char address,  // The 7-bit I2C address to use
  bit generalcall         // 1 = respond to general call, 0 = ignore
                          // general call
  )
{
  // set pins to open-drain
  P1M1 |= 0x0C;
  P1M2 |= 0x0C;

  // configure I2C address
  I2ADR = 0x20;
  I2ADR = address << 1;
  if (generalcall)
  {
    I2ADR |= 0x01;
  } // if

  // configure internal SCL generator
  I2SCLH = 0x08;
  I2SCLL = 0x07;

  // configure I2C interface
  // use internal SCL generator
  I2CON = 0x44;

  // set interrupt priority to 0
  IP1 &= ~0x01;
  IP1H &= ~0x01;

  // initial status
  i2cstatus = I2C_IDLE;

  // enable interrupt
  EI2C = 1;
} // i2c_init
//======================================================================
unsigned char i2c_transmit(unsigned char address)
{
  
  
  //extern unsigned char byte1, byte2;
  // if already busy then return current status
  if (i2cstatus & I2C_BUSY) return i2cstatus;

  // now we are busy performing a transfer
  i2cstatus = I2C_BUSYTX;

  // store slave address + W for use in ISR
  slaveaddress = address << 1;

  // transmit start condition
  STA = 1; 

  // transmission started
  return I2C_OK;


}
//======================================================================
/*
//======================================================================
// FUNCTION:    i2c_receive
// DESCRIPTION: attempts to start an I2C reception as a master from a
//              device with a specific address. If successful then
//              master callback functions will be called to handle the
//              data for the transfer
// INPUT:       address of device to receive from
// OUTPUT:      I2C_BUSYTX if I2C is already busy transmitting data
//              I2C_BUSYRX if I2C is already busy receiving data
//              I2C_OK if reception started
// NOTES:       Can check if I2C busy by ANDing returned value with
//              I2C_BUSY
//======================================================================
unsigned char i2c_receive(unsigned char address)
{
  // if already busy then return current status
  if (i2cstatus & I2C_BUSY) return i2cstatus;

  // now we are busy performing a transfer
  i2cstatus = I2C_BUSYRX;

  // store slave address + R for use in ISR
  slaveaddress = (address << 1) | 0x01;

  // transmit start condition
  STA = 1;

  // reception started
  return I2C_OK;
}
*/
//======================================================================
unsigned char i2c_getstatus(void)
{
  // wait until any interrupt completed
  while(SI);

  // return status
  return i2cstatus;
}


i2c_master.h

// possible states for the I2C peripheral
#define I2C_IDLE   		0x00
#define I2C_BUSY   		0x01
#define I2C_BUSYTX 		0x03
#define I2C_BUSYRX 		0x05
#define I2C_OK     		0x02
#define I2C_ERROR  		0x04
//======================================================================
extern void i2c_init(unsigned char address, bit generalcall);
//======================================================================
extern unsigned char i2c_receive(unsigned char address);
//======================================================================
extern unsigned char i2c_getstatus(void);
//======================================================================
extern unsigned char i2c_transmit(unsigned char address);
