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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers 1wire.cpp Source File

1wire.cpp

00001 #include "mbed.h"
00002 #include "1wire.h"
00003 
00004 OneWire::OneWire(PinName OwUp, PinName OwDn, PinName OwIn) : _OwUp(OwUp, !0), _OwDn(OwDn, !1), _OwIn(OwIn, PullNone)
00005 {
00006 }
00007 
00008 int OneWire::Reset(void)
00009 {
00010     int result;
00011     
00012     DELAY_G();
00013     __disable_irq();
00014     _OwDn = !0;
00015     DELAY_H();
00016     _OwDn = !1;
00017     DELAY_I();
00018     result = _OwIn;
00019     __enable_irq();
00020     DELAY_J();
00021     return result;
00022 }
00023 
00024 void OneWire::WriteBit(int bit)
00025 {
00026     __disable_irq();
00027     if (bit) {
00028         _OwDn = !0;
00029         DELAY_A();
00030         _OwDn = !1;
00031         DELAY_B();
00032     } else {
00033         _OwDn = !0;
00034         DELAY_C();
00035         _OwDn = !1;
00036         DELAY_D();
00037     }
00038     __enable_irq();
00039 }
00040 
00041 int OneWire::ReadBit(void)
00042 {
00043     int result;
00044 
00045     __disable_irq();
00046     _OwDn = !0;
00047     DELAY_A();
00048     _OwDn = !1;
00049     DELAY_E();
00050     result = _OwIn;
00051     __enable_irq();
00052     DELAY_F();
00053     return result;
00054 }
00055 
00056 void OneWire::WriteByte(uint8_t data)
00057 {
00058     for (int i = 0; i < 8; i++) {
00059         WriteBit(data & 0x01);
00060         data >>= 1;
00061     }
00062 }
00063 
00064 uint8_t OneWire::ReadByte(void)
00065 {
00066     uint8_t result = 0;
00067     
00068     for (int i = 0; i < 8; i++) {
00069         result >>= 1;
00070         if (ReadBit())
00071             result |= 0x80;
00072     }
00073     return result;
00074 }
00075 
00076 void OneWire::SendCmd(uint8_t *ROMID, uint8_t cmd)
00077 {
00078     Reset();
00079     if (ROMID == NULL) {
00080         WriteByte(OW_SKIP_ROM_CMD);
00081     } else {
00082         WriteByte(OW_MATCH_ROM_CMD);
00083         for (int i = 0; i < 8; i++)
00084             WriteByte(ROMID[i]);
00085     }
00086     WriteByte(cmd);
00087 }
00088 
00089 int OneWire::First(uint8_t *ROMID)
00090 {
00091     /* Reset state */
00092     OW_LastDiscrepancy = 0;
00093     OW_LastDevice = 0;
00094     OW_LastFamilyDiscrepancy = 0;
00095     
00096     /* Go looking */
00097     return Next(ROMID);
00098 }
00099 
00100 int OneWire::Next(uint8_t *ROMID)
00101 {
00102     uint8_t bit_test, search_direction, bit_number;
00103     uint8_t last_zero, rom_byte_number, rom_byte_mask;
00104     uint8_t lastcrc8, crcaccum;
00105     int next_result;
00106 
00107     /* Init for search */
00108     bit_number = 1;
00109     last_zero = 0;
00110     rom_byte_number = 0;
00111     rom_byte_mask = 1;
00112     next_result = OW_NOMODULES;
00113     lastcrc8 = 0;
00114     crcaccum = 0;
00115     
00116     /* if the last call was not the last one */
00117     if (!OW_LastDevice) {
00118         /* reset the 1-wire if there are no parts on 1-wire, return 0 */
00119         if (Reset()) {
00120             /* reset the search */
00121             OW_LastDiscrepancy = 0;
00122             OW_LastFamilyDiscrepancy = 0;
00123             return OW_NOPRESENCE;
00124         }
00125         
00126         WriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */
00127         
00128         /* pause before beginning the search - removed */
00129         /* loop to do the search */
00130         do {
00131             /* read a bit and its compliment */
00132             bit_test = ReadBit() << 1;
00133             bit_test |= ReadBit();
00134             
00135             /* check for no devices on 1-wire */
00136             if (bit_test == 3) {
00137                 return(OW_BADWIRE);
00138             } else {
00139                 /* all devices coupled have 0 or 1 */
00140                 if (bit_test > 0)
00141                     search_direction = !(bit_test & 0x01);  /* bit write value for search */
00142                 else {
00143                     /* if this discrepancy is before the Last Discrepancy
00144                      * on a previous OWNext then pick the same as last time */
00145                     if (bit_number < OW_LastDiscrepancy)
00146                         search_direction = ((ROMID[rom_byte_number] & rom_byte_mask) > 0);
00147                     else
00148                         /* if equal to last pick 1, if not then pick 0 */
00149                         search_direction = (bit_number == OW_LastDiscrepancy);
00150                     
00151                     /* if 0 was picked then record its position in LastZero */
00152                     if (search_direction == 0) {
00153                         last_zero = bit_number;
00154                         /* check for Last discrepancy in family */
00155                         if (last_zero < 9)
00156                             OW_LastFamilyDiscrepancy = last_zero;
00157                     }
00158                 }
00159                 
00160                 /* set or clear the bit in the ROM byte rom_byte_number
00161                  * with mask rom_byte_mask */
00162                 if (search_direction == 1)
00163                     ROMID[rom_byte_number] |= rom_byte_mask;
00164                 else
00165                     ROMID[rom_byte_number] &= ~rom_byte_mask;
00166                 
00167                 /* serial number search direction write bit */
00168                 WriteBit(search_direction);
00169                 
00170                 /* increment the byte counter bit_number
00171                  * and shift the mask rom_byte_mask */
00172                 bit_number++;
00173                 rom_byte_mask <<= 1;
00174                 
00175                 /* if the mask is 0 then go to new ROM byte rom_byte_number
00176                  * and reset mask */
00177                 if (rom_byte_mask == 0) {
00178                     CRC(ROMID[rom_byte_number], &crcaccum);  /* accumulate the CRC */
00179                     lastcrc8 = crcaccum;
00180                     
00181                     rom_byte_number++;
00182                     rom_byte_mask = 1;
00183                 }
00184             }
00185         } while (rom_byte_number < 8);  /* loop until through all ROM bytes 0-7 */
00186         
00187         /* if the search was successful then */
00188         if (!(bit_number < 65) || lastcrc8) {
00189             if (lastcrc8) {
00190                 next_result = OW_BADCRC;
00191             } else {
00192                 /*  search successful so set LastDiscrepancy,LastDevice,next_result */
00193                 OW_LastDiscrepancy = last_zero;
00194                 OW_LastDevice = (OW_LastDiscrepancy == 0);
00195                 next_result = OW_FOUND;
00196             }
00197         }
00198     }
00199     
00200     /* if no device found then reset counters so next 'next' will be like a first */
00201     if (next_result != OW_FOUND || ROMID[0] == 0) {
00202         OW_LastDiscrepancy = 0;
00203         OW_LastDevice = 0;
00204         OW_LastFamilyDiscrepancy = 0;
00205     }
00206     
00207     if (next_result == OW_FOUND && ROMID[0] == 0x00)
00208         next_result = OW_BADWIRE;
00209     
00210     return next_result;
00211 }
00212 
00213 void OneWire::CRC(uint8_t x, uint8_t *crc)
00214 {
00215     for (int j = 0; j < 8; j++) {
00216         uint8_t mix = (*crc ^ x) & 0x01;
00217         *crc >>= 1;
00218         if (mix) *crc ^= 0x8C;
00219         x >>= 1;
00220     }
00221 }
00222 
00223 void OneWire::ConvertAll(bool wait)
00224 {
00225     SendCmd(NULL, OW_CONVERT_T_CMD);
00226     if (wait) {
00227         _OwUp = !1;
00228         wait_ms(CONVERT_T_DELAY);
00229         _OwUp = !0;
00230     }
00231 }
00232 
00233 int OneWire::ReadTemperature(uint8_t *ROMID, int *result)
00234 {       
00235     uint8_t crc = 0, buf[8];
00236     
00237     SendCmd(ROMID, OW_RD_SCR_CMD);
00238     for (int i = 0; i < 8; i++) {
00239         buf[i] = ReadByte();
00240         CRC(buf[i], &crc);
00241     }
00242     if (crc != ReadByte()) {
00243         return ERR_BADCRC;
00244     }
00245 
00246     switch (ROMID[0]) {
00247         case 0x10: // ds18s20
00248             *result = (signed char)((buf[1] & 0x80) | (buf[0] >> 1)) * 100 + 75 - buf[6] * 100 / 16;
00249             break;
00250         case 0x28: // ds18b20
00251             *result = (signed char)((buf[1] << 4) | (buf[0] >> 4)) * 100 + (buf[0] & 0x0F) * 100 / 16;
00252             break;
00253         default:
00254             return ERR_BADFAMILY;
00255     }
00256     return 0;
00257 }