Dallas 1-wire driver with DS18B20 temperature sensor support; custom bus driver to work with https://emir.googlecode.com/svn/emir2/trunk/eagle/emir-shield.sch
Dependents: testing_RTC_OneWire EMIRv2
1wire.cpp@0:445fe6e6bd68, 2014-04-28 (annotated)
- Committer:
- alpov
- Date:
- Mon Apr 28 06:52:49 2014 +0000
- Revision:
- 0:445fe6e6bd68
initial version, working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
alpov | 0:445fe6e6bd68 | 1 | #include "mbed.h" |
alpov | 0:445fe6e6bd68 | 2 | #include "1wire.h" |
alpov | 0:445fe6e6bd68 | 3 | |
alpov | 0:445fe6e6bd68 | 4 | OneWire::OneWire(PinName OwUp, PinName OwDn, PinName OwIn) : _OwUp(OwUp, !0), _OwDn(OwDn, !1), _OwIn(OwIn, PullNone) |
alpov | 0:445fe6e6bd68 | 5 | { |
alpov | 0:445fe6e6bd68 | 6 | } |
alpov | 0:445fe6e6bd68 | 7 | |
alpov | 0:445fe6e6bd68 | 8 | int OneWire::Reset(void) |
alpov | 0:445fe6e6bd68 | 9 | { |
alpov | 0:445fe6e6bd68 | 10 | int result; |
alpov | 0:445fe6e6bd68 | 11 | |
alpov | 0:445fe6e6bd68 | 12 | DELAY_G(); |
alpov | 0:445fe6e6bd68 | 13 | __disable_irq(); |
alpov | 0:445fe6e6bd68 | 14 | _OwDn = !0; |
alpov | 0:445fe6e6bd68 | 15 | DELAY_H(); |
alpov | 0:445fe6e6bd68 | 16 | _OwDn = !1; |
alpov | 0:445fe6e6bd68 | 17 | DELAY_I(); |
alpov | 0:445fe6e6bd68 | 18 | result = _OwIn; |
alpov | 0:445fe6e6bd68 | 19 | __enable_irq(); |
alpov | 0:445fe6e6bd68 | 20 | DELAY_J(); |
alpov | 0:445fe6e6bd68 | 21 | return result; |
alpov | 0:445fe6e6bd68 | 22 | } |
alpov | 0:445fe6e6bd68 | 23 | |
alpov | 0:445fe6e6bd68 | 24 | void OneWire::WriteBit(int bit) |
alpov | 0:445fe6e6bd68 | 25 | { |
alpov | 0:445fe6e6bd68 | 26 | __disable_irq(); |
alpov | 0:445fe6e6bd68 | 27 | if (bit) { |
alpov | 0:445fe6e6bd68 | 28 | _OwDn = !0; |
alpov | 0:445fe6e6bd68 | 29 | DELAY_A(); |
alpov | 0:445fe6e6bd68 | 30 | _OwDn = !1; |
alpov | 0:445fe6e6bd68 | 31 | DELAY_B(); |
alpov | 0:445fe6e6bd68 | 32 | } else { |
alpov | 0:445fe6e6bd68 | 33 | _OwDn = !0; |
alpov | 0:445fe6e6bd68 | 34 | DELAY_C(); |
alpov | 0:445fe6e6bd68 | 35 | _OwDn = !1; |
alpov | 0:445fe6e6bd68 | 36 | DELAY_D(); |
alpov | 0:445fe6e6bd68 | 37 | } |
alpov | 0:445fe6e6bd68 | 38 | __enable_irq(); |
alpov | 0:445fe6e6bd68 | 39 | } |
alpov | 0:445fe6e6bd68 | 40 | |
alpov | 0:445fe6e6bd68 | 41 | int OneWire::ReadBit(void) |
alpov | 0:445fe6e6bd68 | 42 | { |
alpov | 0:445fe6e6bd68 | 43 | int result; |
alpov | 0:445fe6e6bd68 | 44 | |
alpov | 0:445fe6e6bd68 | 45 | __disable_irq(); |
alpov | 0:445fe6e6bd68 | 46 | _OwDn = !0; |
alpov | 0:445fe6e6bd68 | 47 | DELAY_A(); |
alpov | 0:445fe6e6bd68 | 48 | _OwDn = !1; |
alpov | 0:445fe6e6bd68 | 49 | DELAY_E(); |
alpov | 0:445fe6e6bd68 | 50 | result = _OwIn; |
alpov | 0:445fe6e6bd68 | 51 | __enable_irq(); |
alpov | 0:445fe6e6bd68 | 52 | DELAY_F(); |
alpov | 0:445fe6e6bd68 | 53 | return result; |
alpov | 0:445fe6e6bd68 | 54 | } |
alpov | 0:445fe6e6bd68 | 55 | |
alpov | 0:445fe6e6bd68 | 56 | void OneWire::WriteByte(uint8_t data) |
alpov | 0:445fe6e6bd68 | 57 | { |
alpov | 0:445fe6e6bd68 | 58 | for (int i = 0; i < 8; i++) { |
alpov | 0:445fe6e6bd68 | 59 | WriteBit(data & 0x01); |
alpov | 0:445fe6e6bd68 | 60 | data >>= 1; |
alpov | 0:445fe6e6bd68 | 61 | } |
alpov | 0:445fe6e6bd68 | 62 | } |
alpov | 0:445fe6e6bd68 | 63 | |
alpov | 0:445fe6e6bd68 | 64 | uint8_t OneWire::ReadByte(void) |
alpov | 0:445fe6e6bd68 | 65 | { |
alpov | 0:445fe6e6bd68 | 66 | uint8_t result = 0; |
alpov | 0:445fe6e6bd68 | 67 | |
alpov | 0:445fe6e6bd68 | 68 | for (int i = 0; i < 8; i++) { |
alpov | 0:445fe6e6bd68 | 69 | result >>= 1; |
alpov | 0:445fe6e6bd68 | 70 | if (ReadBit()) |
alpov | 0:445fe6e6bd68 | 71 | result |= 0x80; |
alpov | 0:445fe6e6bd68 | 72 | } |
alpov | 0:445fe6e6bd68 | 73 | return result; |
alpov | 0:445fe6e6bd68 | 74 | } |
alpov | 0:445fe6e6bd68 | 75 | |
alpov | 0:445fe6e6bd68 | 76 | void OneWire::SendCmd(uint8_t *ROMID, uint8_t cmd) |
alpov | 0:445fe6e6bd68 | 77 | { |
alpov | 0:445fe6e6bd68 | 78 | Reset(); |
alpov | 0:445fe6e6bd68 | 79 | if (ROMID == NULL) { |
alpov | 0:445fe6e6bd68 | 80 | WriteByte(OW_SKIP_ROM_CMD); |
alpov | 0:445fe6e6bd68 | 81 | } else { |
alpov | 0:445fe6e6bd68 | 82 | WriteByte(OW_MATCH_ROM_CMD); |
alpov | 0:445fe6e6bd68 | 83 | for (int i = 0; i < 8; i++) |
alpov | 0:445fe6e6bd68 | 84 | WriteByte(ROMID[i]); |
alpov | 0:445fe6e6bd68 | 85 | } |
alpov | 0:445fe6e6bd68 | 86 | WriteByte(cmd); |
alpov | 0:445fe6e6bd68 | 87 | } |
alpov | 0:445fe6e6bd68 | 88 | |
alpov | 0:445fe6e6bd68 | 89 | int OneWire::First(uint8_t *ROMID) |
alpov | 0:445fe6e6bd68 | 90 | { |
alpov | 0:445fe6e6bd68 | 91 | /* Reset state */ |
alpov | 0:445fe6e6bd68 | 92 | OW_LastDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 93 | OW_LastDevice = 0; |
alpov | 0:445fe6e6bd68 | 94 | OW_LastFamilyDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 95 | |
alpov | 0:445fe6e6bd68 | 96 | /* Go looking */ |
alpov | 0:445fe6e6bd68 | 97 | return Next(ROMID); |
alpov | 0:445fe6e6bd68 | 98 | } |
alpov | 0:445fe6e6bd68 | 99 | |
alpov | 0:445fe6e6bd68 | 100 | int OneWire::Next(uint8_t *ROMID) |
alpov | 0:445fe6e6bd68 | 101 | { |
alpov | 0:445fe6e6bd68 | 102 | uint8_t bit_test, search_direction, bit_number; |
alpov | 0:445fe6e6bd68 | 103 | uint8_t last_zero, rom_byte_number, rom_byte_mask; |
alpov | 0:445fe6e6bd68 | 104 | uint8_t lastcrc8, crcaccum; |
alpov | 0:445fe6e6bd68 | 105 | int next_result; |
alpov | 0:445fe6e6bd68 | 106 | |
alpov | 0:445fe6e6bd68 | 107 | /* Init for search */ |
alpov | 0:445fe6e6bd68 | 108 | bit_number = 1; |
alpov | 0:445fe6e6bd68 | 109 | last_zero = 0; |
alpov | 0:445fe6e6bd68 | 110 | rom_byte_number = 0; |
alpov | 0:445fe6e6bd68 | 111 | rom_byte_mask = 1; |
alpov | 0:445fe6e6bd68 | 112 | next_result = OW_NOMODULES; |
alpov | 0:445fe6e6bd68 | 113 | lastcrc8 = 0; |
alpov | 0:445fe6e6bd68 | 114 | crcaccum = 0; |
alpov | 0:445fe6e6bd68 | 115 | |
alpov | 0:445fe6e6bd68 | 116 | /* if the last call was not the last one */ |
alpov | 0:445fe6e6bd68 | 117 | if (!OW_LastDevice) { |
alpov | 0:445fe6e6bd68 | 118 | /* reset the 1-wire if there are no parts on 1-wire, return 0 */ |
alpov | 0:445fe6e6bd68 | 119 | if (Reset()) { |
alpov | 0:445fe6e6bd68 | 120 | /* reset the search */ |
alpov | 0:445fe6e6bd68 | 121 | OW_LastDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 122 | OW_LastFamilyDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 123 | return OW_NOPRESENCE; |
alpov | 0:445fe6e6bd68 | 124 | } |
alpov | 0:445fe6e6bd68 | 125 | |
alpov | 0:445fe6e6bd68 | 126 | WriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */ |
alpov | 0:445fe6e6bd68 | 127 | |
alpov | 0:445fe6e6bd68 | 128 | /* pause before beginning the search - removed */ |
alpov | 0:445fe6e6bd68 | 129 | /* loop to do the search */ |
alpov | 0:445fe6e6bd68 | 130 | do { |
alpov | 0:445fe6e6bd68 | 131 | /* read a bit and its compliment */ |
alpov | 0:445fe6e6bd68 | 132 | bit_test = ReadBit() << 1; |
alpov | 0:445fe6e6bd68 | 133 | bit_test |= ReadBit(); |
alpov | 0:445fe6e6bd68 | 134 | |
alpov | 0:445fe6e6bd68 | 135 | /* check for no devices on 1-wire */ |
alpov | 0:445fe6e6bd68 | 136 | if (bit_test == 3) { |
alpov | 0:445fe6e6bd68 | 137 | return(OW_BADWIRE); |
alpov | 0:445fe6e6bd68 | 138 | } else { |
alpov | 0:445fe6e6bd68 | 139 | /* all devices coupled have 0 or 1 */ |
alpov | 0:445fe6e6bd68 | 140 | if (bit_test > 0) |
alpov | 0:445fe6e6bd68 | 141 | search_direction = !(bit_test & 0x01); /* bit write value for search */ |
alpov | 0:445fe6e6bd68 | 142 | else { |
alpov | 0:445fe6e6bd68 | 143 | /* if this discrepancy is before the Last Discrepancy |
alpov | 0:445fe6e6bd68 | 144 | * on a previous OWNext then pick the same as last time */ |
alpov | 0:445fe6e6bd68 | 145 | if (bit_number < OW_LastDiscrepancy) |
alpov | 0:445fe6e6bd68 | 146 | search_direction = ((ROMID[rom_byte_number] & rom_byte_mask) > 0); |
alpov | 0:445fe6e6bd68 | 147 | else |
alpov | 0:445fe6e6bd68 | 148 | /* if equal to last pick 1, if not then pick 0 */ |
alpov | 0:445fe6e6bd68 | 149 | search_direction = (bit_number == OW_LastDiscrepancy); |
alpov | 0:445fe6e6bd68 | 150 | |
alpov | 0:445fe6e6bd68 | 151 | /* if 0 was picked then record its position in LastZero */ |
alpov | 0:445fe6e6bd68 | 152 | if (search_direction == 0) { |
alpov | 0:445fe6e6bd68 | 153 | last_zero = bit_number; |
alpov | 0:445fe6e6bd68 | 154 | /* check for Last discrepancy in family */ |
alpov | 0:445fe6e6bd68 | 155 | if (last_zero < 9) |
alpov | 0:445fe6e6bd68 | 156 | OW_LastFamilyDiscrepancy = last_zero; |
alpov | 0:445fe6e6bd68 | 157 | } |
alpov | 0:445fe6e6bd68 | 158 | } |
alpov | 0:445fe6e6bd68 | 159 | |
alpov | 0:445fe6e6bd68 | 160 | /* set or clear the bit in the ROM byte rom_byte_number |
alpov | 0:445fe6e6bd68 | 161 | * with mask rom_byte_mask */ |
alpov | 0:445fe6e6bd68 | 162 | if (search_direction == 1) |
alpov | 0:445fe6e6bd68 | 163 | ROMID[rom_byte_number] |= rom_byte_mask; |
alpov | 0:445fe6e6bd68 | 164 | else |
alpov | 0:445fe6e6bd68 | 165 | ROMID[rom_byte_number] &= ~rom_byte_mask; |
alpov | 0:445fe6e6bd68 | 166 | |
alpov | 0:445fe6e6bd68 | 167 | /* serial number search direction write bit */ |
alpov | 0:445fe6e6bd68 | 168 | WriteBit(search_direction); |
alpov | 0:445fe6e6bd68 | 169 | |
alpov | 0:445fe6e6bd68 | 170 | /* increment the byte counter bit_number |
alpov | 0:445fe6e6bd68 | 171 | * and shift the mask rom_byte_mask */ |
alpov | 0:445fe6e6bd68 | 172 | bit_number++; |
alpov | 0:445fe6e6bd68 | 173 | rom_byte_mask <<= 1; |
alpov | 0:445fe6e6bd68 | 174 | |
alpov | 0:445fe6e6bd68 | 175 | /* if the mask is 0 then go to new ROM byte rom_byte_number |
alpov | 0:445fe6e6bd68 | 176 | * and reset mask */ |
alpov | 0:445fe6e6bd68 | 177 | if (rom_byte_mask == 0) { |
alpov | 0:445fe6e6bd68 | 178 | CRC(ROMID[rom_byte_number], &crcaccum); /* accumulate the CRC */ |
alpov | 0:445fe6e6bd68 | 179 | lastcrc8 = crcaccum; |
alpov | 0:445fe6e6bd68 | 180 | |
alpov | 0:445fe6e6bd68 | 181 | rom_byte_number++; |
alpov | 0:445fe6e6bd68 | 182 | rom_byte_mask = 1; |
alpov | 0:445fe6e6bd68 | 183 | } |
alpov | 0:445fe6e6bd68 | 184 | } |
alpov | 0:445fe6e6bd68 | 185 | } while (rom_byte_number < 8); /* loop until through all ROM bytes 0-7 */ |
alpov | 0:445fe6e6bd68 | 186 | |
alpov | 0:445fe6e6bd68 | 187 | /* if the search was successful then */ |
alpov | 0:445fe6e6bd68 | 188 | if (!(bit_number < 65) || lastcrc8) { |
alpov | 0:445fe6e6bd68 | 189 | if (lastcrc8) { |
alpov | 0:445fe6e6bd68 | 190 | next_result = OW_BADCRC; |
alpov | 0:445fe6e6bd68 | 191 | } else { |
alpov | 0:445fe6e6bd68 | 192 | /* search successful so set LastDiscrepancy,LastDevice,next_result */ |
alpov | 0:445fe6e6bd68 | 193 | OW_LastDiscrepancy = last_zero; |
alpov | 0:445fe6e6bd68 | 194 | OW_LastDevice = (OW_LastDiscrepancy == 0); |
alpov | 0:445fe6e6bd68 | 195 | next_result = OW_FOUND; |
alpov | 0:445fe6e6bd68 | 196 | } |
alpov | 0:445fe6e6bd68 | 197 | } |
alpov | 0:445fe6e6bd68 | 198 | } |
alpov | 0:445fe6e6bd68 | 199 | |
alpov | 0:445fe6e6bd68 | 200 | /* if no device found then reset counters so next 'next' will be like a first */ |
alpov | 0:445fe6e6bd68 | 201 | if (next_result != OW_FOUND || ROMID[0] == 0) { |
alpov | 0:445fe6e6bd68 | 202 | OW_LastDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 203 | OW_LastDevice = 0; |
alpov | 0:445fe6e6bd68 | 204 | OW_LastFamilyDiscrepancy = 0; |
alpov | 0:445fe6e6bd68 | 205 | } |
alpov | 0:445fe6e6bd68 | 206 | |
alpov | 0:445fe6e6bd68 | 207 | if (next_result == OW_FOUND && ROMID[0] == 0x00) |
alpov | 0:445fe6e6bd68 | 208 | next_result = OW_BADWIRE; |
alpov | 0:445fe6e6bd68 | 209 | |
alpov | 0:445fe6e6bd68 | 210 | return next_result; |
alpov | 0:445fe6e6bd68 | 211 | } |
alpov | 0:445fe6e6bd68 | 212 | |
alpov | 0:445fe6e6bd68 | 213 | void OneWire::CRC(uint8_t x, uint8_t *crc) |
alpov | 0:445fe6e6bd68 | 214 | { |
alpov | 0:445fe6e6bd68 | 215 | for (int j = 0; j < 8; j++) { |
alpov | 0:445fe6e6bd68 | 216 | uint8_t mix = (*crc ^ x) & 0x01; |
alpov | 0:445fe6e6bd68 | 217 | *crc >>= 1; |
alpov | 0:445fe6e6bd68 | 218 | if (mix) *crc ^= 0x8C; |
alpov | 0:445fe6e6bd68 | 219 | x >>= 1; |
alpov | 0:445fe6e6bd68 | 220 | } |
alpov | 0:445fe6e6bd68 | 221 | } |
alpov | 0:445fe6e6bd68 | 222 | |
alpov | 0:445fe6e6bd68 | 223 | void OneWire::ConvertAll(bool wait) |
alpov | 0:445fe6e6bd68 | 224 | { |
alpov | 0:445fe6e6bd68 | 225 | SendCmd(NULL, OW_CONVERT_T_CMD); |
alpov | 0:445fe6e6bd68 | 226 | if (wait) { |
alpov | 0:445fe6e6bd68 | 227 | _OwUp = !1; |
alpov | 0:445fe6e6bd68 | 228 | wait_ms(CONVERT_T_DELAY); |
alpov | 0:445fe6e6bd68 | 229 | _OwUp = !0; |
alpov | 0:445fe6e6bd68 | 230 | } |
alpov | 0:445fe6e6bd68 | 231 | } |
alpov | 0:445fe6e6bd68 | 232 | |
alpov | 0:445fe6e6bd68 | 233 | int OneWire::ReadTemperature(uint8_t *ROMID, int *result) |
alpov | 0:445fe6e6bd68 | 234 | { |
alpov | 0:445fe6e6bd68 | 235 | uint8_t crc = 0, buf[8]; |
alpov | 0:445fe6e6bd68 | 236 | |
alpov | 0:445fe6e6bd68 | 237 | SendCmd(ROMID, OW_RD_SCR_CMD); |
alpov | 0:445fe6e6bd68 | 238 | for (int i = 0; i < 8; i++) { |
alpov | 0:445fe6e6bd68 | 239 | buf[i] = ReadByte(); |
alpov | 0:445fe6e6bd68 | 240 | CRC(buf[i], &crc); |
alpov | 0:445fe6e6bd68 | 241 | } |
alpov | 0:445fe6e6bd68 | 242 | if (crc != ReadByte()) { |
alpov | 0:445fe6e6bd68 | 243 | return ERR_BADCRC; |
alpov | 0:445fe6e6bd68 | 244 | } |
alpov | 0:445fe6e6bd68 | 245 | |
alpov | 0:445fe6e6bd68 | 246 | switch (ROMID[0]) { |
alpov | 0:445fe6e6bd68 | 247 | case 0x10: // ds18s20 |
alpov | 0:445fe6e6bd68 | 248 | *result = (signed char)((buf[1] & 0x80) | (buf[0] >> 1)) * 100 + 75 - buf[6] * 100 / 16; |
alpov | 0:445fe6e6bd68 | 249 | break; |
alpov | 0:445fe6e6bd68 | 250 | case 0x28: // ds18b20 |
alpov | 0:445fe6e6bd68 | 251 | *result = (signed char)((buf[1] << 4) | (buf[0] >> 4)) * 100 + (buf[0] & 0x0F) * 100 / 16; |
alpov | 0:445fe6e6bd68 | 252 | break; |
alpov | 0:445fe6e6bd68 | 253 | default: |
alpov | 0:445fe6e6bd68 | 254 | return ERR_BADFAMILY; |
alpov | 0:445fe6e6bd68 | 255 | } |
alpov | 0:445fe6e6bd68 | 256 | return 0; |
alpov | 0:445fe6e6bd68 | 257 | } |