/* Access Dallas 1-Wire Devices with ATMEL AVRs Author of the initial code: Peter Dannegger (danni(at)specs.de) modified by Martin Thomas (mthomas(at)rhrk.uni-kl.de) 9/2004 - use of delay.h, optional bus configuration at runtime 10/2009 - additional delay in ow_bit_io for recovery 5/2010 - timing modifcations, additonal config-values and comments, use of atomic.h macros, internal pull-up support 7/2010 - added method to skip recovery time after last bit transfered via ow_command_skip_last_recovery */ #include #include #include #include "onewire.h" #ifdef OW_ONE_BUS #define OW_GET_IN() ( OW_IN & (1< 1usec accoding to timing-diagramm if ( b ) { OW_DIR_IN(); // to write "1" release bus, resistor pulls high #if OW_USE_INTERNAL_PULLUP OW_OUT_HIGH(); #endif } // "Output data from the DS18B20 is valid for 15usec after the falling // edge that initiated the read time slot. Therefore, the master must // release the bus and then sample the bus state within 15ussec from // the start of the slot." _delay_us(15-2-OW_CONF_DELAYOFFSET); if( OW_GET_IN() == 0 ) { b = 0; // sample at end of read-timeslot } _delay_us(60-15-2+OW_CONF_DELAYOFFSET); #if OW_USE_INTERNAL_PULLUP OW_OUT_HIGH(); #endif OW_DIR_IN(); if ( with_parasite_enable ) { ow_parasite_enable(); } } /* ATOMIC_BLOCK */ _delay_us(OW_RECOVERY_TIME); // may be increased for longer wires return b; } uint8_t ow_bit_io( uint8_t b ) { return ow_bit_io_intern( b & 1, 0 ); } uint8_t ow_byte_wr( uint8_t b ) { uint8_t i = 8, j; do { j = ow_bit_io( b & 1 ); b >>= 1; if( j ) { b |= 0x80; } } while( --i ); return b; } uint8_t ow_byte_wr_with_parasite_enable( uint8_t b ) { uint8_t i = 8, j; do { if ( i != 1 ) { j = ow_bit_io_intern( b & 1, 0 ); } else { j = ow_bit_io_intern( b & 1, 1 ); } b >>= 1; if( j ) { b |= 0x80; } } while( --i ); return b; } uint8_t ow_byte_rd( void ) { // read by sending only "1"s, so bus gets released // after the init low-pulse in every slot return ow_byte_wr( 0xFF ); } uint8_t ow_rom_search( uint8_t diff, uint8_t *id ) { uint8_t i, j, next_diff; uint8_t b; if( ow_reset() ) { return OW_PRESENCE_ERR; // error, no device found <--- early exit! } ow_byte_wr( OW_SEARCH_ROM ); // ROM search command next_diff = OW_LAST_DEVICE; // unchanged on last device i = OW_ROMCODE_SIZE * 8; // 8 bytes do { j = 8; // 8 bits do { b = ow_bit_io( 1 ); // read bit if( ow_bit_io( 1 ) ) { // read complement bit if( b ) { // 0b11 return OW_DATA_ERR; // data error <--- early exit! } } else { if( !b ) { // 0b00 = 2 devices if( diff > i || ((*id & 1) && diff != i) ) { b = 1; // now 1 next_diff = i; // next pass 0 } } } ow_bit_io( b ); // write bit *id >>= 1; if( b ) { *id |= 0x80; // store bit } i--; } while( --j ); id++; // next byte } while( i ); return next_diff; // to continue search } static void ow_command_intern( uint8_t command, uint8_t *id, uint8_t with_parasite_enable ) { uint8_t i; ow_reset(); if( id ) { ow_byte_wr( OW_MATCH_ROM ); // to a single device i = OW_ROMCODE_SIZE; do { ow_byte_wr( *id ); id++; } while( --i ); } else { ow_byte_wr( OW_SKIP_ROM ); // to all devices } if ( with_parasite_enable ) { ow_byte_wr_with_parasite_enable( command ); } else { ow_byte_wr( command ); } } void ow_command( uint8_t command, uint8_t *id ) { ow_command_intern( command, id, 0); } void ow_command_with_parasite_enable( uint8_t command, uint8_t *id ) { ow_command_intern( command, id, 1 ); }