/[H7]/trunk/PIC/i2c.c
ViewVC logotype

Contents of /trunk/PIC/i2c.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Mon Jan 29 09:45:25 2007 UTC (17 years, 3 months ago) by torben
File MIME type: text/plain
File size: 6368 byte(s)
Initial import of PIC module
1 #include <pic18.h>
2 #include "delay.h"
3 #include "i2c.h"
4
5 /*
6 * I2C functions for HI-TECH PIC C - master mode only
7 */
8
9 /*
10 * TIMING - see Philips document: THE I2C-BUS SPECIFICATION
11 */
12
13
14 /*
15 * Send stop condition
16 * - data low-high while clock high
17 */
18
19 void
20 i2c_Stop(void)
21 {
22 /* don't assume SCL is high on entry */
23
24 SDA_LOW(); /* ensure data is low first */
25 SCL_HIGH();
26
27 DelayUs(I2C_TM_DATA_SU);
28 SCL_DIR = I2C_INPUT; /* float clock high */
29 DelayUs(I2C_TM_STOP_SU);
30 SDA_HIGH(); /* the low->high data transistion */
31 DelayUs(I2C_TM_BUS_FREE); /* bus free time before next start */
32 SDA_DIR = I2C_INPUT; /* float data high */
33
34 return;
35 }
36
37 /*
38 * Send (re)start condition
39 * - ensure data is high then issue a start condition
40 * - see also i2c_Start() macro
41 */
42
43 void
44 i2c_Restart(void)
45 {
46 SCL_LOW(); /* ensure clock is low */
47 SDA_HIGH(); /* ensure data is high */
48
49 DelayUs(I2C_TM_DATA_SU);
50
51 SCL_DIR = I2C_INPUT; /* clock pulse high */
52 DelayUs(I2C_TM_SCL_HIGH);
53
54 SDA_LOW(); /* the high->low transition */
55 DelayUs(I2C_TM_START_HD);
56 return;
57 }
58
59 /*
60 * Send a byte to the slave
61 * - returns true on error
62 */
63
64 unsigned char
65 i2c_SendByte(unsigned char byte)
66 {
67 signed char i;
68
69 for(i=7; i>=0; i--)
70 {
71 SCL_LOW(); /* drive clock low */
72 /* data hold time = 0, send data now */
73 SDA_DIR = ((byte>>i)&0x01);
74 if ((byte>>i)&0x01) { /* bit to send */
75 SDA_HIGH();
76 }
77 else {
78 SDA_LOW();
79 }
80 DelayUs(I2C_TM_DATA_SU);
81 SCL_DIR = I2C_INPUT; /* float clock high */
82
83 if(i2c_WaitForSCL()) /* wait for clock release */
84 return TRUE; /* bus error */
85
86 DelayUs(I2C_TM_SCL_HIGH); /* clock high time */
87 }
88
89
90 return FALSE;
91 }
92
93 /*
94 * send an address and data direction to the slave
95 * - 7-bit address (lsb ignored)
96 * - direction (FALSE = write )
97 */
98
99 unsigned char
100 i2c_SendAddress(unsigned char address, unsigned char rw)
101 {
102 return i2c_SendByte(address | (rw?1:0));
103 }
104
105 /*
106 * Check for an acknowledge
107 * - returns ack or ~ack, or ERROR if a bus error
108 */
109
110 signed char
111 i2c_ReadAcknowledge(void)
112 {
113 unsigned char ack;
114
115 SCL_LOW(); /* make clock is low */
116 SDA_DIR = I2C_INPUT; /* disable data line - listen for ack */
117 DelayUs(I2C_TM_SCL_TO_DATA); /* SCL low to data out valid */
118 SCL_DIR = I2C_INPUT; /* float clock high */
119 DelayUs(I2C_TM_DATA_SU);
120 ack = SDA; /* read the acknowledge */
121
122 /* wait for slave to release clock line after processing byte */
123 if(i2c_WaitForSCL())
124 return I2C_ERROR;
125 return ack;
126 }
127
128 /*
129 * Read a byte from the slave
130 * - returns the byte, or I2C_ERROR if a bus error
131 */
132
133 int
134 i2c_ReadByte(void)
135 {
136 unsigned char i;
137 unsigned char byte = 0;
138
139 for(i=0; i<8; i++)
140 {
141 SCL_LOW(); /* drive clock low */
142 DelayUs(I2C_TM_SCL_LOW); /* min clock low period */
143 SDA_DIR = I2C_INPUT; /* release data line */
144
145 SCL_DIR = I2C_INPUT; /* float clock high */
146 if(i2c_WaitForSCL())
147 return I2C_ERROR;
148 DelayUs(I2C_TM_SCL_HIGH);
149 byte = byte << 1; /* read the next bit */
150 byte |= SDA;
151 }
152 return (int)byte;
153 }
154
155 /*
156 * Send an (~)acknowledge to the slave
157 * - status of I2C_LAST implies this is the last byte to be sent
158 */
159
160 void
161 i2c_SendAcknowledge(unsigned char status)
162 {
163 SCL_LOW();
164 if ( status & 0x01) {
165 SDA_LOW(); /* drive line low -> more to come */
166 }
167 else {
168 SDA_HIGH();
169 }
170 DelayUs(I2C_TM_DATA_SU);
171 SCL_DIR = I2C_INPUT; /* float clock high */
172 DelayUs(I2C_TM_SCL_HIGH);
173 return;
174 }
175
176 /*
177 * Send a byte to the slave and acknowledges the transfer
178 * - returns I2C_ERROR, ack or ~ack
179 */
180
181 signed char
182 i2c_PutByte(unsigned char data)
183 {
184 if(i2c_SendByte(data))
185 return I2C_ERROR;
186 return i2c_ReadAcknowledge(); /* returns ack, ~ack */
187 }
188
189 /*
190 * Get a byte from the slave and acknowledges the transfer
191 * - returns true on I2C_ERROR or byte
192 */
193
194 int
195 i2c_GetByte(unsigned char more)
196 {
197 int byte;
198
199 if((byte = i2c_ReadByte()) == I2C_ERROR)
200 return I2C_ERROR;
201
202 i2c_SendAcknowledge(more);
203
204 return byte;
205 }
206
207 /*
208 * Send an array of bytes to the slave and acknowledges the transfer
209 * - returns number of bytes not successfully transmitted
210 */
211
212 int
213 i2c_PutString(const unsigned char *str, unsigned char length)
214 {
215 signed char error;
216
217 while(length)
218 {
219 if((error = i2c_PutByte(*str)) == I2C_ERROR)
220 return -(int)length; /* bus error */
221 else
222 if(error)
223 return (int)length; /* non acknowledge */
224 str++;
225 length--;
226 }
227
228 return FALSE; /* everything OK */
229 }
230
231 /*
232 * Reads number bytes from the slave, stores them at str and acknowledges the transfer
233 * - returns number of bytes not successfully read in
234 */
235
236 unsigned char
237 i2c_GetString(unsigned char *str, unsigned char number)
238 {
239 int byte;
240
241 while(number)
242 {
243 if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
244 return number; /* bus error */
245 else
246 *str = (unsigned char)byte;
247 str++;
248 number--;
249 }
250
251 return FALSE; /* everything OK */
252 }
253
254 /*
255 * Opens communication with a device at address. mode
256 * indicates I2C_READ or I2C_WRITE.
257 * - returns TRUE if address is not acknowledged
258 */
259
260 unsigned char
261 i2c_Open(unsigned char address, unsigned char mode)
262 {
263 i2c_Start();
264 i2c_SendAddress(address, mode);
265 if(i2c_ReadAcknowledge())
266 return TRUE;
267
268 return FALSE;
269 }
270
271 /*
272 * wait for the clock line to be released by slow slaves
273 * - returns TRUE if SCL was not released after the
274 * time out period.
275 * - returns FALSE if and when SCL released
276 */
277
278 unsigned char
279 i2c_WaitForSCL(void)
280 {
281 /* SCL_DIR should be input here */
282
283 if(!SCL)
284 {
285 DelayUs(I2C_TM_SCL_TMO);
286 /* if the clock is still low -> bus error */
287 if(!SCL)
288 return TRUE;
289 }
290 return FALSE;
291 }
292 void
293 i2c_Free()
294 {
295 unsigned char ucI;
296
297 SDA_DIR=I2C_INPUT;
298 for(ucI=0;ucI!=9;ucI++)
299 {
300 SCL_HIGH();
301 DelayUs(5);
302 SCL_LOW();
303 DelayUs(5);
304 }
305 }
306
307 unsigned char i2c_read(unsigned char ucAdr)
308 {
309 unsigned char ucDat;
310
311 if (i2c_ReadFrom(ucAdr)==0)
312 {
313 ucDat=i2c_GetByte(I2C_MORE);
314 i2c_Stop();
315
316 }
317
318 return(ucDat);
319 }

  ViewVC Help
Powered by ViewVC 1.1.20