Library to communicate with Maxim OneWire protocol devices Modified timings and IRQ overrides
Fork of Onewire by
Onewire.cpp@7:0a87f8c2d9e6, 2015-10-15 (annotated)
- Committer:
- Bobty
- Date:
- Thu Oct 15 21:39:21 2015 +0000
- Revision:
- 7:0a87f8c2d9e6
- Parent:
- 6:d2452e9b169b
- Child:
- 8:5d0bd95b586f
Added delay after bus reset to comply with Maxim search algorithm; Tidied up search algorithm
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bobty | 3:712bf8967b68 | 1 | // Code derived from a number of sources including: |
Bobty | 3:712bf8967b68 | 2 | // simonbarker on MBED |
Bobty | 3:712bf8967b68 | 3 | // The search code is a port of Jim Studt's Adruino One Wire lib |
Bobty | 3:712bf8967b68 | 4 | // Can handle multiple devices per pin |
Bobty | 3:712bf8967b68 | 5 | // Rob Dobson, 2015 |
Bobty | 3:712bf8967b68 | 6 | |
simonbarker | 0:d961f715d82b | 7 | #include "Onewire.h" |
simonbarker | 0:d961f715d82b | 8 | |
Bobty | 2:b7ee49dbd7ef | 9 | Onewire::Onewire(PinName oneBus):oneBus_(oneBus) |
Bobty | 2:b7ee49dbd7ef | 10 | { |
simonbarker | 0:d961f715d82b | 11 | } |
Bobty | 2:b7ee49dbd7ef | 12 | |
Bobty | 2:b7ee49dbd7ef | 13 | void Onewire::writeBit(int bit) |
Bobty | 2:b7ee49dbd7ef | 14 | { |
Bobty | 5:45b6a39002f1 | 15 | __disable_irq(); |
simonbarker | 0:d961f715d82b | 16 | bit = bit & 0x01; |
Bobty | 2:b7ee49dbd7ef | 17 | if (bit) |
Bobty | 2:b7ee49dbd7ef | 18 | { |
simonbarker | 0:d961f715d82b | 19 | // Write '1' bit |
simonbarker | 0:d961f715d82b | 20 | oneBus_.output(); |
simonbarker | 0:d961f715d82b | 21 | oneBus_ = 0; |
Bobty | 5:45b6a39002f1 | 22 | wait_us(12); |
simonbarker | 0:d961f715d82b | 23 | oneBus_.input(); |
simonbarker | 0:d961f715d82b | 24 | wait_us(60); |
Bobty | 2:b7ee49dbd7ef | 25 | } |
Bobty | 2:b7ee49dbd7ef | 26 | else |
Bobty | 2:b7ee49dbd7ef | 27 | { |
simonbarker | 0:d961f715d82b | 28 | // Write '0' bit |
simonbarker | 0:d961f715d82b | 29 | oneBus_.output(); |
simonbarker | 0:d961f715d82b | 30 | oneBus_ = 0; |
Bobty | 5:45b6a39002f1 | 31 | wait_us(60); |
simonbarker | 0:d961f715d82b | 32 | oneBus_.input(); |
Bobty | 5:45b6a39002f1 | 33 | wait_us(12); |
simonbarker | 0:d961f715d82b | 34 | } |
Bobty | 5:45b6a39002f1 | 35 | __enable_irq(); |
simonbarker | 0:d961f715d82b | 36 | } |
simonbarker | 0:d961f715d82b | 37 | |
Bobty | 2:b7ee49dbd7ef | 38 | int Onewire::readBit() |
Bobty | 2:b7ee49dbd7ef | 39 | { |
simonbarker | 0:d961f715d82b | 40 | char result; |
simonbarker | 0:d961f715d82b | 41 | |
Bobty | 5:45b6a39002f1 | 42 | __disable_irq(); |
simonbarker | 0:d961f715d82b | 43 | oneBus_.output(); |
simonbarker | 0:d961f715d82b | 44 | oneBus_ = 0; |
Bobty | 5:45b6a39002f1 | 45 | wait_us(5); |
simonbarker | 0:d961f715d82b | 46 | oneBus_.input(); |
Bobty | 5:45b6a39002f1 | 47 | wait_us(7); |
simonbarker | 0:d961f715d82b | 48 | result = oneBus_.read(); |
Bobty | 5:45b6a39002f1 | 49 | wait_us(60); |
Bobty | 5:45b6a39002f1 | 50 | __enable_irq(); |
simonbarker | 0:d961f715d82b | 51 | return result; |
simonbarker | 0:d961f715d82b | 52 | } |
simonbarker | 0:d961f715d82b | 53 | |
Bobty | 2:b7ee49dbd7ef | 54 | int Onewire::init() |
Bobty | 2:b7ee49dbd7ef | 55 | { |
simonbarker | 0:d961f715d82b | 56 | oneBus_.output(); |
simonbarker | 0:d961f715d82b | 57 | oneBus_ = 0; |
simonbarker | 0:d961f715d82b | 58 | wait_us(480); |
Bobty | 5:45b6a39002f1 | 59 | __disable_irq(); |
simonbarker | 0:d961f715d82b | 60 | oneBus_.input(); |
simonbarker | 0:d961f715d82b | 61 | wait_us(60); |
Bobty | 2:b7ee49dbd7ef | 62 | if (oneBus_.read() == 0) |
Bobty | 2:b7ee49dbd7ef | 63 | { |
Bobty | 5:45b6a39002f1 | 64 | __enable_irq(); |
Bobty | 5:45b6a39002f1 | 65 | wait_us(100); |
Bobty | 7:0a87f8c2d9e6 | 66 | return ONEWIRE_OK; |
simonbarker | 0:d961f715d82b | 67 | } |
Bobty | 5:45b6a39002f1 | 68 | __enable_irq(); |
Bobty | 7:0a87f8c2d9e6 | 69 | return ONEWIRE_SEARCH_INIT_FAIL; |
simonbarker | 0:d961f715d82b | 70 | } |
Bobty | 2:b7ee49dbd7ef | 71 | |
Bobty | 2:b7ee49dbd7ef | 72 | int Onewire::readByte() |
Bobty | 2:b7ee49dbd7ef | 73 | { |
simonbarker | 0:d961f715d82b | 74 | int result = 0; |
simonbarker | 0:d961f715d82b | 75 | |
Bobty | 4:b678c7c8203c | 76 | for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { |
simonbarker | 0:d961f715d82b | 77 | // shift the result to get it ready for the next bit |
simonbarker | 0:d961f715d82b | 78 | result >>= 1; |
simonbarker | 0:d961f715d82b | 79 | |
simonbarker | 0:d961f715d82b | 80 | // if result is one, then set MS bit |
simonbarker | 0:d961f715d82b | 81 | if (readBit()) |
simonbarker | 0:d961f715d82b | 82 | result |= 0x80; |
simonbarker | 0:d961f715d82b | 83 | } |
simonbarker | 0:d961f715d82b | 84 | return result; |
simonbarker | 0:d961f715d82b | 85 | } |
Bobty | 2:b7ee49dbd7ef | 86 | |
Bobty | 2:b7ee49dbd7ef | 87 | void Onewire::writeByte(char data) |
Bobty | 2:b7ee49dbd7ef | 88 | { |
simonbarker | 0:d961f715d82b | 89 | // Loop to write each bit in the byte, LS-bit first |
Bobty | 4:b678c7c8203c | 90 | for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { |
simonbarker | 0:d961f715d82b | 91 | writeBit(data & 0x01); |
simonbarker | 0:d961f715d82b | 92 | |
simonbarker | 0:d961f715d82b | 93 | // shift the data byte for the next bit |
simonbarker | 0:d961f715d82b | 94 | data >>= 1; |
simonbarker | 0:d961f715d82b | 95 | } |
simonbarker | 0:d961f715d82b | 96 | } |
Bobty | 2:b7ee49dbd7ef | 97 | |
Bobty | 2:b7ee49dbd7ef | 98 | unsigned char Onewire::CRC(unsigned char* addr, unsigned char len) |
Bobty | 2:b7ee49dbd7ef | 99 | { |
simonbarker | 0:d961f715d82b | 100 | unsigned char i, j; |
simonbarker | 0:d961f715d82b | 101 | unsigned char crc = 0; |
simonbarker | 0:d961f715d82b | 102 | |
simonbarker | 0:d961f715d82b | 103 | for (i = 0; i < len; i++) { |
simonbarker | 0:d961f715d82b | 104 | unsigned char inbyte = addr[i]; |
Bobty | 4:b678c7c8203c | 105 | for (j = 0; j < ONEWIRE_ADDR_BYTES; j++) { |
simonbarker | 0:d961f715d82b | 106 | unsigned char mix = (crc ^ inbyte) & 0x01; |
simonbarker | 0:d961f715d82b | 107 | crc >>= 1; |
simonbarker | 0:d961f715d82b | 108 | if (mix) crc ^= 0x8C; |
simonbarker | 0:d961f715d82b | 109 | inbyte >>= 1; |
simonbarker | 0:d961f715d82b | 110 | } |
simonbarker | 0:d961f715d82b | 111 | } |
simonbarker | 0:d961f715d82b | 112 | return crc; |
simonbarker | 0:d961f715d82b | 113 | } |
simonbarker | 0:d961f715d82b | 114 | |
Bobty | 1:8e9464e05ddf | 115 | // |
Bobty | 1:8e9464e05ddf | 116 | // You need to use this function to start a search again from the beginning. |
Bobty | 1:8e9464e05ddf | 117 | // You do not need to do it for the first search, though you could. |
Bobty | 1:8e9464e05ddf | 118 | // |
Bobty | 1:8e9464e05ddf | 119 | void Onewire::reset_search() |
Bobty | 1:8e9464e05ddf | 120 | { |
Bobty | 2:b7ee49dbd7ef | 121 | // reset the search state |
Bobty | 2:b7ee49dbd7ef | 122 | _search_LastDiscrepancy = 0; |
Bobty | 2:b7ee49dbd7ef | 123 | _search_LastDeviceFlag = false; |
Bobty | 2:b7ee49dbd7ef | 124 | _search_LastFamilyDiscrepancy = 0; |
Bobty | 4:b678c7c8203c | 125 | for(int i = ONEWIRE_ADDR_BYTES-1; i >= 0; i--) |
Bobty | 2:b7ee49dbd7ef | 126 | _search_ROM_NO[i] = 0; |
Bobty | 1:8e9464e05ddf | 127 | } |
Bobty | 1:8e9464e05ddf | 128 | |
Bobty | 7:0a87f8c2d9e6 | 129 | // Search Based on Maxim DS18B20 Algorithm |
Bobty | 7:0a87f8c2d9e6 | 130 | // https://www.maximintegrated.com/en/app-notes/index.mvp/id/187 |
Bobty | 1:8e9464e05ddf | 131 | // |
Bobty | 7:0a87f8c2d9e6 | 132 | // Perform a search, returns: |
Bobty | 6:d2452e9b169b | 133 | // ONEWIRE_OK if a new address has been returned. |
Bobty | 6:d2452e9b169b | 134 | // ONEWIRE_SEARCH_ALL_DONE = all devices found |
Bobty | 6:d2452e9b169b | 135 | // ONEWIRE_SEARCH_INIT_FAIL = failed to init |
Bobty | 6:d2452e9b169b | 136 | // ONEWIRE_SEARCH_NOT_FOUND = no devices found If this function returns a '1' then it has |
Bobty | 7:0a87f8c2d9e6 | 137 | // ONEWIRE_SEARCH_STUCK_HIGH = bus is stuck high |
Bobty | 7:0a87f8c2d9e6 | 138 | // ONEWIRE_SEARCH_COMP_BIT_ERR = complement bit error |
Bobty | 1:8e9464e05ddf | 139 | // |
Bobty | 1:8e9464e05ddf | 140 | uint8_t Onewire::search(uint8_t *newAddr) |
Bobty | 1:8e9464e05ddf | 141 | { |
Bobty | 7:0a87f8c2d9e6 | 142 | // initialize for search |
Bobty | 7:0a87f8c2d9e6 | 143 | uint8_t last_zero = 0; |
Bobty | 7:0a87f8c2d9e6 | 144 | unsigned char search_direction = 0; |
Bobty | 1:8e9464e05ddf | 145 | |
Bobty | 7:0a87f8c2d9e6 | 146 | // if the previous call was the last one |
Bobty | 7:0a87f8c2d9e6 | 147 | if (_search_LastDeviceFlag) |
Bobty | 7:0a87f8c2d9e6 | 148 | return ONEWIRE_SEARCH_ALL_DONE; |
Bobty | 7:0a87f8c2d9e6 | 149 | |
Bobty | 7:0a87f8c2d9e6 | 150 | // 1-Wire reset |
Bobty | 7:0a87f8c2d9e6 | 151 | int initRslt = init(); |
Bobty | 7:0a87f8c2d9e6 | 152 | wait_us(410); |
Bobty | 7:0a87f8c2d9e6 | 153 | if (initRslt != ONEWIRE_OK) |
Bobty | 7:0a87f8c2d9e6 | 154 | { |
Bobty | 7:0a87f8c2d9e6 | 155 | // reset the search |
Bobty | 7:0a87f8c2d9e6 | 156 | reset_search(); |
Bobty | 7:0a87f8c2d9e6 | 157 | return initRslt; |
Bobty | 7:0a87f8c2d9e6 | 158 | } |
Bobty | 7:0a87f8c2d9e6 | 159 | |
Bobty | 7:0a87f8c2d9e6 | 160 | // issue the search command |
Bobty | 7:0a87f8c2d9e6 | 161 | writeByte(0xF0); |
Bobty | 7:0a87f8c2d9e6 | 162 | |
Bobty | 7:0a87f8c2d9e6 | 163 | // loop to do the search |
Bobty | 7:0a87f8c2d9e6 | 164 | for (int id_bit_number = 1; id_bit_number <= 64; id_bit_number++) |
Bobty | 7:0a87f8c2d9e6 | 165 | { |
Bobty | 7:0a87f8c2d9e6 | 166 | // read a bit and its complement |
Bobty | 7:0a87f8c2d9e6 | 167 | uint8_t id_bit = readBit(); |
Bobty | 7:0a87f8c2d9e6 | 168 | uint8_t cmp_id_bit = readBit(); |
Bobty | 7:0a87f8c2d9e6 | 169 | |
Bobty | 7:0a87f8c2d9e6 | 170 | // check for no devices on 1-wire |
Bobty | 7:0a87f8c2d9e6 | 171 | if ((id_bit == 1) && (cmp_id_bit == 1)) |
Bobty | 7:0a87f8c2d9e6 | 172 | { |
Bobty | 7:0a87f8c2d9e6 | 173 | reset_search(); |
Bobty | 7:0a87f8c2d9e6 | 174 | return ONEWIRE_SEARCH_COMP_BIT_ERR; |
Bobty | 7:0a87f8c2d9e6 | 175 | } |
Bobty | 1:8e9464e05ddf | 176 | |
Bobty | 7:0a87f8c2d9e6 | 177 | // all devices coupled have 0 or 1 |
Bobty | 7:0a87f8c2d9e6 | 178 | int byteNo = (id_bit_number - 1) / 8; |
Bobty | 7:0a87f8c2d9e6 | 179 | int byteMask = 1 << ((id_bit_number - 1) % 8); |
Bobty | 7:0a87f8c2d9e6 | 180 | if (id_bit != cmp_id_bit) |
Bobty | 7:0a87f8c2d9e6 | 181 | { |
Bobty | 7:0a87f8c2d9e6 | 182 | search_direction = id_bit; // bit write value for search |
Bobty | 7:0a87f8c2d9e6 | 183 | } |
Bobty | 7:0a87f8c2d9e6 | 184 | else |
Bobty | 7:0a87f8c2d9e6 | 185 | { |
Bobty | 7:0a87f8c2d9e6 | 186 | if (id_bit_number == _search_LastDiscrepancy) |
Bobty | 7:0a87f8c2d9e6 | 187 | { |
Bobty | 7:0a87f8c2d9e6 | 188 | search_direction = 1; |
Bobty | 7:0a87f8c2d9e6 | 189 | } |
Bobty | 7:0a87f8c2d9e6 | 190 | else if (id_bit_number > _search_LastDiscrepancy) |
Bobty | 7:0a87f8c2d9e6 | 191 | { |
Bobty | 7:0a87f8c2d9e6 | 192 | search_direction = 0; |
Bobty | 7:0a87f8c2d9e6 | 193 | } |
Bobty | 1:8e9464e05ddf | 194 | else |
Bobty | 1:8e9464e05ddf | 195 | { |
Bobty | 7:0a87f8c2d9e6 | 196 | search_direction = ((_search_ROM_NO[byteNo] & byteMask) > 0); |
Bobty | 1:8e9464e05ddf | 197 | } |
Bobty | 7:0a87f8c2d9e6 | 198 | |
Bobty | 7:0a87f8c2d9e6 | 199 | // if 0 was picked then record its position in LastZero |
Bobty | 7:0a87f8c2d9e6 | 200 | if (search_direction == 0) |
Bobty | 1:8e9464e05ddf | 201 | { |
Bobty | 7:0a87f8c2d9e6 | 202 | last_zero = id_bit_number; |
Bobty | 7:0a87f8c2d9e6 | 203 | // check for Last discrepancy in family |
Bobty | 7:0a87f8c2d9e6 | 204 | if (last_zero < 9) |
Bobty | 7:0a87f8c2d9e6 | 205 | _search_LastFamilyDiscrepancy = last_zero; |
Bobty | 1:8e9464e05ddf | 206 | } |
Bobty | 7:0a87f8c2d9e6 | 207 | } |
Bobty | 7:0a87f8c2d9e6 | 208 | |
Bobty | 7:0a87f8c2d9e6 | 209 | // set or clear the bit in the ROM byte rom_byte_number |
Bobty | 7:0a87f8c2d9e6 | 210 | // with mask rom_byte_mask |
Bobty | 7:0a87f8c2d9e6 | 211 | |
Bobty | 7:0a87f8c2d9e6 | 212 | if (search_direction == 1) |
Bobty | 7:0a87f8c2d9e6 | 213 | _search_ROM_NO[byteNo] |= byteMask; |
Bobty | 7:0a87f8c2d9e6 | 214 | else |
Bobty | 7:0a87f8c2d9e6 | 215 | _search_ROM_NO[byteNo] &= ~byteMask; |
Bobty | 7:0a87f8c2d9e6 | 216 | |
Bobty | 7:0a87f8c2d9e6 | 217 | // serial number search direction write bit |
Bobty | 7:0a87f8c2d9e6 | 218 | writeBit(search_direction); |
Bobty | 7:0a87f8c2d9e6 | 219 | } |
Bobty | 7:0a87f8c2d9e6 | 220 | |
Bobty | 7:0a87f8c2d9e6 | 221 | // search successful so set LastDiscrepancy,LastDeviceFlag,search_result |
Bobty | 7:0a87f8c2d9e6 | 222 | _search_LastDiscrepancy = last_zero; |
Bobty | 7:0a87f8c2d9e6 | 223 | // check for last device |
Bobty | 7:0a87f8c2d9e6 | 224 | if (_search_LastDiscrepancy == 0) |
Bobty | 7:0a87f8c2d9e6 | 225 | _search_LastDeviceFlag = true; |
Bobty | 7:0a87f8c2d9e6 | 226 | |
Bobty | 7:0a87f8c2d9e6 | 227 | // Copy address to return |
Bobty | 7:0a87f8c2d9e6 | 228 | for (int i = 0; i < ONEWIRE_ADDR_BYTES; i++) |
Bobty | 7:0a87f8c2d9e6 | 229 | newAddr[i] = _search_ROM_NO[i]; |
Bobty | 7:0a87f8c2d9e6 | 230 | |
Bobty | 7:0a87f8c2d9e6 | 231 | return ONEWIRE_OK; |
Bobty | 7:0a87f8c2d9e6 | 232 | } |
Bobty | 1:8e9464e05ddf | 233 | |
Bobty | 7:0a87f8c2d9e6 | 234 | char* Onewire::GetErrorStr(int errCode) |
Bobty | 7:0a87f8c2d9e6 | 235 | { |
Bobty | 7:0a87f8c2d9e6 | 236 | switch(errCode) |
Bobty | 7:0a87f8c2d9e6 | 237 | { |
Bobty | 7:0a87f8c2d9e6 | 238 | case ONEWIRE_OK: return "OK"; |
Bobty | 7:0a87f8c2d9e6 | 239 | case ONEWIRE_SEARCH_ALL_DONE: return "All Done"; |
Bobty | 7:0a87f8c2d9e6 | 240 | case ONEWIRE_SEARCH_INIT_FAIL: return "Init Fail"; |
Bobty | 7:0a87f8c2d9e6 | 241 | case ONEWIRE_SEARCH_NOT_FOUND: return "Not Found"; |
Bobty | 7:0a87f8c2d9e6 | 242 | case ONEWIRE_SEARCH_STUCK_HIGH: return "Stuck High"; |
Bobty | 7:0a87f8c2d9e6 | 243 | case ONEWIRE_SEARCH_COMP_BIT_ERR: return "Comp Bit Err"; |
Bobty | 7:0a87f8c2d9e6 | 244 | } |
Bobty | 7:0a87f8c2d9e6 | 245 | return "Unknown Err"; |
Bobty | 7:0a87f8c2d9e6 | 246 | } |
Bobty | 7:0a87f8c2d9e6 | 247 |