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
- Committer:
- alpov
- Date:
- 2014-04-28
- Revision:
- 0:445fe6e6bd68
File content as of revision 0:445fe6e6bd68:
#include "mbed.h" #include "1wire.h" OneWire::OneWire(PinName OwUp, PinName OwDn, PinName OwIn) : _OwUp(OwUp, !0), _OwDn(OwDn, !1), _OwIn(OwIn, PullNone) { } int OneWire::Reset(void) { int result; DELAY_G(); __disable_irq(); _OwDn = !0; DELAY_H(); _OwDn = !1; DELAY_I(); result = _OwIn; __enable_irq(); DELAY_J(); return result; } void OneWire::WriteBit(int bit) { __disable_irq(); if (bit) { _OwDn = !0; DELAY_A(); _OwDn = !1; DELAY_B(); } else { _OwDn = !0; DELAY_C(); _OwDn = !1; DELAY_D(); } __enable_irq(); } int OneWire::ReadBit(void) { int result; __disable_irq(); _OwDn = !0; DELAY_A(); _OwDn = !1; DELAY_E(); result = _OwIn; __enable_irq(); DELAY_F(); return result; } void OneWire::WriteByte(uint8_t data) { for (int i = 0; i < 8; i++) { WriteBit(data & 0x01); data >>= 1; } } uint8_t OneWire::ReadByte(void) { uint8_t result = 0; for (int i = 0; i < 8; i++) { result >>= 1; if (ReadBit()) result |= 0x80; } return result; } void OneWire::SendCmd(uint8_t *ROMID, uint8_t cmd) { Reset(); if (ROMID == NULL) { WriteByte(OW_SKIP_ROM_CMD); } else { WriteByte(OW_MATCH_ROM_CMD); for (int i = 0; i < 8; i++) WriteByte(ROMID[i]); } WriteByte(cmd); } int OneWire::First(uint8_t *ROMID) { /* Reset state */ OW_LastDiscrepancy = 0; OW_LastDevice = 0; OW_LastFamilyDiscrepancy = 0; /* Go looking */ return Next(ROMID); } int OneWire::Next(uint8_t *ROMID) { uint8_t bit_test, search_direction, bit_number; uint8_t last_zero, rom_byte_number, rom_byte_mask; uint8_t lastcrc8, crcaccum; int next_result; /* Init for search */ bit_number = 1; last_zero = 0; rom_byte_number = 0; rom_byte_mask = 1; next_result = OW_NOMODULES; lastcrc8 = 0; crcaccum = 0; /* if the last call was not the last one */ if (!OW_LastDevice) { /* reset the 1-wire if there are no parts on 1-wire, return 0 */ if (Reset()) { /* reset the search */ OW_LastDiscrepancy = 0; OW_LastFamilyDiscrepancy = 0; return OW_NOPRESENCE; } WriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */ /* pause before beginning the search - removed */ /* loop to do the search */ do { /* read a bit and its compliment */ bit_test = ReadBit() << 1; bit_test |= ReadBit(); /* check for no devices on 1-wire */ if (bit_test == 3) { return(OW_BADWIRE); } else { /* all devices coupled have 0 or 1 */ if (bit_test > 0) search_direction = !(bit_test & 0x01); /* bit write value for search */ else { /* if this discrepancy is before the Last Discrepancy * on a previous OWNext then pick the same as last time */ if (bit_number < OW_LastDiscrepancy) search_direction = ((ROMID[rom_byte_number] & rom_byte_mask) > 0); else /* if equal to last pick 1, if not then pick 0 */ search_direction = (bit_number == OW_LastDiscrepancy); /* if 0 was picked then record its position in LastZero */ if (search_direction == 0) { last_zero = bit_number; /* check for Last discrepancy in family */ if (last_zero < 9) OW_LastFamilyDiscrepancy = last_zero; } } /* set or clear the bit in the ROM byte rom_byte_number * with mask rom_byte_mask */ if (search_direction == 1) ROMID[rom_byte_number] |= rom_byte_mask; else ROMID[rom_byte_number] &= ~rom_byte_mask; /* serial number search direction write bit */ WriteBit(search_direction); /* increment the byte counter bit_number * and shift the mask rom_byte_mask */ bit_number++; rom_byte_mask <<= 1; /* if the mask is 0 then go to new ROM byte rom_byte_number * and reset mask */ if (rom_byte_mask == 0) { CRC(ROMID[rom_byte_number], &crcaccum); /* accumulate the CRC */ lastcrc8 = crcaccum; rom_byte_number++; rom_byte_mask = 1; } } } while (rom_byte_number < 8); /* loop until through all ROM bytes 0-7 */ /* if the search was successful then */ if (!(bit_number < 65) || lastcrc8) { if (lastcrc8) { next_result = OW_BADCRC; } else { /* search successful so set LastDiscrepancy,LastDevice,next_result */ OW_LastDiscrepancy = last_zero; OW_LastDevice = (OW_LastDiscrepancy == 0); next_result = OW_FOUND; } } } /* if no device found then reset counters so next 'next' will be like a first */ if (next_result != OW_FOUND || ROMID[0] == 0) { OW_LastDiscrepancy = 0; OW_LastDevice = 0; OW_LastFamilyDiscrepancy = 0; } if (next_result == OW_FOUND && ROMID[0] == 0x00) next_result = OW_BADWIRE; return next_result; } void OneWire::CRC(uint8_t x, uint8_t *crc) { for (int j = 0; j < 8; j++) { uint8_t mix = (*crc ^ x) & 0x01; *crc >>= 1; if (mix) *crc ^= 0x8C; x >>= 1; } } void OneWire::ConvertAll(bool wait) { SendCmd(NULL, OW_CONVERT_T_CMD); if (wait) { _OwUp = !1; wait_ms(CONVERT_T_DELAY); _OwUp = !0; } } int OneWire::ReadTemperature(uint8_t *ROMID, int *result) { uint8_t crc = 0, buf[8]; SendCmd(ROMID, OW_RD_SCR_CMD); for (int i = 0; i < 8; i++) { buf[i] = ReadByte(); CRC(buf[i], &crc); } if (crc != ReadByte()) { return ERR_BADCRC; } switch (ROMID[0]) { case 0x10: // ds18s20 *result = (signed char)((buf[1] & 0x80) | (buf[0] >> 1)) * 100 + 75 - buf[6] * 100 / 16; break; case 0x28: // ds18b20 *result = (signed char)((buf[1] << 4) | (buf[0] >> 4)) * 100 + (buf[0] & 0x0F) * 100 / 16; break; default: return ERR_BADFAMILY; } return 0; }