PIC18 LaurTec Library  3.3.1
Open Source C Library for PIC18 Microcontrollers based on C18 - XC8 Compilers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
i2cEEPROM.c
Go to the documentation of this file.
1 /*******************************************************************************
2 
3 Author : Mauro Laurenti
4 Version : 1.3
5 
6 Created on Date : 04/09/2006
7 Last update : 15/12/2014
8 
9 CopyRight 2006-2014 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 PURPOSES
38 ********************************************************
39 
40 These functions allow the user to read/write inside the eeprom
41 that requires 2 address bytes such as the 24LC512.
42 
43 ********************************************************************************/
44 
45 #ifdef __XC8
46 #include <xc.h>
47 #endif
48 
49 #include "i2cEEPROM.h"
50 
51 
52 
53 //************************************************************
54 // I2C_EEPROM_initialize function implementation
55 //************************************************************
56 void I2C_EEPROM_initialize (unsigned char crystal_frequency_MHz, unsigned int baud_rate_KHz){
57 
58  OpenI2C(MASTER, SLEW_ON);
59 
60  SSPADD = (((crystal_frequency_MHz *1000)/4)/baud_rate_KHz)-1;
61 
62  // Imposto il quarzo per la libreria delay
63  setQuartz (crystal_frequency_MHz);
64 }
65 
66 
67 
68 //************************************************************
69 // I2C_EEPROM_write function implementation
70 //************************************************************
71 
72 signed char I2C_EEPROM_write ( unsigned char control, unsigned int address, unsigned char data ){
73 
74  unsigned char addressH;
75  unsigned char addressL;
76 
77  addressH = (unsigned char) ((address & 0xFF00) >> 8);
78  addressL = (unsigned char) (address & 0x00FF);
79 
80 //*****************************
81 // Start Condition and control
82 // Byte are sent
83 //*****************************
84 
85  // Check if the module is idle
86  IdleI2C();
87  // Initiate START condition
88  StartI2C();
89 
90  // Wait until start condition is over
91  while (SSPCON2bits.SEN);
92 
93  // Check if Bus collision happened
94  if (PIR2bits.BCLIF) {
95  // Return with Bus Collision error
96  return (-1);
97  }
98 
99  // Write control byte - R/W bit should be 0
100  if (WriteI2C(control)){
101  // Return with write Collision error
102  return (-3);
103  }
104 
105 //*****************************
106 // Address High is sent
107 //*****************************
108 
109  // Check if the module is idle
110  IdleI2C();
111 
112  // Check if ACK condition has been received
113  if (!SSPCON2bits.ACKSTAT){
114 
115  // Write address high to the EEPROM
116  if (WriteI2C(addressH)){
117  // Return with write Collision error
118  return (-3);
119  }
120  } else {
121  // Return with Not Ack error condition
122  return (-2);
123  }
124 
125 //*****************************
126 // Address Low is sent
127 //*****************************
128 
129  // Check if the module is idle
130  IdleI2C();
131 
132  // Check if ACK condition has been received
133  if (!SSPCON2bits.ACKSTAT) {
134 
135  // Write address low to the EEPROM
136  if (WriteI2C(addressL)) {
137  // Return with write Collision error
138  return (-3);
139  }
140  } else {
141  // Return with Not Ack error condition
142  return (-2);
143  }
144 
145 //*****************************
146 // Data Byte is sent
147 //*****************************
148 
149  // Check if the module is idle
150  IdleI2C();
151 
152  // Check if ACK condition has been received
153  if (!SSPCON2bits.ACKSTAT){
154 
155  // Write data byte to the EEPROM
156  if (WriteI2C(data)) {
157  // Return with write Collision error
158  return (-3);
159  }
160  } else {
161  // Return with Not Ack error condition
162  return (-2);
163  }
164 
165 //*****************************
166 // Stop command is sent
167 //*****************************
168 
169  // Check if the module is idle
170  IdleI2C();
171 
172  // Check if ACK condition has been received
173  if (!SSPCON2bits.ACKSTAT) {
174 
175  // Send STOP condition
176  StopI2C();
177 
178  // Wait until stop condition is over
179  while (SSPCON2bits.PEN);
180 
181  } else {
182  // Return with Not Ack error condition
183  return (-2);
184  }
185 
186  // Test for bus collision
187  if (PIR2bits.BCLIF){
188  // Return with Bus Collision error
189  return (-1);
190  }
191 
192  // Return with no error
193  return (1);
194 }
195 
196 
197 //************************************************************
198 // I2C_EEPROM_write_check function implementation
199 //************************************************************
200 
201 signed char I2C_EEPROM_write_check (unsigned char control, unsigned int address, unsigned char data ) {
202 
203  // Store the returned error from the read and write function call
204  signed char error;
205 
206  // Store the data read back from the EEPROM
207  unsigned char dataReadback;
208 
209  error = write_I2C_EEPROM(control, address, data);
210 
211  if (error < 0)
212  return (error);
213 
214  // wait for the write process to be completed
215  delay_ms (6);
216 
217  error = read_I2C_EEPROM (control, address, &dataReadback);
218 
219  if (error < 0)
220  return (error);
221 
222  if (dataReadback == data)
223  return (1);
224  else
225  return(-4);
226 }
227 
228 
229 //************************************************************
230 // I2C_EEPROM_read function implementation
231 //************************************************************
232 
233 signed char I2C_EEPROM_read ( unsigned char control, unsigned int address, unsigned char *data) {
234 
235  unsigned char addressH;
236  unsigned char addressL;
237 
238  addressH = (unsigned char) ((address & 0xFF00) >> 8);
239  addressL = (unsigned char) (address & 0x00FF);
240 
241 
242 //*****************************
243 // Start Condition and control
244 // Byte are sent
245 //*****************************
246 
247  // Check if the module is idle
248  IdleI2C();
249  // Initiate START condition
250  StartI2C();
251 
252  // Wait until start condition is over
253  while (SSPCON2bits.SEN);
254 
255  // Check if Bus collision happened
256  if (PIR2bits.BCLIF) {
257  // Return with Bus Collision error
258  return (-1);
259  }
260 
261  // Write Control Byte
262  if (WriteI2C(control)){
263  // Return with write collision error
264  return (-3);
265  }
266 
267 //*****************************
268 // Address High is sent
269 //*****************************
270 
271  // Check if the module is idle
272  IdleI2C();
273 
274  // Check if ACK condition has been received
275  if (!SSPCON2bits.ACKSTAT) {
276 
277  // Write address high to the EEPROM
278  if (WriteI2C(addressH)){
279  // Return with write collision error
280  return (-3);
281  }
282  }else {
283  // Return with Not Ack error condition
284  return (-2);
285  }
286 
287 //*****************************
288 // Address Low is sent
289 //*****************************
290  // Check if the module is idle
291  IdleI2C();
292 
293  // Check if ACK condition has been received
294  if (!SSPCON2bits.ACKSTAT) {
295  // Write address low to the EEPROM
296  if (WriteI2C(addressL)) {
297  // Return with write collision error
298  return (-3);
299  }
300  }else {
301  // Return with Not Ack error condition
302  return (-2);
303  }
304 
305 
306 //*****************************
307 // Restart condition
308 //*****************************
309  // Check if the module is idle
310  IdleI2C();
311 
312  // Check if ACK condition has been received
313  if (!SSPCON2bits.ACKSTAT){
314 
315  // Initiate I2C bus restart condition
316  RestartI2C();
317  // Wait until re-start condition is over
318  while (SSPCON2bits.RSEN);
319 
320  // Check if Bus collision happened
321  if (PIR2bits.BCLIF) {
322  // Return with Bus Collision error
323  return (-1);
324  }
325 
326  // Write Control byte - This time R/W bit should be 1
327  if (WriteI2C(control+1)) {
328  // Return with write collision error
329  return (-3);
330  }
331 
332 //*****************************
333 // Data is Read
334 //*****************************
335 
336  // Check if the module is idle
337  IdleI2C();
338 
339  // Check if ACK condition has been received
340  if (!SSPCON2bits.ACKSTAT){
341 
342  // Enable master for 1 byte reception
343  SSPCON2bits.RCEN = 1;
344 
345  // Check that receive sequence is over
346  while (SSPCON2bits.RCEN);
347 
348  // Send not ACK condition
349  NotAckI2C();
350 
351  // Wait until ACK sequence is over
352  while (SSPCON2bits.ACKEN );
353 
354  // Send STOP condition
355  StopI2C();
356 
357  // Wait until stop condition is over
358  while (SSPCON2bits.PEN);
359 
360  // Check if Bus collision happened
361  if (PIR2bits.BCLIF) {
362  // return with Bus Collision error
363  return (-1);
364  }
365 
366  } else {
367  // Return with Not Ack error
368  return (-2);
369  }
370 
371  } else {
372  // Return with Not Ack error
373  return (-2);
374  }
375 
376  // Data is read from the buffer
377  *data = SSPBUF;
378 
379  // No error occurred
380  return (1);
381 }
382 
383