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