| Seaborgium 
 
 
 Joined: 23 Jul 2012
 Posts: 14
 
 
 
			    
 
 | 
			
				| 10-bit I2C Communication |  
				|  Posted: Thu Jul 26, 2012 2:06 pm |   |  
				| 
 |  
				| I have successful 10-bit I2C communication between a 16LF1503 master and 16F886 slave. I've included the relevant portions here. 
 Master.c:
 
  	  | Code: |  	  | #include <Master.h> 
 #use i2c(Master, Slow, sda=PIN_C3, scl=PIN_C4, force_sw, stream=module)
 
 //Communicates with a certain 10-bit slave address by delivering a certain
 //data address, then returns the received data.
 //Addresses are even, like 7-bit addresses: the form is 0x??????????0.
 int16 requestData(int16 slaveAddress, unsigned int dataAddress) {
 int16 data;
 int slaveHigh; //High byte of slave address
 int slaveLow; //Low byte of slave address
 
 //Split slave address into low and high byte
 slaveHigh = (slaveAddress>>8)&0xFE; //Shift over first 3 bits; clear R/W bit
 slaveHigh = slaveHigh|0xF0; //"11110XXX" signifies 10-bit address; add this.
 slaveLow = (slaveAddress>>1)&0xFF; //Get lower 8 bits, without R/W bit
 
 //Instruct slave that you wish to write
 i2c_start(module);
 i2c_write(module, slaveHigh); //High byte
 i2c_write(module, slaveLow); //Low byte
 
 //Give data address
 i2c_write(module, dataAddress);
 
 //Restart; instruct slave that you wish to read
 i2c_start(module);
 i2c_write(module, slaveHigh|1); //High byte with R/W set
 
 //Receive data and finish
 data=i2c_read(module, 1)<<8; //Read high byte and ACK
 data+=i2c_read(module, 0); //Read low byte and end transmission
 i2c_stop(module);
 
 return data;
 }
 
 void main() {
 setup_comparator(NC_NC_NC_NC); // This device COMP currently not supported by the PICWizard
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(TRUE);
 }
 | 
 
 Master.h:
 
  	  | Code: |  	  | #include <16LF1503.h> #device adc=16
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
 #FUSES WDT_SW                   //No Watch Dog Timer, enabled in Software
 #FUSES NOMCLR                   //Master Clear pin used for I/O
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 
 #use delay(int=16000000)
 | 
 
 Slave.c:
 
  	  | Code: |  	  | #include <Slave.h> 
 //10-bit addressing bits
 #BYTE SSPCON=0x14
 #BIT SSPM0=SSPCON.0
 #BYTE SSPSTAT=0x94
 #BIT UPDATEADDR=SSPSTAT.1
 #BIT RW=SSPSTAT.2
 
 //Change # of sensors per module to correct number in sensorVals
 
 int writeBuffer [2]; //Holds data to write through i2c
 
 //10-bit addressing stuff
 int1 firstByte; //Records whether first byte of 10-bit address has been received
 int16 addrHigh; //High byte of address
 int16 addrLow; //Low byte of address
 
 #int_SSP
 void i2c_interrupt() {
 if (UPDATEADDR) { //Just received one of two start bytes
 if (!firstByte) { //Just received first byte
 firstByte=TRUE;
 i2c_slaveAddr(addrLow); //Set low byte
 }
 else { //Just received second byte
 firstByte=FALSE;
 i2c_slaveAddr(addrHigh); //Set high byte
 }
 i2c_read();
 return;
 }
 
 //Get state
 int state;
 //Clear R/W bit; CCS compiler sometimes gives incorrect value.
 state = i2c_isr_state()&0b01111111;
 if (RW==TRUE) //Manually retrieve R/W bit.
 state+=0x80;
 
 if (state==0||state==0x80) //Master has issued start command
 i2c_read(); //Clear address from read buffer.
 
 if (state>=0x80) //Master is waiting for data
 i2c_write(writeBuffer[state - 0x80]); //Write appropriate byte, based on how many have already been written
 
 else if(state>0) { //Master has sent data; read.
 unsigned int message;
 message=i2c_read();
 //Master requests sensor data.
 int16 toSend;
 toSend=0b10101010;
 writeBuffer[0] = toSend>>8;
 writeBuffer[1] = toSend&0xFF;
 }
 }
 
 void main() {
 setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
 enable_interrupts(INT_SSP); //Enable interrupts
 enable_interrupts(GLOBAL);
 
 GCEN=TRUE; //Allow general calls
 SSPM0=TRUE; //10-bit addressing
 
 firstByte=FALSE;
 
 int16 slaveAddress=0x1E;
 addrHigh=(slaveAddress>>8)&0xFE; //Calculate high/low bytes of address
 addrHigh=addrHigh|0xF0;
 addrLow=(slaveAddress>>1)&0xFF;
 i2c_slaveAddr(addrHigh); //Set address to high byte
 
 while (true);
 }
 | 
 
 Slave.h:
 
  	  | Code: |  	  | #include <16F886.h> #device adc=16
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
 #FUSES NOMCLR                   //Master Clear pin used for I/O
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 #FUSES NOPROTECT                //No read protection
 #FUSES NOWRT                    //No write protection
 
 #use delay(int=8000000)
 
 #use i2c(Slave, Slow, sda=PIN_C4, scl=PIN_C3, force_hw, address=0xa0)
 | 
 |  |