Aktuální adresář: FITkit /
trunk /
apps /
communication /
1-wire_mcu /
mcu /
one_wire.c
1 /*******************************************************************************
2 main: rozhrani one wire
3 Copyright (C) 2009 Brno University of Technology,
4 Faculty of Information Technology
5 Author(s): Karel Slany <slany AT fit.vutbr.cz>
6
7 LICENSE TERMS
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in
16 the documentation and/or other materials provided with the
17 distribution.
18 3. All advertising materials mentioning features or use of this software
19 or firmware must display the following acknowledgement:
20
21 This product includes software developed by the University of
22 Technology, Faculty of Information Technology, Brno and its
23 contributors.
24
25 4. Neither the name of the Company nor the names of its contributors
26 may be used to endorse or promote products derived from this
27 software without specific prior written permission.
28
29 This software or firmware is provided ``as is'', and any express or implied
30 warranties, including, but not limited to, the implied warranties of
31 merchantability and fitness for a particular purpose are disclaimed.
32 In no event shall the company or contributors be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability, whether
37 in contract, strict liability, or tort (including negligence or
38 otherwise) arising in any way out of the use of this software, even
39 if advised of the possibility of such damage.
40
41 $Id$
42
43
44 *******************************************************************************/
45
46 /*
47 * Note:
48 *
49 * The source code is based o the source codes released in the following
50 * application notes related to the DS18B20 digital thermometer device.
51 *
52 * AN126 - 1-Wire Communication Through Software
53 * http://www.maxim-ic.com/app-notes/index.mvp/id/126
54 * http://pdfserv.maxim-ic.com/en/an/AN126.pdf
55 *
56 * AN187 - 1-Wire Search Algorithm
57 * http://www.maxim-ic.com/app-notes/index.mvp/id/187
58 * http://pdfserv.maxim-ic.com/en/an/AN187.pdf
59 *
60 */
61
62
63 #include <fitkitlib.h>
64
65 #include "one_wire.h"
66
67
68 /*******************************************************************************
69 * 1-wire global wariables
70 *******************************************************************************/
71 unsigned char ROM[ROM_BYTES]; // ROM bits
72 unsigned char last_discrep = 0; // last discrepancy
73 unsigned char done_flag = 0; // done flag
74 unsigned char found_ROMs[MAX_DEVICES][ROM_BYTES]; // table of found ROM codes
75 unsigned char num_ROMs;
76 unsigned char dowcrc;
77 unsigned char dscrc_table[] = {
78 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
79 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
80 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
81 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
82 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
83 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
84 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
85 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
86 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
87 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
88 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
89 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
90 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
91 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
92 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
93 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
94
95
96 /*******************************************************************************
97 * TimerB delay function, behaviour defined by timerb_init() - period 0.5425us
98 *******************************************************************************/
99 void delay_1us083(unsigned long us)
100 {
101 #if defined MSP_16X
102 #elif defined MSP_261X
103 TBCCR1 = (us << 1) + TBR;
104 while (TBR != TBCCR1) {}
105 #else
106 #error "Unknown CPU type"
107 #endif
108
109 }
110
111
112 /*******************************************************************************
113 * 1-wire bus reset
114 *******************************************************************************/
115 unsigned char ow_reset(void)
116 {
117 unsigned long presence; // 0 - presence, 1 - no part
118
119 DQ_dir_out(); // set output
120 DQ_set_0(); // and set it to 0
121 delay_500us();
122 DQ_dir_in(); // set input
123 delay_60us();
124
125 presence = DQ_read();
126
127 delay_420us();
128
129 return presence;
130 }
131
132
133 /*******************************************************************************
134 * read one bit
135 *******************************************************************************/
136 unsigned char ow_read_bit(void)
137 {
138 unsigned char bit;
139
140 delay_7us();
141
142 DQ_dir_out(); // out
143 DQ_set_0(); // 0
144 delay_7us();
145 DQ_dir_in(); // in
146 delay_7us();
147
148 bit = DQ_read(); // read bus
149
150 delay_80us();
151
152 return(bit);
153 }
154
155
156 /*******************************************************************************
157 * write one bit
158 *******************************************************************************/
159 void ow_write_bit(unsigned char bit)
160 {
161 DQ_dir_out(); // out
162 DQ_set_0(); // 0
163 delay_7us();
164
165 if (bit)
166 DQ_set_1(); // 1
167 else
168 DQ_set_0(); // 0
169 delay_80us();
170
171 DQ_dir_in();
172 delay_7us();
173 }
174
175
176 /*******************************************************************************
177 * read one byte
178 *******************************************************************************/
179 unsigned char ow_read_byte(void)
180 {
181 unsigned char i;
182 unsigned char byte = 0;
183
184 for (i = 0; i < 8; i++)
185 {
186 if (ow_read_bit())
187 byte |= 0x01 << i;
188 }
189
190 return byte;
191 }
192
193
194 /*******************************************************************************
195 * write one byte
196 *******************************************************************************/
197 void ow_write_byte(unsigned char byte)
198 {
199 unsigned char i;
200
201 for (i = 0; i < 8; i++)
202 {
203 ow_write_bit((byte >> i) & 0x01);
204 }
205 }
206
207
208 /*******************************************************************************
209 * 1-wire crc
210 *******************************************************************************/
211 unsigned char ow_crc(unsigned char x)
212 {
213 dowcrc = dscrc_table[dowcrc^x];
214 return dowcrc;
215 }
216
217
218 /*******************************************************************************
219 * next
220 * The function searches for the next device on the 1-wire bus. If
221 * there are no more devices on the 1-wire then false is returned.
222 *******************************************************************************/
223 unsigned char next(void)
224 {
225 unsigned char bit_i = 1; // ROM bit index
226 unsigned char byte_i = 0; // ROM byte index
227 unsigned char bit_mask = 1; // bit mask
228 unsigned char x = 0;
229 unsigned char discrep_marker = 0; // discrepancy marker
230 unsigned char out_bit; // output bit
231 unsigned char nxt; // return value
232 int flag;
233
234 nxt = FALSE; // set the next flag to false
235 dowcrc = 0; // reset the dowcrc
236 flag = ow_reset(); // reset the 1-wire
237
238 if (flag || done_flag) // no parts -> return false
239 {
240 last_discrep = 0; // reset the search
241 return FALSE;
242 }
243
244 ow_write_byte(0xF0); // send search ROM command
245 do // for all eight bytes
246 {
247 x = 0;
248 if (ow_read_bit())
249 x = 0x02;
250 if (ow_read_bit())
251 x |= 0x01; // and its complement
252 if (x == 0x03) // there are no devices on the 1-wire
253 break;
254 else
255 {
256 if(x > 0) // all devices coupled have 0 or 1
257 out_bit = x >> 1; // bit write value for search
258 else
259 {
260 // if this discrepancy is before the last
261 // discrepancy on a previous next call then pick
262 // the same as last time
263 if (bit_i < last_discrep)
264 out_bit = ((ROM[byte_i] & bit_mask) > 0);
265 else // if equal to last pick 1
266 out_bit = (bit_i == last_discrep); // if not then pick 0
267 // if 0 was picked then record
268 // position with mask bit_mask
269 if (out_bit == 0)
270 discrep_marker = bit_i;
271 }
272 if (out_bit == 1) // isolate bit in ROM[byte_i] with mask bit_mask
273 ROM[byte_i] |= bit_mask;
274 else
275 ROM[byte_i] &= ~bit_mask;
276 ow_write_bit(out_bit); // ROM search write
277 bit_i++; // increment bit counter bit_i
278 bit_mask = bit_mask << 1; // and shift the bit mask bit_mask
279 if (bit_mask == 0) // if the mask is 0 then go to new ROM
280 { // byte byte_i and reset mask
281 ow_crc(ROM[byte_i]); // accumulate the CRC
282 byte_i++; bit_mask++;
283 }
284 }
285 } while (byte_i < ROM_BYTES); // loop until through all ROM bytes 0-7
286
287 if (bit_i < 65 || dowcrc) // if search was unsuccessful then
288 last_discrep = 0; // reset the last discrepancy to 0
289 else
290 {
291 // search was successful, so set last_discrep,
292 // done_flag, nxt
293 last_discrep = discrep_marker;
294 done_flag = (last_discrep == 0);
295 nxt = TRUE; // indicates search is not complete yet, more
296 // parts remain
297 }
298
299 return nxt;
300
301 }
302
303
304 /*******************************************************************************
305 * first
306 * The function resets the current state of a ROM search and calls
307 * function next to find the first device on the 1-wire bus.
308 *******************************************************************************/
309 unsigned char first(void)
310 {
311 last_discrep = 0; // reset the ROM search last discrepancy global
312 done_flag = FALSE;
313 return next(); // call next and return its return value
314 }
315
316
317 /*******************************************************************************
318 * searches for devices connected to the 1-wire
319 *******************************************************************************/
320 void ow_find_devices(void)
321 {
322 unsigned char m;
323
324 if (!ow_reset()) // begins when a presence is detected
325 {
326 if (first()) // begins when at least one part is found
327 {
328 num_ROMs = 0;
329 do
330 {
331 //num_ROMs++;
332 for (m = 0; m < ROM_BYTES; m++)
333 {
334 found_ROMs[num_ROMs][m] = ROM[m]; // identifies ROM
335 // number on found device
336 }
337 num_ROMs++;
338 } while (next() && (num_ROMs < MAX_DEVICES)); // continues until no additional devices are found
339 }
340 }
341
342 }
343
344
345 /*******************************************************************************
346 * perform match ROM
347 *******************************************************************************/
348 unsigned char ow_send_match_rom(unsigned char idx)
349 {
350 unsigned char i;
351 if (ow_reset())
352 return FALSE;
353 ow_write_byte(0x55); // match ROM
354 for (i = 0; i < ROM_BYTES; i++)
355 {
356 ow_write_byte(found_ROMs[idx][i]); // send ROM code
357 }
358 return TRUE;
359
360 }
361