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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (hide 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 torben 77 #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