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.
DS1820.cpp
00001 #include "DS1820.h" 00002 #include "mbed.h" 00003 00004 // Global variables shared between all DS1820 objects 00005 bool DS1820_done_flag; 00006 int DS1820_last_descrepancy; 00007 char DS1820_search_ROM[8]; 00008 00009 00010 DS1820::DS1820 (PinName data_pin, PinName power_pin) : _datapin(data_pin), _parasitepin(power_pin) 00011 { 00012 int byte_counter; 00013 00014 _last_temperature = NULL; 00015 _parasite_power = true; 00016 for(byte_counter=0; byte_counter<8; byte_counter++) 00017 ROM[byte_counter] = 0xFF; 00018 for(byte_counter=0; byte_counter<9; byte_counter++) 00019 RAM[byte_counter] = 0x00; 00020 } 00021 DS1820::DS1820 (PinName data_pin) : _datapin(data_pin), _parasitepin(NC) 00022 { 00023 int byte_counter; 00024 00025 _last_temperature = NULL; 00026 _parasite_power = false; 00027 for(byte_counter=0; byte_counter<8; byte_counter++) 00028 ROM[byte_counter] = 0xFF; 00029 for(byte_counter=0; byte_counter<9; byte_counter++) 00030 RAM[byte_counter] = 0x00; 00031 } 00032 00033 void DS1820::_auto_convert_temperature() 00034 { 00035 convert_temperature(false, DS1820::this_device); 00036 } 00037 00038 void DS1820::enable_auto_convert(float interval) 00039 { 00040 _autoConvert.attach(this, &DS1820::_auto_convert_temperature, interval); 00041 } 00042 00043 bool DS1820::onewire_reset() 00044 { 00045 // This will return false if no devices are present on the data bus 00046 bool presence=false; 00047 _datapin.output(); 00048 _datapin.mode(PullUp); 00049 _datapin = 0; // bring low for 500 us 00050 wait_us(500); 00051 _datapin.input(); // let the data line float high 00052 _datapin.mode(PullUp); 00053 wait_us(90); // wait 90us 00054 if (_datapin.read()==0) // see if any devices are pulling the data line low 00055 presence=true; 00056 wait_us(410); 00057 return presence; 00058 } 00059 00060 void DS1820::onewire_bit_out (bool bit_data) 00061 { 00062 _datapin.output(); 00063 _datapin = 0; 00064 wait_us(5); 00065 if (bit_data) { 00066 _datapin.input(); // bring data line high 00067 _datapin.mode(PullUp); 00068 wait_us(55); 00069 } else { 00070 wait_us(55); // keep data line low 00071 _datapin.input(); 00072 _datapin.mode(PullUp); 00073 } 00074 } 00075 00076 void DS1820::onewire_byte_out(char data) // output data character (least sig bit first). 00077 { 00078 int n; 00079 for (n=0; n<8; n++) { 00080 onewire_bit_out(data & 0x01); 00081 data = data >> 1; // now the next bit is in the least sig bit position. 00082 } 00083 } 00084 00085 bool DS1820::onewire_bit_in() 00086 { 00087 bool answer; 00088 _datapin.output(); 00089 _datapin = 0; 00090 wait_us(5); 00091 _datapin.input(); 00092 _datapin.mode(PullUp); 00093 wait_us(5); 00094 answer = _datapin.read(); 00095 wait_us(50); 00096 return answer; 00097 } 00098 00099 char DS1820::onewire_byte_in() // read byte, least sig byte first 00100 { 00101 char answer = 0x00; 00102 int i; 00103 for (i=0; i<8; i++) { 00104 answer = answer >> 1; // shift over to make room for the next bit 00105 if (onewire_bit_in()) 00106 answer = answer | 0x80; // if the data port is high, make this bit a 1 00107 } 00108 return answer; 00109 } 00110 00111 bool DS1820::search_ROM() 00112 { 00113 return search_ROM_routine(0xF0); // Search ROM command 00114 } 00115 00116 bool DS1820::search_alarm() 00117 { 00118 return search_ROM_routine(0xEC); // Search Alarm command 00119 } 00120 00121 bool DS1820::search_ROM_routine(char command) 00122 { 00123 extern bool DS1820_done_flag; 00124 extern int DS1820_last_descrepancy; 00125 extern char DS1820_search_ROM[8]; 00126 int descrepancy_marker, ROM_bit_index; 00127 bool return_value, Bit_A, Bit_B; 00128 char byte_counter, bit_mask; 00129 00130 return_value=false; 00131 if (!DS1820_done_flag) { 00132 if (!onewire_reset()) { 00133 DS1820_last_descrepancy = 0; // no devices present 00134 } else { 00135 ROM_bit_index=1; 00136 descrepancy_marker=0; 00137 onewire_byte_out(command); // Search ROM command or Search Alarm command 00138 byte_counter = 0; 00139 bit_mask = 0x01; 00140 while (ROM_bit_index<=64) { 00141 Bit_A = onewire_bit_in(); 00142 Bit_B = onewire_bit_in(); 00143 if (Bit_A & Bit_B) { 00144 descrepancy_marker = 0; // data read error, this should never happen 00145 ROM_bit_index = 0xFF; 00146 } else { 00147 if (Bit_A | Bit_B) { 00148 // Set ROM bit to Bit_A 00149 if (Bit_A) { 00150 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one 00151 } else { 00152 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero 00153 } 00154 } else { 00155 // both bits A and B are low, so there are two or more devices present 00156 if ( ROM_bit_index == DS1820_last_descrepancy ) { 00157 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one 00158 } else { 00159 if ( ROM_bit_index > DS1820_last_descrepancy ) { 00160 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero 00161 descrepancy_marker = ROM_bit_index; 00162 } else { 00163 if (( DS1820_search_ROM[byte_counter] & bit_mask) == 0x00 ) 00164 descrepancy_marker = ROM_bit_index; 00165 } 00166 } 00167 } 00168 onewire_bit_out (DS1820_search_ROM[byte_counter] & bit_mask); 00169 ROM_bit_index++; 00170 if (bit_mask & 0x80) { 00171 byte_counter++; 00172 bit_mask = 0x01; 00173 } else { 00174 bit_mask = bit_mask << 1; 00175 } 00176 } 00177 } 00178 DS1820_last_descrepancy = descrepancy_marker; 00179 if (ROM_bit_index != 0xFF) { 00180 for(byte_counter=0; byte_counter<8; byte_counter++) 00181 ROM[byte_counter] = DS1820_search_ROM[byte_counter]; 00182 return_value = true; 00183 } 00184 } 00185 if (DS1820_last_descrepancy == 0) 00186 DS1820_done_flag = true; 00187 } 00188 return return_value; 00189 } 00190 00191 void DS1820::search_ROM_setup() 00192 { 00193 extern bool DS1820_done_flag; 00194 extern int DS1820_last_descrepancy; 00195 extern char DS1820_search_ROM[8]; 00196 DS1820_done_flag = false; 00197 DS1820_last_descrepancy = 0; 00198 int i; 00199 for (i=0; i<8; i++) 00200 DS1820_search_ROM[i]=0x00; 00201 } 00202 00203 void DS1820::read_ROM() 00204 { 00205 // NOTE: This command can only be used when there is one DS1820 on the bus. If this command 00206 // is used when there is more than one slave present on the bus, a data collision will occur 00207 // when all the DS1820s attempt to respond at the same time. 00208 int i; 00209 onewire_reset(); 00210 onewire_byte_out(0x33); // Read ROM id 00211 for (i=0; i<8; i++) 00212 ROM[i]=onewire_byte_in(); 00213 } 00214 00215 void DS1820::match_ROM() 00216 { 00217 // Used to select a specific device 00218 int i; 00219 onewire_reset(); 00220 onewire_byte_out( 0x55); //Match ROM command 00221 for (i=0; i<8; i++) 00222 onewire_byte_out(ROM[i]); 00223 } 00224 00225 void DS1820::skip_ROM() 00226 { 00227 onewire_reset(); 00228 onewire_byte_out(0xCC); // Skip ROM command 00229 } 00230 00231 bool DS1820::ROM_checksum_error() 00232 { 00233 char xCRC=0x00; 00234 int i; 00235 for(i=0; i<7; i++) // Only going to shift the lower 7 bytes 00236 xCRC = CRC_byte(xCRC, ROM[i]); 00237 // After 7 bytes CRC should equal the 8th byte (ROM CRC) 00238 return (xCRC!=ROM[7]); // will return true if there is a CRC checksum error 00239 } 00240 00241 bool DS1820::RAM_checksum_error() 00242 { 00243 char xCRC=0x00; 00244 int i; 00245 read_RAM(); 00246 for(i=0; i<8; i++) // Only going to shift the lower 8 bytes 00247 xCRC = CRC_byte(xCRC, RAM[i]); 00248 // After 8 bytes CRC should equal the 9th byte (RAM CRC) 00249 return (xCRC!=RAM[8]); // will return true if there is a CRC checksum error 00250 } 00251 00252 char DS1820::CRC_byte (char xCRC, char byte ) 00253 { 00254 int j; 00255 for(j=0; j<8; j++) { 00256 if ((byte & 0x01 ) ^ (xCRC & 0x01)) { 00257 // DATA ^ LSB CRC = 1 00258 xCRC = xCRC>>1; 00259 // Set the MSB to 1 00260 xCRC = xCRC | 0x80; 00261 // Check bit 3 00262 if (xCRC & 0x04) { 00263 xCRC = xCRC & 0xFB; // Bit 3 is set, so clear it 00264 } else { 00265 xCRC = xCRC | 0x04; // Bit 3 is clear, so set it 00266 } 00267 // Check bit 4 00268 if (xCRC & 0x08) { 00269 xCRC = xCRC & 0xF7; // Bit 4 is set, so clear it 00270 } else { 00271 xCRC = xCRC | 0x08; // Bit 4 is clear, so set it 00272 } 00273 } else { 00274 // DATA ^ LSB xCRC = 0 00275 xCRC = xCRC>>1; 00276 // clear MSB 00277 xCRC = xCRC & 0x7F; 00278 // No need to check bits, with DATA ^ LSB xCRC = 0, they will remain unchanged 00279 } 00280 byte = byte>>1; 00281 } 00282 return xCRC; 00283 } 00284 00285 void DS1820::convert_temperature(bool blocking, devices device) 00286 { 00287 // Convert temperature into scratchpad RAM for all devices at once 00288 int delay_time = 750; // Default delay time (for 12 bits) 00289 char resolution; 00290 if (device==all_devices) 00291 skip_ROM(); // Skip ROM command, will convert for ALL devices 00292 else { 00293 match_ROM(); 00294 if (FAMILY_CODE == FAMILY_CODE_DS18B20 ) { 00295 resolution = RAM[4] & 0x60; 00296 if (resolution == 0x00) // 9 bits 00297 delay_time = 94; 00298 if (resolution == 0x20) // 10 bits 00299 delay_time = 188; 00300 if (resolution == 0x40) // 11 bits. Note 12bits uses the 750ms default 00301 delay_time = 375; 00302 } 00303 } 00304 onewire_byte_out( 0x44); // perform temperature conversion 00305 if (_parasite_power) 00306 _parasitepin = 1; // Parasite power strong pullup 00307 if (blocking) { // blocking 00308 wait_ms(delay_time); 00309 _temperature_raw(); 00310 } else { // non-blocking 00311 float timeout_time = ((float)delay_time)/1000.0; 00312 auto_get_new_temperature.attach(callback(this, &DS1820::_temperature_raw), timeout_time); // update _last_temperture automagically 00313 } 00314 if (_parasite_power) 00315 _parasitepin = 0; 00316 } 00317 00318 void DS1820::read_RAM() 00319 { 00320 // This will copy the DS1820's 9 bytes of RAM data 00321 // into the objects RAM array. Functions that use 00322 // RAM values will automaticly call this procedure. 00323 int i; 00324 match_ROM(); // Select this device 00325 onewire_byte_out( 0xBE); //Read Scratchpad command 00326 for(i=0; i<9; i++) { 00327 RAM[i] = onewire_byte_in(); 00328 } 00329 } 00330 00331 bool DS1820::set_configuration_bits(unsigned int resolution, devices device) 00332 { 00333 bool answer = false; 00334 resolution = resolution - 9; 00335 if (resolution < 4) { 00336 if (device==all_devices) 00337 skip_ROM(); 00338 else 00339 match_ROM(); 00340 resolution = resolution<<5; // align the bits 00341 RAM[4] = (RAM[4] & 0b00011111) | resolution; // mask out old data, insert new 00342 write_scratchpad ((RAM[2]<<8) + RAM[3]); 00343 // store_scratchpad (DS1820::this_device); // Need to test if this is required 00344 answer = true; 00345 } 00346 return answer; 00347 } 00348 00349 int DS1820::read_scratchpad() 00350 { 00351 int answer; 00352 read_RAM(); 00353 answer = (RAM[2]<<8) + RAM[3]; 00354 return answer; 00355 } 00356 00357 void DS1820::write_scratchpad(int data) 00358 { 00359 RAM[3] = data; 00360 RAM[2] = data>>8; 00361 match_ROM(); 00362 onewire_byte_out(0x4E); // Copy scratchpad into DS1820 ram memory 00363 onewire_byte_out(RAM[2]); // T(H) 00364 onewire_byte_out(RAM[3]); // T(L) 00365 if ( FAMILY_CODE == FAMILY_CODE_DS18B20 ) { 00366 onewire_byte_out(RAM[4]); // Configuration register 00367 } 00368 } 00369 00370 void DS1820::store_scratchpad(devices device) 00371 { 00372 if (device==all_devices) 00373 skip_ROM(); // Skip ROM command, will store for ALL devices 00374 else 00375 match_ROM(); 00376 onewire_byte_out(0x48); // Write scratchpad into E2 command 00377 if (_parasite_power) 00378 _parasitepin=1; 00379 wait_ms(10); // Parasite power strong pullup for 10ms 00380 if (_parasite_power) 00381 _parasitepin=0; 00382 } 00383 00384 int DS1820::recall_scratchpad(devices device) 00385 { 00386 // This copies the E2 values into the DS1820's memory. 00387 // If you specify all_devices this will return zero, otherwise 00388 // it will return the value of the scratchpad memory. 00389 int answer=0; 00390 if (device==all_devices) 00391 skip_ROM(); // Skip ROM command, will recall for ALL devices 00392 else 00393 match_ROM(); 00394 onewire_byte_out(0xB8); // Recall E2 data to scratchpad command 00395 wait_ms(10); // not sure I like polling for completion 00396 // it could cause an infinite loop 00397 if (device==DS1820::this_device) { 00398 read_RAM(); 00399 answer = read_scratchpad(); 00400 } 00401 return answer; 00402 } 00403 void DS1820::_temperature_raw() 00404 { 00405 float answer, remaining_count, count_per_degree; 00406 int reading; 00407 read_RAM(); 00408 reading = (RAM[1] << 8) + RAM[0]; 00409 if (reading & 0x8000) { // negative degrees C 00410 reading = 0-((reading ^ 0xffff) + 1); // 2's comp then convert to signed int 00411 } 00412 answer = reading +0.0; // convert to floating point 00413 if ( FAMILY_CODE == FAMILY_CODE_DS18B20 ) { 00414 answer = answer / 8.0; 00415 } else { 00416 remaining_count = RAM[6]; 00417 count_per_degree = RAM[7]; 00418 answer = answer - 0.25 + (count_per_degree - remaining_count) / count_per_degree; 00419 } 00420 _last_temperature = answer; 00421 } 00422 00423 float DS1820::temperature(char scale) 00424 { 00425 // The data specs state that count_per_degree should be 0x10 (16), I found my devices 00426 // to have a count_per_degree of 0x4B (75). With the standard resolution of 1/2 deg C 00427 // this allowed an expanded resolution of 1/150th of a deg C. I wouldn't rely on this 00428 // being super acurate, but it does allow for a smooth display in the 1/10ths of a 00429 // deg C or F scales. 00430 if (_last_temperature == NULL) { 00431 convert_temperature(true); 00432 } 00433 float answer = _last_temperature; 00434 if (scale=='C' or scale=='c') 00435 answer = answer / 2.0; 00436 else 00437 // Convert to deg F 00438 answer = answer * 9.0 / 10.0 + 32.0; 00439 return answer; 00440 } 00441 00442 bool DS1820::read_power_supply(devices device) 00443 { 00444 // This will return true if the device (or all devices) are Vcc powered 00445 // This will return false if the device (or ANY device) is parasite powered 00446 if (device==all_devices) 00447 skip_ROM(); // Skip ROM command, will poll for any device using parasite power 00448 else 00449 match_ROM(); 00450 onewire_byte_out(0xB4); // Read power supply command 00451 return onewire_bit_in(); 00452 }
Generated on Sat Jul 16 2022 06:07:07 by
1.7.2