Advertisement
tidwelltimj

spark core ds18b20 example

Dec 17th, 2013
763
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.44 KB | None | 0 0
  1. #ifndef OneWire_h
  2. #define OneWire_h
  3.  
  4. #include <inttypes.h>
  5. // you can exclude onewire_search by defining that to 0
  6. #ifndef ONEWIRE_SEARCH
  7. #define ONEWIRE_SEARCH 1
  8. #endif
  9.  
  10. // You can exclude CRC checks altogether by defining this to 0
  11. #ifndef ONEWIRE_CRC
  12. #define ONEWIRE_CRC 1
  13. #endif
  14.  
  15.  
  16.  
  17. // You can allow 16-bit CRC checks by defining this to 1
  18. // (Note that ONEWIRE_CRC must also be 1.)
  19. #ifndef ONEWIRE_CRC16
  20. #define ONEWIRE_CRC16 1
  21. #endif
  22.  
  23. #define FALSE 0
  24. #define TRUE  1
  25.  
  26. class OneWire
  27. {
  28.   private:
  29.  
  30.     uint16_t _pin;
  31.     void DIRECT_WRITE_LOW(void);
  32.     void DIRECT_MODE_OUTPUT(void);
  33.     void DIRECT_WRITE_HIGH(void);
  34.     void DIRECT_MODE_INPUT(void);
  35.     uint8_t DIRECT_READ(void);
  36. #if ONEWIRE_SEARCH
  37.     // global search state
  38.     unsigned char ROM_NO[8];
  39.     uint8_t LastDiscrepancy;
  40.     uint8_t LastFamilyDiscrepancy;
  41.     uint8_t LastDeviceFlag;
  42. #endif
  43.  
  44.   public:
  45.     OneWire( uint16_t pin);
  46.  
  47.     // Perform a 1-Wire reset cycle. Returns 1 if a device responds
  48.     // with a presence pulse.  Returns 0 if there is no device or the
  49.     // bus is shorted or otherwise held low for more than 250uS
  50.     uint8_t reset(void);
  51.  
  52.     // Issue a 1-Wire rom select command, you do the reset first.
  53.     void select(const uint8_t rom[8]);
  54.  
  55.     // Issue a 1-Wire rom skip command, to address all on bus.
  56.     void skip(void);
  57.  
  58.     // Write a byte. If 'power' is one then the wire is held high at
  59.     // the end for parasitically powered devices. You are responsible
  60.     // for eventually depowering it by calling depower() or doing
  61.     // another read or write.
  62.     void write(uint8_t v, uint8_t power = 0);
  63.  
  64.     void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);
  65.  
  66.     // Read a byte.
  67.     uint8_t read(void);
  68.  
  69.     void read_bytes(uint8_t *buf, uint16_t count);
  70.  
  71.     // Write a bit. The bus is always left powered at the end, see
  72.     // note in write() about that.
  73.     void write_bit(uint8_t v);
  74.  
  75.     // Read a bit.
  76.     uint8_t read_bit(void);
  77.  
  78.     // Stop forcing power onto the bus. You only need to do this if
  79.     // you used the 'power' flag to write() or used a write_bit() call
  80.     // and aren't about to do another read or write. You would rather
  81.     // not leave this powered if you don't have to, just in case
  82.     // someone shorts your bus.
  83.     void depower(void);
  84.  
  85. #if ONEWIRE_SEARCH
  86.     // Clear the search state so that if will start from the beginning again.
  87.     void reset_search();
  88.  
  89.     // Setup the search to find the device type 'family_code' on the next call
  90.     // to search(*newAddr) if it is present.
  91.     void target_search(uint8_t family_code);
  92.  
  93.     // Look for the next device. Returns 1 if a new address has been
  94.     // returned. A zero might mean that the bus is shorted, there are
  95.     // no devices, or you have already retrieved all of them.  It
  96.     // might be a good idea to check the CRC to make sure you didn't
  97.     // get garbage.  The order is deterministic. You will always get
  98.     // the same devices in the same order.
  99.     uint8_t search(uint8_t *newAddr);
  100. #endif
  101.  
  102. #if ONEWIRE_CRC
  103.     // Compute a Dallas Semiconductor 8 bit CRC, these are used in the
  104.     // ROM and scratchpad registers.
  105.     static uint8_t crc8(uint8_t *addr, uint8_t len);
  106.  
  107. #if ONEWIRE_CRC16
  108.     // Compute the 1-Wire CRC16 and compare it against the received CRC.
  109.     // Example usage (reading a DS2408):
  110.     //    // Put everything in a buffer so we can compute the CRC easily.
  111.     //    uint8_t buf[13];
  112.     //    buf[0] = 0xF0;    // Read PIO Registers
  113.     //    buf[1] = 0x88;    // LSB address
  114.     //    buf[2] = 0x00;    // MSB address
  115.     //    WriteBytes(net, buf, 3);    // Write 3 cmd bytes
  116.     //    ReadBytes(net, buf+3, 10);  // Read 6 data bytes, 2 0xFF, 2 CRC16
  117.     //    if (!CheckCRC16(buf, 11, &buf[11])) {
  118.     //        // Handle error.
  119.     //    }    
  120.     //          
  121.     // @param input - Array of bytes to checksum.
  122.     // @param len - How many bytes to use.
  123.     // @param inverted_crc - The two CRC16 bytes in the received data.
  124.     //                       This should just point into the received data,
  125.     //                       *not* at a 16-bit integer.
  126.     // @param crc - The crc starting value (optional)
  127.     // @return True, iff the CRC matches.
  128.     static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0);
  129.  
  130.     // Compute a Dallas Semiconductor 16 bit CRC.  This is required to check
  131.     // the integrity of data received from many 1-Wire devices.  Note that the
  132.     // CRC computed here is *not* what you'll get from the 1-Wire network,
  133.     // for two reasons:
  134.     //   1) The CRC is transmitted bitwise inverted.
  135.     //   2) Depending on the endian-ness of your processor, the binary
  136.     //      representation of the two-byte return value may have a different
  137.     //      byte order than the two bytes you get from 1-Wire.
  138.     // @param input - Array of bytes to checksum.
  139.     // @param len - How many bytes to use.
  140.     // @param crc - The crc starting value (optional)
  141.     // @return The CRC16, as defined by Dallas Semiconductor.
  142.     static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0);
  143. #endif
  144. #endif
  145. };
  146.  
  147. #endif
  148. OneWire::OneWire(uint16_t pin)
  149. {
  150.     pinMode(pin, INPUT);
  151.      _pin = pin;
  152.  
  153. }
  154.  
  155. void OneWire::DIRECT_WRITE_LOW(void)
  156. {
  157. PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin;
  158. }  
  159. void OneWire::DIRECT_MODE_OUTPUT(void)
  160. {
  161. GPIO_TypeDef *gpio_port = PIN_MAP[_pin].gpio_peripheral;
  162.     uint16_t gpio_pin = PIN_MAP[_pin].gpio_pin;
  163.  
  164.         GPIO_InitTypeDef GPIO_InitStructure;
  165.  
  166.         if (gpio_port == GPIOA )
  167.         {
  168.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  169.         }
  170.         else if (gpio_port == GPIOB )
  171.         {
  172.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  173.         }
  174.  
  175.     GPIO_InitStructure.GPIO_Pin = gpio_pin;
  176.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  177.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  178.     PIN_MAP[_pin].pin_mode = OUTPUT;
  179.     GPIO_Init(gpio_port, &GPIO_InitStructure);
  180. }
  181. void OneWire::DIRECT_WRITE_HIGH(void)
  182. {
  183. PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin;
  184. }
  185. void OneWire::DIRECT_MODE_INPUT(void)
  186. {
  187.     GPIO_TypeDef *gpio_port = PIN_MAP[_pin].gpio_peripheral;
  188.     uint16_t gpio_pin = PIN_MAP[_pin].gpio_pin;
  189.  
  190.         GPIO_InitTypeDef GPIO_InitStructure;
  191.  
  192.         if (gpio_port == GPIOA )
  193.         {
  194.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  195.         }
  196.         else if (gpio_port == GPIOB )
  197.         {
  198.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  199.         }
  200.  
  201.     GPIO_InitStructure.GPIO_Pin = gpio_pin;
  202.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  203.     PIN_MAP[_pin].pin_mode = INPUT;
  204. GPIO_Init(gpio_port, &GPIO_InitStructure);
  205. }
  206. uint8_t OneWire::DIRECT_READ(void)
  207. {
  208. return GPIO_ReadInputDataBit(PIN_MAP[_pin].gpio_peripheral, PIN_MAP[_pin].gpio_pin);
  209. }
  210. // Perform the onewire reset function.  We will wait up to 250uS for
  211. // the bus to come high, if it doesn't then it is broken or shorted
  212. // and we return a 0;
  213. //
  214. // Returns 1 if a device asserted a presence pulse, 0 otherwise.
  215. //
  216.  
  217. uint8_t OneWire::reset(void)
  218. {
  219.     uint8_t r;
  220.     uint8_t retries = 125;
  221.  
  222.     noInterrupts();
  223.     DIRECT_MODE_INPUT();
  224.     interrupts();
  225.     // wait until the wire is high... just in case
  226.     do {
  227.         if (--retries == 0) return 0;
  228.         delayMicroseconds(2);
  229.     } while ( !DIRECT_READ());
  230.  
  231.     noInterrupts();
  232.     DIRECT_WRITE_LOW();
  233.     DIRECT_MODE_OUTPUT();   // drive output low
  234.     interrupts();
  235.     delayMicroseconds(480);
  236.     noInterrupts();
  237.     DIRECT_MODE_INPUT();    // allow it to float
  238.     delayMicroseconds(70);
  239.     r = !DIRECT_READ();
  240.     interrupts();
  241.     delayMicroseconds(410);
  242.     return r;
  243. }
  244. void OneWire::write_bit(uint8_t v)
  245. {
  246.    
  247.  
  248.     if (v & 1) {
  249.         noInterrupts();
  250.         DIRECT_WRITE_LOW();
  251.         DIRECT_MODE_OUTPUT();   // drive output low
  252.         delayMicroseconds(10);
  253.         DIRECT_WRITE_HIGH();    // drive output high
  254.         interrupts();
  255.         delayMicroseconds(55);
  256.     } else {
  257.         noInterrupts();
  258.         DIRECT_WRITE_LOW();
  259.         DIRECT_MODE_OUTPUT();   // drive output low
  260.         delayMicroseconds(65);
  261.         DIRECT_WRITE_HIGH();    // drive output high
  262.         interrupts();
  263.         delayMicroseconds(5);
  264.     }
  265. }
  266.  
  267. //
  268. // Read a bit. Port and bit is used to cut lookup time and provide
  269. // more certain timing.
  270. //
  271. uint8_t OneWire::read_bit(void)
  272. {
  273.    
  274.     uint8_t r;
  275.  
  276.     noInterrupts();
  277.     DIRECT_MODE_OUTPUT();
  278.     DIRECT_WRITE_LOW();
  279.     delayMicroseconds(3);
  280.     DIRECT_MODE_INPUT();    // let pin float, pull up will raise
  281.     delayMicroseconds(10);
  282.     r = DIRECT_READ();
  283.     interrupts();
  284.     delayMicroseconds(53);
  285.     return r;
  286. }
  287.  
  288. //
  289. // Write a byte. The writing code uses the active drivers to raise the
  290. // pin high, if you need power after the write (e.g. DS18S20 in
  291. // parasite power mode) then set 'power' to 1, otherwise the pin will
  292. // go tri-state at the end of the write to avoid heating in a short or
  293. // other mishap.
  294. //
  295. void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
  296.     uint8_t bitMask;
  297.  
  298.     for (bitMask = 0x01; bitMask; bitMask <<= 1) {
  299.     OneWire::write_bit( (bitMask & v)?1:0);
  300.     }
  301.     if ( !power) {
  302.     noInterrupts();
  303.     DIRECT_MODE_INPUT();
  304.     DIRECT_WRITE_LOW();
  305.     interrupts();
  306.     }
  307. }
  308.  
  309. void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
  310.   for (uint16_t i = 0 ; i < count ; i++)
  311.     write(buf[i]);
  312.   if (!power) {
  313.     noInterrupts();
  314.     DIRECT_MODE_INPUT();
  315.     DIRECT_WRITE_LOW();
  316.     interrupts();
  317.   }
  318. }
  319.  
  320. //
  321. // Read a byte
  322. //
  323. uint8_t OneWire::read() {
  324.     uint8_t bitMask;
  325.     uint8_t r = 0;
  326.  
  327.     for (bitMask = 0x01; bitMask; bitMask <<= 1) {
  328.     if ( OneWire::read_bit()) r |= bitMask;
  329.     }
  330.     return r;
  331. }
  332.  
  333. void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
  334.   for (uint16_t i = 0 ; i < count ; i++)
  335.     buf[i] = read();
  336. }
  337.  
  338. //
  339. // Do a ROM select
  340. //
  341. void OneWire::select(const uint8_t rom[8])
  342. {
  343.     uint8_t i;
  344.  
  345.     write(0x55);           // Choose ROM
  346.  
  347.     for (i = 0; i < 8; i++) write(rom[i]);
  348. }
  349.  
  350. //
  351. // Do a ROM skip
  352. //
  353. void OneWire::skip()
  354. {
  355.     write(0xCC);           // Skip ROM
  356. }
  357.  
  358. void OneWire::depower()
  359. {
  360.     noInterrupts();
  361.     DIRECT_MODE_INPUT();
  362.     interrupts();
  363. }
  364.  
  365. #if ONEWIRE_SEARCH
  366.  
  367. //
  368. // You need to use this function to start a search again from the beginning.
  369. // You do not need to do it for the first search, though you could.
  370. //
  371. void OneWire::reset_search()
  372. {
  373.   // reset the search state
  374.   LastDiscrepancy = 0;
  375.   LastDeviceFlag = FALSE;
  376.   LastFamilyDiscrepancy = 0;
  377.   for(int i = 7; ; i--) {
  378.     ROM_NO[i] = 0;
  379.     if ( i == 0) break;
  380.   }
  381. }
  382.  
  383. // Setup the search to find the device type 'family_code' on the next call
  384. // to search(*newAddr) if it is present.
  385. //
  386. void OneWire::target_search(uint8_t family_code)
  387. {
  388.    // set the search state to find SearchFamily type devices
  389.    ROM_NO[0] = family_code;
  390.    for (uint8_t i = 1; i < 8; i++)
  391.       ROM_NO[i] = 0;
  392.    LastDiscrepancy = 64;
  393.    LastFamilyDiscrepancy = 0;
  394.    LastDeviceFlag = FALSE;
  395. }
  396.  
  397. //
  398. // Perform a search. If this function returns a '1' then it has
  399. // enumerated the next device and you may retrieve the ROM from the
  400. // OneWire::address variable. If there are no devices, no further
  401. // devices, or something horrible happens in the middle of the
  402. // enumeration then a 0 is returned.  If a new device is found then
  403. // its address is copied to newAddr.  Use OneWire::reset_search() to
  404. // start over.
  405. //
  406. // --- Replaced by the one from the Dallas Semiconductor web site ---
  407. //--------------------------------------------------------------------------
  408. // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
  409. // search state.
  410. // Return TRUE  : device found, ROM number in ROM_NO buffer
  411. //        FALSE : device not found, end of search
  412. //
  413. uint8_t OneWire::search(uint8_t *newAddr)
  414. {
  415.    uint8_t id_bit_number;
  416.    uint8_t last_zero, rom_byte_number, search_result;
  417.    uint8_t id_bit, cmp_id_bit;
  418.  
  419.    unsigned char rom_byte_mask, search_direction;
  420.  
  421.    // initialize for search
  422.    id_bit_number = 1;
  423.    last_zero = 0;
  424.    rom_byte_number = 0;
  425.    rom_byte_mask = 1;
  426.    search_result = 0;
  427.  
  428.    // if the last call was not the last one
  429.    if (!LastDeviceFlag)
  430.    {
  431.       // 1-Wire reset
  432.       if (!reset())
  433.       {
  434.          // reset the search
  435.          LastDiscrepancy = 0;
  436.          LastDeviceFlag = FALSE;
  437.          LastFamilyDiscrepancy = 0;
  438.          return FALSE;
  439.       }
  440.  
  441.       // issue the search command
  442.       write(0xF0);
  443.  
  444.       // loop to do the search
  445.       do
  446.       {
  447.          // read a bit and its complement
  448.          id_bit = read_bit();
  449.          cmp_id_bit = read_bit();
  450.  
  451.          // check for no devices on 1-wire
  452.          if ((id_bit == 1) && (cmp_id_bit == 1))
  453.             break;
  454.          else
  455.          {
  456.             // all devices coupled have 0 or 1
  457.             if (id_bit != cmp_id_bit)
  458.                search_direction = id_bit;  // bit write value for search
  459.             else
  460.             {
  461.                // if this discrepancy if before the Last Discrepancy
  462.                // on a previous next then pick the same as last time
  463.                if (id_bit_number < LastDiscrepancy)
  464.                   search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
  465.                else
  466.                   // if equal to last pick 1, if not then pick 0
  467.                   search_direction = (id_bit_number == LastDiscrepancy);
  468.  
  469.                // if 0 was picked then record its position in LastZero
  470.                if (search_direction == 0)
  471.                {
  472.                   last_zero = id_bit_number;
  473.  
  474.                   // check for Last discrepancy in family
  475.                   if (last_zero < 9)
  476.                      LastFamilyDiscrepancy = last_zero;
  477.                }
  478.             }
  479.  
  480.             // set or clear the bit in the ROM byte rom_byte_number
  481.             // with mask rom_byte_mask
  482.             if (search_direction == 1)
  483.               ROM_NO[rom_byte_number] |= rom_byte_mask;
  484.             else
  485.               ROM_NO[rom_byte_number] &= ~rom_byte_mask;
  486.  
  487.             // serial number search direction write bit
  488.             write_bit(search_direction);
  489.  
  490.             // increment the byte counter id_bit_number
  491.             // and shift the mask rom_byte_mask
  492.             id_bit_number++;
  493.             rom_byte_mask <<= 1;
  494.  
  495.             // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
  496.             if (rom_byte_mask == 0)
  497.             {
  498.                 rom_byte_number++;
  499.                 rom_byte_mask = 1;
  500.             }
  501.          }
  502.       }
  503.       while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7
  504.  
  505.       // if the search was successful then
  506.       if (!(id_bit_number < 65))
  507.       {
  508.          // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
  509.          LastDiscrepancy = last_zero;
  510.  
  511.          // check for last device
  512.          if (LastDiscrepancy == 0)
  513.             LastDeviceFlag = TRUE;
  514.  
  515.          search_result = TRUE;
  516.       }
  517.    }
  518.  
  519.    // if no device found then reset counters so next 'search' will be like a first
  520.    if (!search_result || !ROM_NO[0])
  521.    {
  522.       LastDiscrepancy = 0;
  523.       LastDeviceFlag = FALSE;
  524.       LastFamilyDiscrepancy = 0;
  525.       search_result = FALSE;
  526.    }
  527.    for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
  528.    return search_result;
  529.   }
  530.  
  531. #endif
  532.  
  533. #if ONEWIRE_CRC
  534. // The 1-Wire CRC scheme is described in Maxim Application Note 27:
  535. // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
  536. //
  537.  
  538.  
  539. //
  540. // Compute a Dallas Semiconductor 8 bit CRC directly.
  541. // this is much slower, but much smaller, than the lookup table.
  542. //
  543. uint8_t OneWire::crc8( uint8_t *addr, uint8_t len)
  544. {
  545.     uint8_t crc = 0;
  546.    
  547.     while (len--) {
  548.         uint8_t inbyte = *addr++;
  549.         for (uint8_t i = 8; i; i--) {
  550.             uint8_t mix = (crc ^ inbyte) & 0x01;
  551.             crc >>= 1;
  552.             if (mix) crc ^= 0x8C;
  553.             inbyte >>= 1;
  554.         }
  555.     }
  556.     return crc;
  557. }
  558. #endif
  559.  
  560. #if ONEWIRE_CRC16
  561. bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc)
  562. {
  563.     crc = ~crc16(input, len, crc);
  564.     return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
  565. }
  566.  
  567. uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
  568. {
  569.     static const uint8_t oddparity[16] =
  570.         { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
  571.  
  572.     for (uint16_t i = 0 ; i < len ; i++) {
  573.       // Even though we're just copying a byte from the input,
  574.       // we'll be doing 16-bit computation with it.
  575.       uint16_t cdata = input[i];
  576.       cdata = (cdata ^ crc) & 0xff;
  577.       crc >>= 8;
  578.  
  579.       if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
  580.           crc ^= 0xC001;
  581.  
  582.       cdata <<= 6;
  583.       crc ^= cdata;
  584.       cdata <<= 1;
  585.       crc ^= cdata;
  586.     }
  587.     return crc;
  588. }
  589. #endif
  590.  
  591.  
  592.  
  593.  
  594. OneWire one = OneWire(D3);
  595. uint8_t rom[8];
  596. uint8_t resp[9];
  597. void setup() {
  598. Serial1.begin(9600);
  599. one.reset();
  600. one.write(0x33);
  601. one.read_bytes(rom,8);
  602. Serial1.println("rom is:");
  603. for(int i=0;i<8;i++)
  604. {
  605.    Serial1.println(rom[i],HEX);
  606.    
  607. }
  608. }
  609.  
  610. void loop() {
  611.  
  612.  
  613. one.reset();
  614. one.write(0x55);
  615. one.write_bytes(rom,8);
  616. one.write(0x44);
  617. delay(10);
  618. one.reset();
  619. one.write(0x55);
  620. one.write_bytes(rom,8);
  621. one.write(0xBE);
  622. one.read_bytes(resp,9);
  623.  
  624. //Serial1.println("t ");
  625. //for(int i=0;i<9;i++)
  626. //{
  627. //   Serial1.println(resp[i],HEX);
  628.    
  629. //}
  630.  
  631.  byte MSB = resp[1];
  632.   byte LSB = resp[0];
  633.  
  634.   float tempRead = ((MSB << 8) | LSB); //using two's compliment
  635.   float TemperatureSum = tempRead / 16;
  636.   Serial1.print("Temp ");
  637.   Serial1.println(TemperatureSum);
  638.  
  639. delay(100);
  640. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement