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