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