LTlib LaurTec Library  4.0.3
Open Source C Library for Microchip Microcontrollers based on XC8 Compiler
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
module_I2C.c
Go to the documentation of this file.
1 /*******************************************************************************
2 
3 Autore : Mauro Laurenti
4 Versione : 1.2
5 
6 Created on Date : 02/10/2010
7 Last update : 16/03/2016
8 
9 CopyRight 2006-2015 all rights are reserved
10 
11 ********************************************************
12 SOFTWARE LICENSE AGREEMENT
13 ********************************************************
14 
15 The usage of the supplied software imply the acceptance of the following license.
16 
17 The software supplied herewith by Mauro Laurenti (the Author) is intended for
18 use solely and exclusively on Microchip PIC Microcontroller (registered mark).
19 The software is owned by the Author, and is protected under applicable
20 copyright laws. All rights are reserved.
21 Any use in violation of the foregoing restrictions may subject the
22 user to criminal sanctions under applicable laws, as well as to civil liability
23 for the breach of the terms and conditions of this license.
24 Commercial use is forbidden without a written acknowledgement with the Author.
25 Personal or educational use is allowed if the application containing the
26 following software doesn't aim to commercial use or monetary earning of any kind.
27 
28 THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
29 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
30 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE AUTHOR SHALL NOT,
32 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
33 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
34 
35 *******************************************************************************/
36 
37 #ifdef __XC8
38 #include <xc.h>
39 #endif
40 
41 #include "module_I2C.h"
42 
43 //************************************************************
44 // I2C1_open function implementation
45 //************************************************************
46 
47 void I2C1_open (unsigned char device_type){
48 
49  unsigned char dummy_read;
50 
51  //IO pin initialization
52  I2C1_SDA_LINE_TRIS = PIN_AS_INPUT;
53  I2C1_SCL_LINE_TRIS = PIN_AS_INPUT;
54 
55  //Register initialization (Starting known value)
56  SSPSTAT &= 0x3F;
57  SSPCON1 = 0x00;
58  SSPCON2 = 0x00;
59 
60  //Device definition Master or Slave
61  SSPCON1 |= device_type;
62 
63  //Slew Rate Control set to ON by default
64  SSPSTAT |= I2C_SLEW_ON;
65 
66  //Enable the I2C Module
67  SSPCON1 |= 0b00100000;
68 
69  //clear input buffer
70  dummy_read = I2C1_read_byte ();
71 
72 }
73 
74 #ifdef I2C_MODULE_TYPE_2
75 
76 void I2C2_open (unsigned char device_type){
77 
78  unsigned char dummy_read;
79 
80  //IO pin initialization
81  I2C2_SDA_LINE_TRIS = PIN_AS_INPUT;
82  I2C2_SCL_LINE_TRIS = PIN_AS_INPUT;
83 
84  //Register initialization (Starting known value)
85  SSP2STAT &= 0x3F;
86  SSP2CON1 = 0x00;
87  SSP2CON2 = 0x00;
88 
89  //Device definition Master or Slave
90  SSP2CON1 |= device_type;
91 
92  //Slew Rate Control set to ON by default
93  SSP2STAT |= I2C_SLEW_ON;
94 
95  //Enable the I2C Module
96  SSP2CON1 |= 0b00100000;
97 
98  //clear input buffer
99  dummy_read = I2C2_read_byte ();
100 
101 }
102 #endif
103 
104 //************************************************************
105 // I2C1_baud_rate function implementation
106 //************************************************************
107 void I2C1_baud_rate (unsigned int bus_baud_rate_KHZ){
108 
109  unsigned int div_a = (unsigned int) (I2C_CLOCK /1000);
110  unsigned int div_b = (4 *bus_baud_rate_KHZ);
111  SSPADD = (unsigned char)(div_a/div_b)-1;
112 }
113 
114 #ifdef I2C_MODULE_TYPE_2
115 void I2C2_baud_rate (unsigned int bus_baud_rate_KHZ){
116  unsigned int div_a = (unsigned int) (I2C_CLOCK /1000);
117  unsigned int div_b = (4 *bus_baud_rate_KHZ);
118  SSP2ADD = (unsigned char) (div_a/div_b)-1;
119 }
120 #endif
121 
122 //************************************************************
123 // I2C1_set_slave_address function implementation
124 //************************************************************
125 void I2C1_set_slave_address (unsigned int device_address){
126 
127  //Only one byte address is supported
128  SSPADD = (unsigned char) device_address;
129 }
130 
131 #ifdef I2C_MODULE_TYPE_2
132 void I2C2_set_slave_address (unsigned int device_address){
133  SSP2ADD = (unsigned char) device_address;
134 }
135 #endif
136 
137 
138 
139 
140 //************************************************************
141 // I2C1_start_bit function implementation
142 //************************************************************
143 void I2C1_start_bit (void){
144 
145  SSPCON2bits.SEN=1;
146  //Waits util start bit is in idle
147  while(SSPCON2bits.SEN);
148 }
149 
150 
151 #ifdef I2C_MODULE_TYPE_2
152 void I2C2_start_bit (void){
153  SSP2CON2bits.SEN=1;
154  //Waits util start bit is in idle
155  while(SSP2CON2bits.SEN);
156 }
157 #endif
158 
159 
160 //************************************************************
161 // I2C1_stop_bit function implementation
162 //************************************************************
163 
164 void I2C1_stop_bit (void){
165  SSPCON2bits.PEN=1;
166  while(SSPCON2bits.PEN);
167 }
168 
169 
170 #ifdef I2C_MODULE_TYPE_2
171 void I2C2_stop_bit (void){
172 
173  SSP2CON2bits.PEN=1;
174  while(SSP2CON2bits.PEN);
175 }
176 #endif
177 
178 //************************************************************
179 // I2C1_write_byte function implementation
180 //************************************************************
181 signed char I2C1_write_byte (unsigned char byte_to_send){
182 
183  //Writes the data to the output buffer
184  SSPBUF = byte_to_send;
185 
186  //Check for collision errors
187  if ( SSPCON1bits.WCOL )
188  return ( -1 );
189  else {
190 
191  //slave mode only
192  if( ((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) ) {
193 
194  // release clock line
195  SSPCON1bits.CKP = 1;
196 
197  // wait until the nineth clock pulse is received
198  while ( !PIR1bits.SSPIF );
199 
200  // if R/W=0 and BF=0, NOT ACK was received
201  if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF )){
202  return ( -2 );
203  }
204  else
205  return(0);
206 
207  }
208  else
209 
210  //master mode only
211  if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) ) {
212 
213  // wait until write cycle is complete
214  while( SSPSTATbits.BF );
215 
217 
218  // test for ACK condition received
219  if (SSPCON2bits.ACKSTAT )
220  return ( -2 );
221  else
222  return ( 0 );
223  }
224  }
225 
226  //Unknown Error
227  return ( -3 );
228 }
229 
230 #ifdef I2C_MODULE_TYPE_2
231 signed char I2C2_write_byte (unsigned char byte_to_send){
232 
233  //Writes the data to the output buffer
234  SSP2BUF = byte_to_send;
235 
236  //Check for collision errors
237  if ( SSP2CON1bits.WCOL )
238  return ( -1 );
239  else {
240 
241  //slave mode only
242  if( ((SSP2CON1&0x0F)!=0x08) && ((SSP2CON1&0x0F)!=0x0B) ) {
243  // release clock line
244  SSP2CON1bits.CKP = 1;
245 
246  // wait until ninth clock pulse received
247  while ( !PIR3bits.SSP2IF );
248 
249  // if R/W=0 and BF=0, NOT ACK was received
250  if ( ( !SSP2STATbits.R_W ) && ( !SSP2STATbits.BF )){
251  return ( -2 );
252  }
253  else
254  return(0);
255 
256  }
257  else
258 
259  //master mode only
260  if( ((SSP2CON1&0x0F)==0x08) || ((SSP2CON1&0x0F)==0x0B) ) {
261 
262  // wait until write cycle is complete
263  while( SSP2STATbits.BF );
264 
265  I2C2_wait_bus_IDLE();
266 
267  // test for ACK condition received
268  if ( SSP2CON2bits.ACKSTAT )
269  return ( -2 );
270  else
271  return ( 0 );
272  }
273  }
274 
275  //Unknown Error
276  return ( -3 );
277 }
278 #endif
279 
280 
281 //************************************************************
282 // I2C1_reset_write_collision_flag function implementation
283 //************************************************************
285  SSPCON1bits.WCOL=0;
286 }
287 
288 #ifdef I2C_MODULE_TYPE_2
289 void I2C2_reset_write_collision_flag (void){
290  SSP2CON1bits.WCOL=0;
291 }
292 #endif
293 
294 
295 //************************************************************
296 // I2C1_write_byte_to_external_device function implementation
297 //************************************************************
298 signed char I2C1_write_byte_to_external_device (unsigned char control_byte, unsigned char register_address, unsigned char data){
299 
301  I2C1_start_bit();
302 
303  // test for bus collision
304  if ( PIR2bits.BCLIF ){
305  return ( -1 );
306  }
307  else {
308  // write byte - R/W bit should be 0
309  if ( I2C1_write_byte(control_byte)){
310  I2C1_stop_bit();
311  return (-3);
312  }
313 
314  // test for ACK condition received
315  if ( !SSPCON2bits.ACKSTAT )
316  {
317  if (I2C1_write_byte(register_address)) {
318  I2C1_stop_bit();
319  return ( -3 );
320  }
321  // test for ACK condition received
322  if ( !SSPCON2bits.ACKSTAT ){
323  if (I2C1_write_byte(data)) {
324  I2C1_stop_bit();
325  return ( -3 );
326  }
327  }else {
328  I2C1_stop_bit();
329  return ( -2 );
330  }
331  } else {
332  I2C1_stop_bit();
333  return ( -2 );
334  }
335  }
336 
337  I2C1_stop_bit();
338 
339  // test for bus collision
340  if ( PIR2bits.BCLIF ){
341  return ( -1 );
342  }
343 
344  return ( 0 );
345 }
346 
347 #ifdef I2C_MODULE_TYPE_2
348 signed char I2C2_write_byte_to_external_device (unsigned char control_byte, unsigned char register_address, unsigned char data){
349 
350  I2C2_wait_bus_IDLE();
351  I2C2_start_bit();
352 
353  // test for bus collision
354  if (PIR3bits.BCL2IF){
355  return (-1);
356  }
357  else {
358  // write byte - R/W bit should be 0
359  if ( I2C2_write_byte(control_byte)){
360  I2C2_stop_bit();
361  return (-3);
362  }
363 
364  // test for ACK condition received
365  if (!SSP2CON2bits.ACKSTAT){
366 
367  if (I2C2_write_byte(register_address)) {
368  I2C2_stop_bit();
369  return (-3);
370  }
371 
372  // test for ACK condition received
373  if ( !SSP2CON2bits.ACKSTAT ){
374  if (I2C2_write_byte(data)) {
375  I2C2_stop_bit();
376  return (-3);
377  }
378  }else {
379  I2C2_stop_bit();
380  return (-2);
381  }
382  } else {
383  I2C2_stop_bit();
384  return (-2);
385  }
386  }
387 
388  I2C2_stop_bit();
389 
390  // test for bus collision
391  if (PIR3bits.BCL2IF){
392  return (-1);
393  }
394 
395  return (0);
396 }
397 #endif
398 
399 //************************************************************
400 // I2C1_read_byte_from_external_device function implementation
401 //************************************************************
402 
403 signed char I2C1_read_byte_from_external_device (unsigned char control_byte, unsigned char register_address, unsigned char *data){
404 
406  I2C1_start_bit();
407 
408  // test for bus collision
409  if (PIR2bits.BCLIF){
410  return (-1);
411  } else {
412  if (I2C1_write_byte(control_byte)) {
413  I2C1_stop_bit();
414  return (-3);
415  }
416 
417  // Check for ACK condition
418  if (!SSPCON2bits.ACKSTAT){
419  // WRITE word address for EEPROM
420  if (I2C1_write_byte(register_address)){
421  I2C1_stop_bit();
422  return (-3);
423  }
424 
425  // Check for ACK condition
426  if (!SSPCON2bits.ACKSTAT) {
427 
429 
430  // test for bus collision
431  if ( PIR2bits.BCLIF ){
432  return (-1);
433  }
434 
435  // write 1 byte - R/W bit should be 1
436  if (I2C1_write_byte(control_byte+1)){
437  I2C1_stop_bit();
438  return (-3);
439  }
440 
441  // Check for ACK condition
442  if (!SSPCON2bits.ACKSTAT ){
443  // enable master for 1 byte reception
444  SSPCON2bits.RCEN = 1;
445  // check that receive sequence is over
446  while ( SSPCON2bits.RCEN );
447 
448  // send ACK condition
450 
451  // send STOP condition
452  I2C1_stop_bit();
453 
454  // test for bus collision
455  if (PIR2bits.BCLIF) {
456  return (-1);
457  }
458  } else {
459  I2C1_stop_bit();
460  return (-2);
461  }
462  } else {
463  I2C1_stop_bit();
464  return (-2);
465  }
466  }
467  else
468  {
469  I2C1_stop_bit();
470  return (-2);
471  }
472  }
473 
474  // if no error occured the data is valid!
475  *data = SSPBUF;
476 
477  return (0);
478 }
479 
480 #ifdef I2C_MODULE_TYPE_2
481 signed char I2C2_read_byte_from_external_device (unsigned char control_byte, unsigned char register_address, unsigned char *data){
482  I2C2_wait_bus_IDLE();
483  I2C2_start_bit();
484 
485  // test for bus collision
486  if (PIR3bits.BCL2IF){
487  return (-1);
488  } else {
489  if (I2C2_write_byte(control_byte)) {
490  I2C2_stop_bit();
491  return (-3);
492  }
493 
494  // Check for ACK condition
495  if (!SSP2CON2bits.ACKSTAT){
496  // WRITE word address for EEPROM
497  if (I2C2_write_byte(register_address)){
498  I2C2_stop_bit();
499  return (-3);
500  }
501 
502  // Check for ACK condition
503  if (!SSP2CON2bits.ACKSTAT) {
504 
505  I2C2_restart_communication();
506 
507  // test for bus collision
508  if (PIR3bits.BCL2IF){
509  return (-1);
510  }
511 
512  // write 1 byte - R/W bit should be 1
513  if (I2C2_write_byte(control_byte+1)){
514  I2C1_stop_bit();
515  return (-3);
516  }
517 
518  // Check for ACK condition
519  if (!SSP2CON2bits.ACKSTAT){
520  // enable master for 1 byte reception
521  SSP2CON2bits.RCEN = 1;
522  // check that receive sequence is over
523  while (SSP2CON2bits.RCEN);
524 
525  // send ACK condition
526  I2C2_negative_ACK();
527 
528  // send STOP condition
529  I2C2_stop_bit();
530 
531  // test for bus collision
532  if (PIR3bits.BCL2IF) {
533  return (-1);
534  }
535  } else {
536  I2C2_stop_bit();
537  return (-2);
538  }
539  } else {
540  I2C2_stop_bit();
541  return (-2);
542  }
543  }
544  else {
545  I2C2_stop_bit();
546  return (-2);
547  }
548  }
549 
550  // if no error occured the data is valid!
551  *data = SSP2BUF;
552 
553  return (0);
554 }
555 #endif