Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OneWire by
OneWire.cpp
00001 /* 00002 Copyright (c) 2007, Jim Studt (original old version - many contributors since) 00003 00004 The latest version of this library may be found at: 00005 http://www.pjrc.com/teensy/td_libs_OneWire.html 00006 00007 OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since 00008 January 2010. At the time, it was in need of many bug fixes, but had 00009 been abandoned the original author (Jim Studt). None of the known 00010 contributors were interested in maintaining OneWire. Paul typically 00011 works on OneWire every 6 to 12 months. Patches usually wait that 00012 long. If anyone is interested in more actively maintaining OneWire, 00013 please contact Paul. 00014 00015 Version 2.2: 00016 Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com 00017 Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030 00018 Fix DS18B20 example negative temperature 00019 Fix DS18B20 example's low res modes, Ken Butcher 00020 Improve reset timing, Mark Tillotson 00021 Add const qualifiers, Bertrik Sikken 00022 Add initial value input to crc16, Bertrik Sikken 00023 Add target_search() function, Scott Roberts 00024 00025 Version 2.1: 00026 Arduino 1.0 compatibility, Paul Stoffregen 00027 Improve temperature example, Paul Stoffregen 00028 DS250x_PROM example, Guillermo Lovato 00029 PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com 00030 Improvements from Glenn Trewitt: 00031 - crc16() now works 00032 - check_crc16() does all of calculation/checking work. 00033 - Added read_bytes() and write_bytes(), to reduce tedious loops. 00034 - Added ds2408 example. 00035 Delete very old, out-of-date readme file (info is here) 00036 00037 Version 2.0: Modifications by Paul Stoffregen, January 2010: 00038 http://www.pjrc.com/teensy/td_libs_OneWire.html 00039 Search fix from Robin James 00040 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 00041 Use direct optimized I/O in all cases 00042 Disable interrupts during timing critical sections 00043 (this solves many random communication errors) 00044 Disable interrupts during read-modify-write I/O 00045 Reduce RAM consumption by eliminating unnecessary 00046 variables and trimming many to 8 bits 00047 Optimize both crc8 - table version moved to flash 00048 00049 Modified to work with larger numbers of devices - avoids loop. 00050 Tested in Arduino 11 alpha with 12 sensors. 00051 26 Sept 2008 -- Robin James 00052 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 00053 00054 Updated to work with arduino-0008 and to include skip() as of 00055 2007/07/06. --RJL20 00056 00057 Modified to calculate the 8-bit CRC directly, avoiding the need for 00058 the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010 00059 -- Tom Pollard, Jan 23, 2008 00060 00061 Jim Studt's original library was modified by Josh Larios. 00062 00063 Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008 00064 00065 Permission is hereby granted, free of charge, to any person obtaining 00066 a copy of this software and associated documentation files (the 00067 "Software"), to deal in the Software without restriction, including 00068 without limitation the rights to use, copy, modify, merge, publish, 00069 distribute, sublicense, and/or sell copies of the Software, and to 00070 permit persons to whom the Software is furnished to do so, subject to 00071 the following conditions: 00072 00073 The above copyright notice and this permission notice shall be 00074 included in all copies or substantial portions of the Software. 00075 00076 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00077 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00078 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00079 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00080 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00081 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00082 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00083 00084 Much of the code was inspired by Derek Yerger's code, though I don't 00085 think much of that remains. In any event that was.. 00086 (copyleft) 2006 by Derek Yerger - Free to distribute freely. 00087 00088 The CRC code was excerpted and inspired by the Dallas Semiconductor 00089 sample code bearing this copyright. 00090 //--------------------------------------------------------------------------- 00091 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. 00092 // 00093 // Permission is hereby granted, free of charge, to any person obtaining a 00094 // copy of this software and associated documentation files (the "Software"), 00095 // to deal in the Software without restriction, including without limitation 00096 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 00097 // and/or sell copies of the Software, and to permit persons to whom the 00098 // Software is furnished to do so, subject to the following conditions: 00099 // 00100 // The above copyright notice and this permission notice shall be included 00101 // in all copies or substantial portions of the Software. 00102 // 00103 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00104 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00105 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00106 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES 00107 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00108 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00109 // OTHER DEALINGS IN THE SOFTWARE. 00110 // 00111 // Except as contained in this notice, the name of Dallas Semiconductor 00112 // shall not be used except as stated in the Dallas Semiconductor 00113 // Branding Policy. 00114 //-------------------------------------------------------------------------- 00115 */ 00116 00117 #include "OneWire.h" 00118 00119 OneWire::OneWire(PinName pin): 00120 wire(pin) 00121 { 00122 #if ONEWIRE_SEARCH 00123 reset_search(); 00124 #endif 00125 } 00126 00127 00128 // Perform the onewire reset function. We will wait up to 250uS for 00129 // the bus to come high, if it doesn't then it is broken or shorted 00130 // and we return a 0; 00131 // 00132 // Returns ONEWIRE_OK if a device asserted a presence pulse, ONEWIRE_ERROR otherwise. 00133 // 00134 00135 00136 uint8_t OneWire::init_sequence() 00137 { 00138 uint16_t retries = 20000; 00139 00140 //if( reset() != ONEWIRE_OK ) 00141 // return ONEWIRE_ERROR; 00142 00143 reset(); 00144 00145 //wire.input(); should be input coming out of reset 00146 00147 wait_us(80); 00148 00149 while( wire == 0 ) 00150 { 00151 if (--retries == 0) { 00152 return ONEWIRE_NO_RESPONSE; 00153 } 00154 wait_us(20); 00155 } 00156 00157 return ONEWIRE_OK; 00158 00159 00160 00161 00162 } 00163 00164 uint8_t OneWire::reset( bool force/* = true*/ ) 00165 { 00166 /*uint8_t retries = 125; 00167 00168 wire.input(); 00169 // wait until the wire is high... just in case 00170 00171 do { 00172 if (--retries == 0) 00173 { 00174 if( force ) 00175 break; 00176 else 00177 return ONEWIRE_ERROR; 00178 } 00179 wait_us(2); 00180 } while (wire != 1);*/ 00181 00182 wire.output(); 00183 wire = 0; 00184 wait_us(480); 00185 wire.input(); 00186 00187 //wait_us(70); 00188 /*uint8_t err = wire; //just do the reset, use init_seq function to do more 00189 00190 wait_us(240); 00191 if ( wire == 0 ) { // short circuit 00192 printf("OneWire::reset SHORT_CIRCUIT\r\n"); 00193 return ONEWIRE_ERROR_SHORT_CIRCUIT; 00194 }*/ 00195 00196 //printf("OneWire::reset OK\r\n"); 00197 return ONEWIRE_OK; 00198 } 00199 00200 // 00201 // Write a bit. Port and bit is used to cut lookup time and provide 00202 // more certain timing. 00203 // 00204 void OneWire::write_bit(uint8_t v) 00205 { 00206 wire.output(); 00207 00208 if (v & 1) { 00209 wire = 0; // drive output low 00210 wait_us(10); 00211 wire = 1; // drive output high 00212 wait_us(55); 00213 } else { 00214 wire = 0; // drive output low 00215 wait_us(65); 00216 wire = 1; // drive output high 00217 wait_us(5); 00218 } 00219 } 00220 00221 // 00222 // Read a bit. Port and bit is used to cut lookup time and provide 00223 // more certain timing. 00224 // 00225 uint8_t OneWire::read_bit(void) 00226 { 00227 uint8_t r; 00228 00229 wire.output(); 00230 wire = 0; 00231 wait_us(2); //modified to meet ray's values 00232 wire.input(); 00233 wait_us(14); 00234 r = wire.read(); 00235 wait_us(48); 00236 00237 return r; 00238 } 00239 00240 // 00241 // Write a byte. The writing code uses the active drivers to raise the 00242 // pin high, if you need power after the write (e.g. DS18S20 in 00243 // parasite power mode) then set 'power' to 1, otherwise the pin will 00244 // go tri-state at the end of the write to avoid heating in a short or 00245 // other mishap. 00246 // 00247 void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { 00248 uint8_t bitMask; 00249 00250 //printf("OneWire::write => %#x\r\n", v); 00251 00252 for (bitMask = 0x01; bitMask; bitMask <<= 1) { 00253 OneWire::write_bit( (bitMask & v)?1:0); 00254 } 00255 if ( !power) { 00256 wire.input(); 00257 } 00258 } 00259 00260 void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { 00261 00262 for (uint16_t i = 0 ; i < count ; i++) 00263 { 00264 write(buf[i]); 00265 } 00266 00267 if (!power) { 00268 wire.input(); 00269 } 00270 } 00271 00272 // 00273 // Read a byte 00274 // 00275 uint8_t OneWire::read() { 00276 uint8_t bitMask; 00277 uint8_t r = 0; 00278 00279 for (bitMask = 0x01; bitMask; bitMask <<= 1) 00280 { 00281 if ( OneWire::read_bit()) r |= bitMask; 00282 } 00283 00284 return r; 00285 } 00286 00287 void OneWire::read_bytes(uint8_t *buf, uint16_t count) { 00288 for (uint16_t i = 0 ; i < count ; i++) 00289 { 00290 buf[i] = read(); 00291 } 00292 } 00293 00294 // 00295 // Do a ROM select 00296 // 00297 void OneWire::select(const uint8_t rom[8]) 00298 { 00299 uint8_t i; 00300 00301 write(0x55); // Choose ROM 00302 00303 for (i = 0; i < 8; i++) write(rom[i]); 00304 } 00305 00306 // 00307 // Do a ROM skip 00308 // 00309 void OneWire::skip() 00310 { 00311 write(0xCC); // Skip ROM 00312 } 00313 00314 void OneWire::depower() 00315 { 00316 wire.input(); 00317 } 00318 00319 #if ONEWIRE_SEARCH 00320 00321 // 00322 // You need to use this function to start a search again from the beginning. 00323 // You do not need to do it for the first search, though you could. 00324 // 00325 void OneWire::reset_search() 00326 { 00327 // reset the search state 00328 LastDiscrepancy = 0; 00329 LastDeviceFlag = false; 00330 LastFamilyDiscrepancy = 0; 00331 for(int i = 7; ; i--) { 00332 ROM_NO[i] = 0; 00333 if ( i == 0) break; 00334 } 00335 } 00336 00337 // Setup the search to find the device type 'family_code' on the next call 00338 // to search(*newAddr) if it is present. 00339 // 00340 void OneWire::target_search(uint8_t family_code) 00341 { 00342 // set the search state to find SearchFamily type devices 00343 ROM_NO[0] = family_code; 00344 for (uint8_t i = 1; i < 8; i++) 00345 ROM_NO[i] = 0; 00346 LastDiscrepancy = 64; 00347 LastFamilyDiscrepancy = 0; 00348 LastDeviceFlag = false; 00349 } 00350 00351 // 00352 // Perform a search. If this function returns a '1' then it has 00353 // enumerated the next device and you may retrieve the ROM from the 00354 // OneWire::address variable. If there are no devices, no further 00355 // devices, or something horrible happens in the middle of the 00356 // enumeration then a 0 is returned. If a new device is found then 00357 // its address is copied to newAddr. Use OneWire::reset_search() to 00358 // start over. 00359 // 00360 // --- Replaced by the one from the Dallas Semiconductor web site --- 00361 //-------------------------------------------------------------------------- 00362 // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing 00363 // search state. 00364 // Return true : device found, ROM number in ROM_NO buffer 00365 // false : device not found, end of search 00366 // 00367 uint8_t OneWire::search(uint8_t *newAddr) 00368 { 00369 uint8_t id_bit_number; 00370 uint8_t last_zero, rom_byte_number, search_result; 00371 uint8_t id_bit, cmp_id_bit; 00372 00373 unsigned char rom_byte_mask, search_direction; 00374 00375 // initialize for search 00376 id_bit_number = 1; 00377 last_zero = 0; 00378 rom_byte_number = 0; 00379 rom_byte_mask = 1; 00380 search_result = 0; 00381 00382 // if the last call was not the last one 00383 if (!LastDeviceFlag) 00384 { 00385 // 1-Wire reset 00386 if (!reset()) 00387 { 00388 // reset the search 00389 LastDiscrepancy = 0; 00390 LastDeviceFlag = false; 00391 LastFamilyDiscrepancy = 0; 00392 return false; 00393 } 00394 00395 // issue the search command 00396 write(0xF0); 00397 00398 // loop to do the search 00399 do 00400 { 00401 // read a bit and its complement 00402 id_bit = read_bit(); 00403 cmp_id_bit = read_bit(); 00404 00405 // check for no devices on 1-wire 00406 if ((id_bit == 1) && (cmp_id_bit == 1)) 00407 break; 00408 else 00409 { 00410 // all devices coupled have 0 or 1 00411 if (id_bit != cmp_id_bit) 00412 search_direction = id_bit; // bit write value for search 00413 else 00414 { 00415 // if this discrepancy if before the Last Discrepancy 00416 // on a previous next then pick the same as last time 00417 if (id_bit_number < LastDiscrepancy) 00418 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); 00419 else 00420 // if equal to last pick 1, if not then pick 0 00421 search_direction = (id_bit_number == LastDiscrepancy); 00422 00423 // if 0 was picked then record its position in LastZero 00424 if (search_direction == 0) 00425 { 00426 last_zero = id_bit_number; 00427 00428 // check for Last discrepancy in family 00429 if (last_zero < 9) 00430 LastFamilyDiscrepancy = last_zero; 00431 } 00432 } 00433 00434 // set or clear the bit in the ROM byte rom_byte_number 00435 // with mask rom_byte_mask 00436 if (search_direction == 1) 00437 ROM_NO[rom_byte_number] |= rom_byte_mask; 00438 else 00439 ROM_NO[rom_byte_number] &= ~rom_byte_mask; 00440 00441 // serial number search direction write bit 00442 write_bit(search_direction); 00443 00444 // increment the byte counter id_bit_number 00445 // and shift the mask rom_byte_mask 00446 id_bit_number++; 00447 rom_byte_mask <<= 1; 00448 00449 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask 00450 if (rom_byte_mask == 0) 00451 { 00452 rom_byte_number++; 00453 rom_byte_mask = 1; 00454 } 00455 } 00456 } 00457 while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 00458 00459 // if the search was successful then 00460 if (!(id_bit_number < 65)) 00461 { 00462 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result 00463 LastDiscrepancy = last_zero; 00464 00465 // check for last device 00466 if (LastDiscrepancy == 0) 00467 LastDeviceFlag = true; 00468 00469 search_result = true; 00470 } 00471 } 00472 00473 // if no device found then reset counters so next 'search' will be like a first 00474 if (!search_result || !ROM_NO[0]) 00475 { 00476 LastDiscrepancy = 0; 00477 LastDeviceFlag = false; 00478 LastFamilyDiscrepancy = 0; 00479 search_result = false; 00480 } 00481 for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; 00482 return search_result; 00483 } 00484 00485 #endif 00486 00487 #if ONEWIRE_CRC 00488 // The 1-Wire CRC scheme is described in Maxim Application Note 27: 00489 // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" 00490 // Compute a Dallas Semiconductor 8 bit CRC directly. 00491 // 00492 uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 00493 { 00494 uint8_t crc = 0; 00495 00496 while (len--) { 00497 uint8_t inbyte = *addr++; 00498 for (uint8_t i = 8; i; i--) { 00499 uint8_t mix = (crc ^ inbyte) & 0x01; 00500 crc >>= 1; 00501 if (mix) crc ^= 0x8C; 00502 inbyte >>= 1; 00503 } 00504 } 00505 return crc; 00506 } 00507 #endif
Generated on Fri Jul 15 2022 06:24:28 by
 1.7.2
 1.7.2 
    