Dallas' 1-Wire bus protocol library using mbed debug logs
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 1 if a device asserted a presence pulse, 0 otherwise. 00133 // 00134 uint8_t OneWire::reset(void) 00135 { 00136 uint8_t r; 00137 uint8_t retries = 125; 00138 00139 wire.input(); 00140 // wait until the wire is high... just in case 00141 do { 00142 if (--retries == 0) { 00143 return 0; 00144 } 00145 wait_us(2); 00146 } while (wire.read() != 1); 00147 00148 wire.output(); 00149 wire = 0; 00150 wait_us(480); 00151 wire.input(); 00152 wait_us(70); 00153 r = !wire.read(); 00154 wait_us(410); 00155 return r; 00156 } 00157 00158 // 00159 // Write a bit. Port and bit is used to cut lookup time and provide 00160 // more certain timing. 00161 // 00162 void OneWire::write_bit(uint8_t v) 00163 { 00164 wire.output(); 00165 if (v & 1) { 00166 wire = 0; // drive output low 00167 wait_us(10); 00168 wire = 1; // drive output high 00169 wait_us(55); 00170 } else { 00171 wire = 0; // drive output low 00172 wait_us(65); 00173 wire = 1; // drive output high 00174 wait_us(5); 00175 } 00176 } 00177 00178 // 00179 // Read a bit. Port and bit is used to cut lookup time and provide 00180 // more certain timing. 00181 // 00182 uint8_t OneWire::read_bit(void) 00183 { 00184 uint8_t r; 00185 00186 wire.output(); 00187 wire = 0; 00188 //wait_us(1); 00189 wire.input(); 00190 wait_us(5); 00191 r = wire.read(); 00192 wait_us(54); 00193 return r; 00194 } 00195 00196 // 00197 // Write a byte. The writing code uses the active drivers to raise the 00198 // pin high, if you need power after the write (e.g. DS18S20 in 00199 // parasite power mode) then set 'power' to 1, otherwise the pin will 00200 // go tri-state at the end of the write to avoid heating in a short or 00201 // other mishap. 00202 // 00203 void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { 00204 uint8_t bitMask; 00205 00206 for (bitMask = 0x01; bitMask; bitMask <<= 1) { 00207 OneWire::write_bit( (bitMask & v)?1:0); 00208 } 00209 if ( !power) { 00210 wire.input(); 00211 } 00212 } 00213 00214 void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { 00215 for (uint16_t i = 0 ; i < count ; i++) 00216 write(buf[i]); 00217 if (!power) { 00218 wire.input(); 00219 } 00220 } 00221 00222 // 00223 // Read a byte 00224 // 00225 uint8_t OneWire::read() { 00226 uint8_t bitMask; 00227 uint8_t r = 0; 00228 00229 for (bitMask = 0x01; bitMask; bitMask <<= 1) { 00230 if ( OneWire::read_bit()) r |= bitMask; 00231 } 00232 return r; 00233 } 00234 00235 void OneWire::read_bytes(uint8_t *buf, uint16_t count) { 00236 for (uint16_t i = 0 ; i < count ; i++) 00237 buf[i] = read(); 00238 } 00239 00240 // 00241 // Do a ROM select 00242 // 00243 void OneWire::select(const uint8_t rom[8]) 00244 { 00245 uint8_t i; 00246 00247 write(0x55); // Choose ROM 00248 00249 for (i = 0; i < 8; i++) write(rom[i]); 00250 } 00251 00252 // 00253 // Do a ROM skip 00254 // 00255 void OneWire::skip() 00256 { 00257 write(0xCC); // Skip ROM 00258 } 00259 00260 void OneWire::depower() 00261 { 00262 wire.input(); 00263 } 00264 00265 #if ONEWIRE_SEARCH 00266 00267 // 00268 // You need to use this function to start a search again from the beginning. 00269 // You do not need to do it for the first search, though you could. 00270 // 00271 void OneWire::reset_search() 00272 { 00273 // reset the search state 00274 LastDiscrepancy = 0; 00275 LastDeviceFlag = false; 00276 LastFamilyDiscrepancy = 0; 00277 for(int i = 7; ; i--) { 00278 ROM_NO[i] = 0; 00279 if ( i == 0) break; 00280 } 00281 } 00282 00283 // Setup the search to find the device type 'family_code' on the next call 00284 // to search(*newAddr) if it is present. 00285 // 00286 void OneWire::target_search(uint8_t family_code) 00287 { 00288 // set the search state to find SearchFamily type devices 00289 ROM_NO[0] = family_code; 00290 for (uint8_t i = 1; i < 8; i++) 00291 ROM_NO[i] = 0; 00292 LastDiscrepancy = 64; 00293 LastFamilyDiscrepancy = 0; 00294 LastDeviceFlag = false; 00295 } 00296 00297 // 00298 // Perform a search. If this function returns a '1' then it has 00299 // enumerated the next device and you may retrieve the ROM from the 00300 // OneWire::address variable. If there are no devices, no further 00301 // devices, or something horrible happens in the middle of the 00302 // enumeration then a 0 is returned. If a new device is found then 00303 // its address is copied to newAddr. Use OneWire::reset_search() to 00304 // start over. 00305 // 00306 // --- Replaced by the one from the Dallas Semiconductor web site --- 00307 //-------------------------------------------------------------------------- 00308 // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing 00309 // search state. 00310 // Return true : device found, ROM number in ROM_NO buffer 00311 // false : device not found, end of search 00312 // 00313 uint8_t OneWire::search(uint8_t *newAddr) 00314 { 00315 uint8_t id_bit_number; 00316 uint8_t last_zero, rom_byte_number, search_result; 00317 uint8_t id_bit, cmp_id_bit; 00318 00319 unsigned char rom_byte_mask, search_direction; 00320 00321 // initialize for search 00322 id_bit_number = 1; 00323 last_zero = 0; 00324 rom_byte_number = 0; 00325 rom_byte_mask = 1; 00326 search_result = 0; 00327 00328 // if the last call was not the last one 00329 if (!LastDeviceFlag) 00330 { 00331 // 1-Wire reset 00332 if (!reset()) 00333 { 00334 // reset the search 00335 LastDiscrepancy = 0; 00336 LastDeviceFlag = false; 00337 LastFamilyDiscrepancy = 0; 00338 return false; 00339 } 00340 00341 // issue the search command 00342 write(0xF0); 00343 00344 // loop to do the search 00345 do 00346 { 00347 // read a bit and its complement 00348 id_bit = read_bit(); 00349 cmp_id_bit = read_bit(); 00350 00351 // check for no devices on 1-wire 00352 if ((id_bit == 1) && (cmp_id_bit == 1)) 00353 break; 00354 else 00355 { 00356 // all devices coupled have 0 or 1 00357 if (id_bit != cmp_id_bit) 00358 search_direction = id_bit; // bit write value for search 00359 else 00360 { 00361 // if this discrepancy if before the Last Discrepancy 00362 // on a previous next then pick the same as last time 00363 if (id_bit_number < LastDiscrepancy) 00364 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); 00365 else 00366 // if equal to last pick 1, if not then pick 0 00367 search_direction = (id_bit_number == LastDiscrepancy); 00368 00369 // if 0 was picked then record its position in LastZero 00370 if (search_direction == 0) 00371 { 00372 last_zero = id_bit_number; 00373 00374 // check for Last discrepancy in family 00375 if (last_zero < 9) 00376 LastFamilyDiscrepancy = last_zero; 00377 } 00378 } 00379 00380 // set or clear the bit in the ROM byte rom_byte_number 00381 // with mask rom_byte_mask 00382 if (search_direction == 1) 00383 ROM_NO[rom_byte_number] |= rom_byte_mask; 00384 else 00385 ROM_NO[rom_byte_number] &= ~rom_byte_mask; 00386 00387 // serial number search direction write bit 00388 write_bit(search_direction); 00389 00390 // increment the byte counter id_bit_number 00391 // and shift the mask rom_byte_mask 00392 id_bit_number++; 00393 rom_byte_mask <<= 1; 00394 00395 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask 00396 if (rom_byte_mask == 0) 00397 { 00398 rom_byte_number++; 00399 rom_byte_mask = 1; 00400 } 00401 } 00402 } 00403 while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 00404 00405 // if the search was successful then 00406 if (!(id_bit_number < 65)) 00407 { 00408 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result 00409 LastDiscrepancy = last_zero; 00410 00411 // check for last device 00412 if (LastDiscrepancy == 0) 00413 LastDeviceFlag = true; 00414 00415 search_result = true; 00416 } 00417 } 00418 00419 // if no device found then reset counters so next 'search' will be like a first 00420 if (!search_result || !ROM_NO[0]) 00421 { 00422 LastDiscrepancy = 0; 00423 LastDeviceFlag = false; 00424 LastFamilyDiscrepancy = 0; 00425 search_result = false; 00426 } 00427 for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; 00428 return search_result; 00429 } 00430 00431 #endif 00432 00433 #if ONEWIRE_CRC 00434 // The 1-Wire CRC scheme is described in Maxim Application Note 27: 00435 // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" 00436 // Compute a Dallas Semiconductor 8 bit CRC directly. 00437 // 00438 uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 00439 { 00440 uint8_t crc = 0; 00441 00442 while (len--) { 00443 uint8_t inbyte = *addr++; 00444 for (uint8_t i = 8; i; i--) { 00445 uint8_t mix = (crc ^ inbyte) & 0x01; 00446 crc >>= 1; 00447 if (mix) crc ^= 0x8C; 00448 inbyte >>= 1; 00449 } 00450 } 00451 return crc; 00452 } 00453 #endif
Generated on Sat Jul 16 2022 12:50:38 by 1.7.2