⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 onewire.c

📁 基于AVR ATmega32 单片机的DS1820驱动程序 基于winavr 平台编译
💻 C
字号:
/************************************************************************/
/*                                                                      */
/*        Access Dallas 1-Wire Device with ATMEL AVRs                   */
/*                                                                      */
/*              Author: Peter Dannegger                                 */
/*                      danni@specs.de                                  */
/*                                                                      */
/* modified by Martin Thomas <eversmith@heizung-thomas.de> 9/2004       */
/************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>

#include "delay.h"
#include "onewire.h"

#ifdef OW_ONE_BUS

#define OW_GET_IN()   ( OW_IN & (1<<OW_PIN))
#define OW_OUT_LOW()  ( OW_OUT &= (~(1 << OW_PIN)) )
#define OW_OUT_HIGH() ( OW_OUT |= (1 << OW_PIN) )
#define OW_DIR_IN()   ( OW_DDR &= (~(1 << OW_PIN )) )
#define OW_DIR_OUT()  ( OW_DDR |= (1 << OW_PIN) )

#else

/* set bus-config with ow_set_bus() */
uint8_t OW_PIN_MASK; 
volatile uint8_t* OW_IN;
volatile uint8_t* OW_OUT;
volatile uint8_t* OW_DDR;

#define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
#define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
#define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
#define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
//#define OW_PIN2 PD6
//#define OW_DIR_IN2()   ( *OW_DDR &= ~(1 << OW_PIN2 ) )

void ow_set_bus(volatile uint8_t* in, volatile uint8_t* out, volatile uint8_t* ddr, uint8_t pin)
 { OW_DDR=ddr;
   OW_OUT=out;
   OW_IN=in;
   OW_PIN_MASK=(1<<pin);
   ow_reset();
 }

#endif

uint8_t ow_input_pin_state()
 { return OW_GET_IN();
 }

void ow_parasite_enable(void)
 { OW_OUT_HIGH();
   OW_DIR_OUT();
 }

void ow_parasite_disable(void)
 { OW_OUT_LOW();
   OW_DIR_IN();
 }

uint8_t ow_reset(void)
 { uint8_t err;
   uint8_t sreg;

   OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)
   OW_DIR_OUT(); // pull OW-Pin low for 480us

   delay_us(480);
   
   sreg=SREG;
   cli();

   // set Pin as input - wait for clients to pull low
   OW_DIR_IN(); // input

   delay_us(66);
   err = OW_GET_IN();		// no presence detect
   // nobody pulled to low, still high

   SREG=sreg; // sei()

   // after a delay the clients should release the line
   // and input-pin gets back to high due to pull-up-resistor
   delay_us(480-66);
   if( OW_GET_IN() == 0 )		// short circuit
      err = 1;

   return err;
 }

/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
   The master should sample at the end of the 15-slot after initiating
   the read-time-slot. The variable bus-settings need more
   cycles than the constant ones so the delays had to be shortened 
   to achive a 15uS overall delay 
   Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
   but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
uint8_t ow_bit_io( uint8_t b )
 { uint8_t sreg;

   sreg=SREG;
   cli();
	
   OW_DIR_OUT(); // drive bus low

   delay_us(1); // Recovery-Time wuffwuff was 1
   if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
	
   // wuffwuff delay was 15uS-1 see comment above
   delay_us(15-1-OW_CONF_DELAYOFFSET);
      
   if( OW_GET_IN() == 0 ) b = 0;  // sample at end of read-timeslot
	
   delay_us(60-15);
   OW_DIR_IN();

   SREG=sreg; // sei();
	
   return b;
 }


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_rd( void )
 { // read by sending 0xff (a dontcare?)
   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

   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 )                 // 11
               return OW_DATA_ERR;  // data error
          }
         else 
          { if( !b ) 
             { // 00 = 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
 }


void ow_command( uint8_t command, uint8_t *id )
 { 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

   ow_byte_wr( command );
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -