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

Annotation of /trunk/PIC/i2c.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Mon Jan 29 09:45:25 2007 UTC (17 years, 4 months ago) by torben
File MIME type: text/plain
File size: 6368 byte(s)
Initial import of PIC module
1 torben 2 #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