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