OneWire + DS18X20 Library
Basic functions for OneWire operations + specific DS18x20 operations
 All Functions Groups Pages
onewire.c
1 /*
2 onewire (tm) library V1.00
3 
4 copyright (c) Falk Brunner, 2016
5 
6 Released under GPLv3.
7 Please refer to LICENSE file for licensing information.
8 */
9 
10 #include <string.h>
11 #include <avr/io.h>
12 #include <avr/pgmspace.h>
13 #include <util/delay.h>
14 #include <avr/interrupt.h>
15 #include <util/atomic.h>
16 
17 #include "onewire.h"
18 
19 uint8_t onewire_reset(void) {
20  uint8_t err=0;
21 
22  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
23  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
24  _delay_us(480);
25  //ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
26  uint8_t sreg_tmp=SREG; cli(); // Arduino workaround :-0
27  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
28  _delay_us(66);
29  if( (ONEWIRE_PIN & ONEWIRE_MASK)) { // no presence pulse detect
30  err = 1;
31  }
32  //}
33  SREG = sreg_tmp; // Arduino workaround :-0
34 
35  _delay_us(480);
36  if( !(ONEWIRE_PIN & ONEWIRE_MASK)) { // bus short circuit to GND
37  err = 2;
38  }
39  return err;
40 }
41 
42 void onewire_write_bit(uint8_t wrbit) {
43 
44  //ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
45  uint8_t sreg_tmp=SREG; cli(); // Arduino workaround :-0
46  if (!(wrbit & 1)) {
47  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
48  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
49  _delay_us(95);
50  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
51  _delay_us(5);
52  } else {
53  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
54  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
55  _delay_us(10);
56  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
57  _delay_us(90);
58  }
59  //}
60  SREG = sreg_tmp; // Arduino workaround :-0
61 }
62 
63 uint8_t onewire_read_bit(void) {
64  uint8_t rebit;
65 
66  //ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
67  uint8_t sreg_tmp=SREG; cli(); // Arduino workaround :-0
68 
69  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
70  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
71  _delay_us(3);
72  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
73  _delay_us(10);
74  rebit = ONEWIRE_PIN & ONEWIRE_MASK; // read bit
75  _delay_us(87);
76  //}
77  SREG = sreg_tmp; // Arduino workaround :-0
78  if (rebit) {
79  return 1;
80  } else {
81  return 0;
82  }
83 }
84 
85 uint8_t onewire_read_byte(void) {
86  uint8_t data=0;
87  uint8_t i;
88 
89  for (i=0; i<8; i++) {
90  data >>= 1; // LSB first on OneWire
91  if (onewire_read_bit()) {;
92  data |= 0x80;
93  }
94  }
95  return data;
96 }
97 
98 void onewire_write_byte(uint8_t data) {
99  uint8_t i;
100 
101  for (i=0; i<8; i++) {
102  // LSB first on OneWire
103  // no need for masking, LSB is masked inside function
104  onewire_write_bit(data);
105  data >>= 1;
106  }
107 }
108 
109 void onewire_search_init(uint8_t buffer[8]) {
110  memset(buffer, 0, 8);
111  onewire_search(NULL, 0);
112 }
113 
114 uint8_t onewire_search_rom(uint8_t buffer[8]) {
115  return onewire_search(buffer, ONEWIRE_SEARCH_ROM);
116 }
117 
118 uint8_t onewire_alarm_search(uint8_t buffer[8]) {
119  return onewire_search(buffer, ONEWIRE_ALARM_SEARCH);
120 }
121 
122 uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd) {
123  uint8_t mask, i, j, bit, rom_tmp;
124  uint8_t max_conf_zero=0; // last bit conflict that was resolved to zero
125  static uint8_t max_conf_old; // last bit conflict that was resolved to zero in last scan
126  uint8_t branch_flag=0; // indicate new scan branch, new ROM code found
127 
128  if (buffer == NULL) { // init search
129  max_conf_old=64;
130  return 0;
131  }
132 
133  if (onewire_reset()) {
134  return 1; // no response
135  } else {
136  onewire_write_byte(cmd);
137  rom_tmp = buffer[0];
138  i=0;
139  mask=1;
140  // scan all 64 ROM bits
141  for(j=0; j<64; j++) {
142  bit = onewire_read_bit(); // bit
143  bit |= onewire_read_bit()<<1; // inverted bit
144 
145  switch(bit) {
146  case 0: // bit conflict, more than one device with different bit
147  if (j < max_conf_old) { // below last zero branch conflict level, keep current bit
148  if (rom_tmp & mask) { // last bit was 1
149  bit = 1;
150  } else { // last bit was 0
151  bit = 0;
152  max_conf_zero = j;
153  branch_flag = 1;
154  }
155  } else if (j == max_conf_old) { // last zero branch conflict, now enter new path
156  bit = 1;
157  } else { // above last run conflict level
158  bit = 0; // scan 0 branch first
159  max_conf_zero = j;
160  branch_flag = 1;
161  }
162  break;
163 
164  case 1:
165  // no break
166 
167  case 2: // no bit conflict
168  // do nothing, just go on with current bit
169  break;
170 
171  case 3: // no response, error
172  return 3;
173  break;
174  }
175 
176  // write bit to OneWire and store code
177 
178  if (bit & 1) {
180  rom_tmp |= mask;
181  } else {
183  rom_tmp &= ~mask;
184  }
185 
186  mask <<= 1;
187  if (mask == 0) {
188  mask = 1;
189  buffer[i] = rom_tmp; // update tmp data
190  i++;
191  if (i<8) {
192  rom_tmp = buffer[i]; // read new data
193  }
194  }
195  }
196  }
197 
198  max_conf_old = max_conf_zero;
199 
200  if (branch_flag) {
201  return 0; // new code found
202  } else {
203  return 4; // no new code found
204  }
205 
206 }
207 
208 uint8_t onewire_match_rom(const uint8_t rom[8]) {
209  uint8_t mask, tmp=0, i, j;
210 
211  if (onewire_reset()) {
212  return 1; // no response
213  } else {
214  onewire_write_byte(ONEWIRE_MATCH_ROM);
215  mask=0;
216  i=0;
217  for (j=0; j<64; j++) {
218  mask <<= 1;
219  if (mask == 0) {
220  mask = 1;
221  tmp = rom[i];
222  i++;
223  }
224 
225  if (tmp & mask) {
226  onewire_write_bit(1); // branch 1
227  } else {
228  onewire_write_bit(0); // branch 0
229  }
230 
231  }
232  }
233  return 0;
234 }
235 
236 uint8_t onewire_skip_rom(void) {
237  if (onewire_reset()) {
238  return 1; // no response
239  } else {
240  onewire_write_byte(ONEWIRE_SKIP_ROM);
241  }
242  return 0;
243 }
244 
245 uint8_t onewire_read_rom(uint8_t rom[8]) {
246  uint8_t mask=1, tmp=0, i=0, j;
247 
248  if (onewire_reset()) {
249  return 1; // no response
250  } else {
251  onewire_write_byte(ONEWIRE_READ_ROM);
252  for (j=0; j<64; j++) {
253  if (onewire_read_bit()) {
254  tmp |= mask;
255  }
256 
257  mask <<= 1;
258  if (mask == 0) {
259  mask = 1;
260  rom[i]=tmp;
261  tmp=0;
262  i++;
263  }
264  }
265 
266  if(onewire_crc(rom, 8)) {
267  return 2; // CRC error
268  }
269  }
270  return 0;
271 }
272 
273 /*-----------------------------------------------------------------------------
274 
275  calculate CRC over data array
276  nibble wide processing, ~3x faster than serial version
277  CRC calculation of 8 Bytes takes ~0.3ms@1MHz
278 
279  CRC polynon is x^8 + x^5 + x^4 + 1 = 0x8C
280  Attention! This CRC is reversed, CRC is shifted right with new data
281  comming in at the MSB! That's why the polynom is mirrored!
282 
283  return: CRC
284 
285  usage:
286 
287  check CRC of received data:
288 
289  When the array includes the received CRC (last byte), the calculated CRC
290  will be zero if no transmission error took place.
291 
292  When the array does not include the received CRC, the byte after the
293  last valid data must be zero. The calculated CRC will be returned and must
294  be compared to the received CRC.
295 
296  generate CRC for transmit data:
297 
298  When a CRC for transmission is to be calculated, add a zero after the last
299  valid data and copy the CRC value there after this functions returns.
300 
301 -----------------------------------------------------------------------------*/
302 
303 uint8_t onewire_crc(const uint8_t *data, uint8_t cnt) {
304  static const uint8_t crc_table[16] PROGMEM =
305  {0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
306  0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74};
307 
308  uint8_t crc, i, tmp;
309 
310  // nibble based CRC calculation,
311  // good trade off between speed and memory usage
312 
313  // first byte is not changed, since CRC is initialized with 0
314  crc = *data++;
315  cnt--;
316 
317  for(; cnt>0; cnt--) {
318  tmp = *data++; // next byte
319 
320  i = crc & 0x0F;
321  crc = (crc >> 4) | (tmp << 4); // shift in next nibble
322  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
323 
324  i = crc & 0x0F;
325  crc = (crc >> 4) | (tmp & 0xF0); // shift in next nibble
326  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
327  }
328 
329  return crc;
330 }
331 
uint8_t onewire_reset(void)
OneWire reset.
Definition: onewire.c:19
uint8_t onewire_match_rom(const uint8_t rom[8])
select device on bus
Definition: onewire.c:208
void onewire_write_byte(uint8_t data)
write one byte
Definition: onewire.c:98
uint8_t onewire_read_rom(uint8_t rom[8])
read ROM of device
Definition: onewire.c:245
void onewire_search_init(uint8_t buffer[8])
init rom search buffer and internal variables
Definition: onewire.c:109
uint8_t onewire_crc(const uint8_t *data, uint8_t cnt)
calculate CRC over data array, fast version, 0.3ms for 8 bytes @1MHz
Definition: onewire.c:303
void onewire_write_bit(uint8_t wrbit)
write one bit to bus
Definition: onewire.c:42
uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd)
scan OneWire bus for normal ROM or alarm search
Definition: onewire.c:122
uint8_t onewire_skip_rom(void)
select device on bus
Definition: onewire.c:236
uint8_t onewire_read_bit(void)
read one bit from bus
Definition: onewire.c:63
uint8_t onewire_read_byte(void)
read one byte
Definition: onewire.c:85
uint8_t onewire_alarm_search(uint8_t buffer[8])
scan OneWire bus for devices with active alarm flag
Definition: onewire.c:118
uint8_t onewire_search_rom(uint8_t buffer[8])
scan OneWire bus for ROMs
Definition: onewire.c:114