1-Wire tester, shows ROM code and temperature on an LCD screen

onewire.c 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include "iopins.h"
  6. #include "onewire.h"
  7. /** Perform bus reset. Returns true if any device is connected */
  8. bool ow_reset(const uint8_t pin)
  9. {
  10. as_output_n(pin);
  11. pin_down_n(pin);
  12. _delay_us(480);
  13. as_input_pu_n(pin);
  14. _delay_us(70);
  15. const bool a = ! pin_read_n(pin);
  16. _delay_us(410);
  17. return a;
  18. }
  19. /** Send a single bit */
  20. void _ow_tx_bit(const uint8_t pin, const bool bit)
  21. {
  22. as_output_n(pin);
  23. pin_down_n(pin);
  24. if (bit)
  25. {
  26. _delay_us(6);
  27. as_input_pu_n(pin);
  28. _delay_us(64);
  29. }
  30. else
  31. {
  32. _delay_us(60);
  33. as_input_pu_n(pin);
  34. _delay_us(10);
  35. }
  36. }
  37. /** Send a single byte */
  38. void ow_write(const uint8_t pin, const uint8_t byte)
  39. {
  40. for (uint8_t i = 0; i < 8; i++)
  41. {
  42. _ow_tx_bit(pin, (byte >> i) & 0x01);
  43. }
  44. }
  45. /** Read a single bit */
  46. bool _ow_rx_bit(const uint8_t pin)
  47. {
  48. as_output_n(pin);
  49. pin_down_n(pin);
  50. _delay_us(6);
  51. as_input_pu_n(pin);
  52. _delay_us(9);
  53. const bool a = pin_read_n(pin);
  54. _delay_us(55);
  55. return a;
  56. }
  57. /** Read a single byte */
  58. uint8_t ow_read(const uint8_t pin)
  59. {
  60. uint8_t byte = 0;
  61. for (uint8_t i = 0; i < 8; i++)
  62. {
  63. byte = (byte >> 1) | (_ow_rx_bit(pin) << 7);
  64. }
  65. return byte;
  66. }
  67. /** Wait until the device is ready. Returns false on timeout */
  68. bool ow_wait_ready(const uint8_t pin)
  69. {
  70. uint16_t timeout = 700;
  71. as_input_pu_n(pin);
  72. while (--timeout > 0)
  73. {
  74. if (pin_is_high_n(pin)) return true;
  75. _delay_ms(1);
  76. }
  77. return false;
  78. }
  79. /** Read bytes into an array */
  80. void ow_read_arr(const uint8_t pin, uint8_t* array, const uint8_t count)
  81. {
  82. for (uint8_t i = 0; i < count; i++)
  83. {
  84. array[i] = ow_read(pin);
  85. }
  86. }
  87. // ---------- CRC utils ----------
  88. /*
  89. Dallas 1-wire CRC routines for Arduino with examples of usage.
  90. The 16-bit routine is new.
  91. The 8-bit routine is from http://github.com/paeaetech/paeae/tree/master/Libraries/ds2482/
  92. Copyright (C) 2010 Kairama Inc
  93. This program is free software: you can redistribute it and/or modify
  94. it under the terms of the GNU General Public License as published by
  95. the Free Software Foundation, either version 3 of the License, or
  96. (at your option) any later version.
  97. This program is distributed in the hope that it will be useful,
  98. but WITHOUT ANY WARRANTY; without even the implied warranty of
  99. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  100. GNU General Public License for more details.
  101. You should have received a copy of the GNU General Public License
  102. along with this program. If not, see <http://www.gnu.org/licenses/>.
  103. */
  104. // Dallas 1-wire 16-bit CRC calculation. Developed from Maxim Application Note 27.
  105. /** Compute a CRC16 checksum */
  106. uint16_t crc16(uint8_t *data, uint8_t len)
  107. {
  108. uint16_t crc = 0;
  109. for (uint8_t i = 0; i < len; i++)
  110. {
  111. uint8_t inbyte = data[i];
  112. for (uint8_t j = 0; j < 8; j++)
  113. {
  114. uint8_t mix = (crc ^ inbyte) & 0x01;
  115. crc = crc >> 1;
  116. if (mix)
  117. crc = crc ^ 0xA001;
  118. inbyte = inbyte >> 1;
  119. }
  120. }
  121. return crc;
  122. }
  123. // The 1-Wire CRC scheme is described in Maxim Application Note 27:
  124. // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
  125. /** Compute a CRC8 checksum */
  126. uint8_t crc8(uint8_t *addr, uint8_t len)
  127. {
  128. uint8_t crc = 0;
  129. for (uint8_t i = 0; i < len; i++)
  130. {
  131. uint8_t inbyte = addr[i];
  132. for (uint8_t j = 0; j < 8; j++)
  133. {
  134. uint8_t mix = (crc ^ inbyte) & 0x01;
  135. crc >>= 1;
  136. if (mix)
  137. crc ^= 0x8C;
  138. inbyte >>= 1;
  139. }
  140. }
  141. return crc;
  142. }
  143. // --- utils for DS1820 ---
  144. /** Read temperature in 0.0625°C */
  145. int16_t ds18s20_read_temp(uint8_t pin)
  146. {
  147. ow_write(pin, READ_SCRATCHPAD);
  148. uint8_t bytes[9];
  149. ow_read_arr(pin, bytes, 9);
  150. uint8_t crc = crc8(bytes, 8);
  151. if (crc != bytes[8])
  152. {
  153. return TEMP_ERROR;
  154. }
  155. else
  156. {
  157. int16_t a = ((bytes[1] << 8) | bytes[0]) >> 1;
  158. a = a << 4;
  159. a += (16 - bytes[6]) & 0x0F;
  160. a -= 0x04;
  161. return a;
  162. }
  163. }
  164. int16_t conv0_0625to0_1(int32_t temp) {
  165. temp *= 625;
  166. uint16_t rem = temp % 1000;
  167. temp /= 1000;
  168. if (rem >= 500) temp++;
  169. return (int16_t) temp;
  170. }
  171. /** Read temperature in 0.1°C, or TEMP_ERROR on error */
  172. int16_t ds18s20_read_temp_c(uint8_t pin)
  173. {
  174. int16_t value = ds18s20_read_temp(pin);
  175. if (value == TEMP_ERROR) return TEMP_ERROR;
  176. return conv0_0625to0_1(value);
  177. }
  178. /** Read temperature in 0.0625°C */
  179. uint16_t ds18b20_read_temp(uint8_t pin)
  180. {
  181. ow_write(pin, READ_SCRATCHPAD);
  182. uint8_t bytes[9];
  183. ow_read_arr(pin, bytes, 9);
  184. uint8_t crc = crc8(bytes, 8);
  185. if (crc != bytes[8]) {
  186. return TEMP_ERROR;
  187. }
  188. int32_t value = bytes[0] | ((bytes[1] & 0x7) << 8); // value in 0.0625
  189. if (bytes[1] & 0x80) {
  190. value = -value;
  191. }
  192. if (value == 0x0550) {
  193. return TEMP_ERROR;
  194. }
  195. return value;
  196. }
  197. /** Read temperature in 0.1°C, or TEMP_ERROR on error */
  198. int16_t ds18b20_read_temp_c(uint8_t pin)
  199. {
  200. int16_t value = ds18b20_read_temp(pin);
  201. if (value == TEMP_ERROR) return TEMP_ERROR;
  202. return conv0_0625to0_1(value);
  203. }
  204. bool ds18x20_single_measure(uint8_t pin)
  205. {
  206. ow_reset(pin);
  207. ow_write(pin, SKIP_ROM);
  208. ow_write(pin, CONVERT_T);
  209. if (!ow_wait_ready(pin))
  210. {
  211. return false;
  212. }
  213. ow_reset(pin);
  214. ow_write(pin, SKIP_ROM);
  215. return true;
  216. }