We have developed this library to use the i2c bus on our 12f1840 development board.
http://www.xappsoftware.com/wordpress/?p=3523
http://www.xappsoftware.com/wordpress/?p=3428
Naturally it can be used also with our PICcoletta board and with other boards which use Microchip PICs. Leave a message to this post if you find useful this library or if you use this library with other PICs.
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:
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 ; }
If you found useful this article, please share it using the social buttons below. Thank you in advance.
Gg1
ACK and NACK functions are missing, Stop function instead.