/[H8]/trunk/PIC/Torbens/i2c.c
ViewVC logotype

Contents of /trunk/PIC/Torbens/i2c.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20