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