Yet another DS1820 lib, but this one is make in sweat of struggling with other ones. It's a fork really of <insert original as mbed doesn't track idk why> with *added capability* of not blocking.
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