This library doesn't use interrupts, but only the polling mode (arghh!!!)

The flow goes out from the polling cycle when the flag has been signaled or when the timeout occurs. The timeout is handled using the tmr1 overflow.


(Refer to the Microchip application note AN1355)

We have used the HI-TECH C compiler LITE edition that can be downloaded freely from the Microchip site.

The following procedure initializes the i2c:

void ini_i2c1(void)         // init the I2C module on MSSP1
{
  TRISA       = 0b00111111; // all input
  ANSELA      = 0b00000000; // no analog input    
  SSP1ADD     = 0×03 ;      // baud rate =  50 khz    SSP1ADD = 79 , Baud rate = 100Khz SPP1ADD = 39 Baud rate 400Khz SSP1ADD = 9
  SSP1STAT    = 0×80  ;     // slew rate dis  8 , SMBUS disabled 
  SSP1CON1    = 0×28  ;     // enable module, I2C master SSP1ADD=baud rate
  SSP1CON2    = 0×00  ; 
} ;

 

As we have already said, all the operations on the i2c bus are controlled using the "polling mode". The procedure that controls the polling is the poll_if_tim1 function:
This function arms a timer and performs a check on the overflow flags and on the SSP1IF flag of the PIR1 register. If the timeout expires the function sets the error variable.

void poll_if_tim1(void)
{           
      TMR1H = ~(10000/256)&0xff;          // poll 2 flags: MSSP1IF & T1
      TMR1L = ~(10000%256)&0xff;          //  1msec delay
      T1_ON = 1 ;                         //  start timer1
      while(!(PIR1bits.SSP1IF|T1_OVFL)) ; // wait at least on flag to rise
      if (T1_OVFL)
      {
            gucI2CError = 0×01; // if timeout, set error flag
      }   
      PIR1bits.SSP1IF = 0;               // in any case, clear all  
      T1_OVFL     = 0;
      T1_ON       = 0;         
}   

To start or restart the i2c communication we use two equal functions, we use two functions because you can decide to implements differents behaviours in the two cases.

/** start the I2C COMMUNICATION   */
void i2c_start(void)             // START I2C communication
{
      SSP1CON2bits.SEN = 1;      // START bit (cleared by hw in the end)
      poll_if_tim1()    ;    
} 
/** restart the I2C COMMUNICATION
 */
void i2c_restart(void)           // RESTART I2C communication (change to 'reads')
{
      SSP1CON2bits.RSEN = 1;      // REPEATED START bit (cleared by hw in the end)
      poll_if_tim1()    ;    
}     

The stop function is very simple, too.

/** Send STOP for the I2C COMMUNICATION
 */
void i2c_stop(void)              // STOP I2C communication
{
      SSP1CON2bits.PEN = 1;      // STOP bit (cleared by hw in the end)
      poll_if_tim1()    ;    
}     

And now the ACK and NACK functions:

/** Send STOP for the I2C COMMUNICATION
 */
void i2c_stop(void)              // STOP I2C communication
{
      SSP1CON2bits.PEN = 1;      // STOP bit (cleared by hw in the end)
      poll_if_tim1()    ;    
}     

Last but not least, the write and read functions:

/** The write function
 */
void i2c_wr(unsigned char i2c_data) // writes a byte in the I2C SLAVE
{
      SSP1BUF = i2c_data      ;      // load char in data buffer ; start streaming
      poll_if_tim1()    ;            // poll MSSP1IF with 1msec timeout 
      if(SSP1CON2bits.ACKSTAT)       // if NOACK from slave 
      {    
            gucI2CError = ERR_I2C_FATAL;
      }               
      else
      {
            // wonderfull … I have the pic written correctly
            ;
      }               
}      // if a correct ACK from the slave, do nothing
 
/** The read function
 */
unsigned char  i2c_rd(void)
{
      unsigned char ucByteRead;
 
      SSP1CON2bits.RCEN = 1   ;      // enable I2C receive mode(RCEN=0 after 8cks by hw)
      poll_if_tim1()              ;      // poll MSSP1IF with timeout
      ucByteRead = SSP1BUF    ;
      return ucByteRead           ;
}  
