Library to communicate with Maxim OneWire protocol devices Modified timings and IRQ overrides
Fork of Onewire by
Onewire.cpp
00001 // Code derived from a number of sources including: 00002 // simonbarker on MBED 00003 // The search code is a port of Jim Studt's Adruino One Wire lib 00004 // Can handle multiple devices per pin 00005 // Rob Dobson, 2015 00006 00007 #include "Onewire.h" 00008 00009 Onewire::Onewire(PinName oneBus):oneBus_(oneBus) 00010 { 00011 } 00012 00013 void Onewire::writeBit(int bit) 00014 { 00015 __disable_irq(); 00016 bit = bit & 0x01; 00017 if (bit) 00018 { 00019 // Write '1' bit 00020 __disable_irq(); 00021 oneBus_.output(); 00022 oneBus_ = 0; 00023 wait_us(10); 00024 oneBus_ = 1; 00025 __enable_irq(); 00026 wait_us(55); 00027 } 00028 else 00029 { 00030 // Write '0' bit 00031 __disable_irq(); 00032 oneBus_.output(); 00033 oneBus_ = 0; 00034 wait_us(65); 00035 oneBus_ = 1; 00036 __enable_irq(); 00037 wait_us(5); 00038 } 00039 __enable_irq(); 00040 } 00041 00042 int Onewire::readBit() 00043 { 00044 char result; 00045 00046 __disable_irq(); 00047 oneBus_.output(); 00048 oneBus_ = 0; 00049 wait_us(3); 00050 oneBus_.input(); 00051 wait_us(10); 00052 result = oneBus_.read(); 00053 __enable_irq(); 00054 wait_us(53); 00055 return result; 00056 } 00057 00058 int Onewire::init() 00059 { 00060 // Ensure bus is high to start 00061 oneBus_.input(); 00062 int MAX_RETRY_TEST_BUS_HIGH = 125; 00063 for (int i = 0; i < MAX_RETRY_TEST_BUS_HIGH; i++) 00064 { 00065 if (oneBus_.read() == 1) 00066 break; 00067 wait_us(2); 00068 } 00069 if (oneBus_.read() != 1) 00070 return ONEWIRE_FAIL_STUCK_LOW; 00071 00072 // Pull LOW for 480us 00073 __disable_irq(); 00074 oneBus_.output(); 00075 oneBus_ = 0; 00076 __enable_irq(); 00077 wait_us(480); 00078 00079 // Allow to float and test to ensure presence of devices 00080 // (which pull the bus low) 00081 __disable_irq(); 00082 oneBus_.input(); 00083 wait_us(70); 00084 int readVal = oneBus_.read(); 00085 __enable_irq(); 00086 wait_us(410); 00087 return (readVal == 0) ? ONEWIRE_OK : ONEWIRE_SEARCH_INIT_FAIL; 00088 } 00089 00090 int Onewire::readByte() 00091 { 00092 int result = 0; 00093 00094 for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { 00095 // shift the result to get it ready for the next bit 00096 result >>= 1; 00097 00098 // if result is one, then set MS bit 00099 if (readBit()) 00100 result |= 0x80; 00101 } 00102 return result; 00103 } 00104 00105 void Onewire::writeByte(char data) 00106 { 00107 // Loop to write each bit in the byte, LS-bit first 00108 for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { 00109 writeBit(data & 0x01); 00110 00111 // shift the data byte for the next bit 00112 data >>= 1; 00113 } 00114 } 00115 00116 unsigned char Onewire::CRC(unsigned char* addr, unsigned char len) 00117 { 00118 unsigned char i, j; 00119 unsigned char crc = 0; 00120 00121 for (i = 0; i < len; i++) { 00122 unsigned char inbyte = addr[i]; 00123 for (j = 0; j < ONEWIRE_ADDR_BYTES; j++) { 00124 unsigned char mix = (crc ^ inbyte) & 0x01; 00125 crc >>= 1; 00126 if (mix) crc ^= 0x8C; 00127 inbyte >>= 1; 00128 } 00129 } 00130 return crc; 00131 } 00132 00133 // 00134 // You need to use this function to start a search again from the beginning. 00135 // You do not need to do it for the first search, though you could. 00136 // 00137 void Onewire::reset_search() 00138 { 00139 // reset the search state 00140 _search_LastDiscrepancy = 0; 00141 _search_LastDeviceFlag = false; 00142 _search_LastFamilyDiscrepancy = 0; 00143 for(int i = ONEWIRE_ADDR_BYTES-1; i >= 0; i--) 00144 _search_ROM_NO[i] = 0; 00145 } 00146 00147 // Search Based on Maxim DS18B20 Algorithm 00148 // https://www.maximintegrated.com/en/app-notes/index.mvp/id/187 00149 // 00150 // Perform a search, returns: 00151 // ONEWIRE_OK if a new address has been returned. 00152 // ONEWIRE_SEARCH_ALL_DONE = all devices found 00153 // ONEWIRE_SEARCH_INIT_FAIL = failed to init 00154 // ONEWIRE_SEARCH_NOT_FOUND = no devices found If this function returns a '1' then it has 00155 // ONEWIRE_SEARCH_STUCK_HIGH = bus is stuck high 00156 // ONEWIRE_SEARCH_COMP_BIT_ERR = complement bit error 00157 // 00158 uint8_t Onewire::search(uint8_t *newAddr) 00159 { 00160 // initialize for search 00161 uint8_t last_zero = 0; 00162 unsigned char search_direction = 0; 00163 00164 // if the previous call was the last one 00165 if (_search_LastDeviceFlag) 00166 return ONEWIRE_SEARCH_ALL_DONE; 00167 00168 // 1-Wire reset 00169 int initRslt = init(); 00170 if (initRslt != ONEWIRE_OK) 00171 { 00172 // reset the search 00173 reset_search(); 00174 return initRslt; 00175 } 00176 00177 // issue the search command 00178 writeByte(0xF0); 00179 00180 // loop to do the search 00181 for (int id_bit_number = 1; id_bit_number <= 64; id_bit_number++) 00182 { 00183 // read a bit and its complement 00184 uint8_t id_bit = readBit(); 00185 uint8_t cmp_id_bit = readBit(); 00186 00187 // check for no devices on 1-wire 00188 if ((id_bit == 1) && (cmp_id_bit == 1)) 00189 { 00190 reset_search(); 00191 return ONEWIRE_SEARCH_COMP_BIT_ERR; 00192 } 00193 00194 // all devices coupled have 0 or 1 00195 int byteNo = (id_bit_number - 1) / 8; 00196 int byteMask = 1 << ((id_bit_number - 1) % 8); 00197 if (id_bit != cmp_id_bit) 00198 { 00199 search_direction = id_bit; // bit write value for search 00200 } 00201 else 00202 { 00203 if (id_bit_number == _search_LastDiscrepancy) 00204 { 00205 search_direction = 1; 00206 } 00207 else if (id_bit_number > _search_LastDiscrepancy) 00208 { 00209 search_direction = 0; 00210 } 00211 else 00212 { 00213 search_direction = ((_search_ROM_NO[byteNo] & byteMask) > 0); 00214 } 00215 00216 // if 0 was picked then record its position in LastZero 00217 if (search_direction == 0) 00218 { 00219 last_zero = id_bit_number; 00220 // check for Last discrepancy in family 00221 if (last_zero < 9) 00222 _search_LastFamilyDiscrepancy = last_zero; 00223 } 00224 } 00225 00226 // set or clear the bit in the ROM byte rom_byte_number 00227 // with mask rom_byte_mask 00228 00229 if (search_direction == 1) 00230 _search_ROM_NO[byteNo] |= byteMask; 00231 else 00232 _search_ROM_NO[byteNo] &= ~byteMask; 00233 00234 // serial number search direction write bit 00235 writeBit(search_direction); 00236 } 00237 00238 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result 00239 _search_LastDiscrepancy = last_zero; 00240 // check for last device 00241 if (_search_LastDiscrepancy == 0) 00242 _search_LastDeviceFlag = true; 00243 00244 // Copy address to return 00245 for (int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 00246 newAddr[i] = _search_ROM_NO[i]; 00247 00248 return ONEWIRE_OK; 00249 } 00250 00251 char* Onewire::GetErrorStr(int errCode) 00252 { 00253 switch(errCode) 00254 { 00255 case ONEWIRE_OK: return "OK"; 00256 case ONEWIRE_FAIL_STUCK_LOW: return "Stuck Low"; 00257 case ONEWIRE_SEARCH_ALL_DONE: return "All Done"; 00258 case ONEWIRE_SEARCH_INIT_FAIL: return "Init Fail"; 00259 case ONEWIRE_SEARCH_NOT_FOUND: return "Not Found"; 00260 case ONEWIRE_SEARCH_COMP_BIT_ERR: return "Comp Bit Err"; 00261 } 00262 return "Unknown Err"; 00263 } 00264
Generated on Tue Jul 12 2022 21:42:30 by
1.7.2
