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

Committer:
alpov
Date:
Mon Apr 28 06:52:49 2014 +0000
Revision:
0:445fe6e6bd68
initial version, working

Who changed what in which revision?

UserRevisionLine numberNew 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 }