📄 onewirelib.c
字号:
//////////////////
// OneWireLib.c
// (C) 2004 Steve Childress stevech@san.rr.com
// NOTE: the test function at the bottom of this file can be
// omitted from the compilation of this library.
#include "OPEX.h"
// Define which bit on which port is one-wire
#define IODDR DDRA
#define OUTPORT PORTA
#define INPORT PINA
#define IOBIT 7
#define IOBITMASK 0x80
// this math works for CPU clocks 1MHz or more
// CPU clock at 6MHz so 1/f = 0.16uSec = 160 nsec
// 8MHz = 125ns
// 10Mhz = 100ns
// 16MHz = 62ns
const int xCLOCKS_PER_USEC = 1000 / 160; // 1000 nSec = 1uSec
#define FALSE 0
#define TRUE 1
extern char StringBuf1[];
// Externally useful routines
int OWReset(void); // TRUE if device(s) detected
void OWFamilySelect(unsigned char family_code);
int OWFirst(void);
int OWNext(void);
int OWVerify(void);
// internal OW routines
int OWSearch(void);
void OWTargetSetup(unsigned char family_code);
void OWFamilySkipSetup(void);
void OWWriteByte(unsigned char byte_value);
void OWWriteBit(unsigned char bit_value);
unsigned char OWReadBit(void);
unsigned char docrc8(unsigned char value);
////////////////////////
// Static
// global search state
unsigned char ROM_NO[8];
int LastDiscrepancy;
int LastFamilyDiscrepancy;
int LastDeviceFlag;
unsigned char crc8;
/////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------
// I/O PORT FUNCTIONS FOR ONE WIRE
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Reset the 1-Wire bus and return the presence of any device
// Reset is a 0 on the bus for at least 480uSec
// RETURN: state = 0 if no devices detected
////////////////////////////////////////////////
int OWReset(void)
{
register unsigned int n;
int ret = 0;
// create 480uSec reset pulse with CPU looping (oh my)
n = (xCLOCKS_PER_USEC * 480) / 3; // compile-time math
sbi(IODDR, IOBIT); // output mode
cbi(OUTPORT, IOBIT); // begin the reset, 0 to the bu
while (--n) // delay, 3 clocks per loop iteration
;
sbi(OUTPORT, IOBIT); // unreset
cbi(IODDR, IOBIT); // pin is an input
// now expect a presence pulse created by any connected 1-wire chip
n = 0;
while ((INPORT & IOBITMASK) == 0) // should go hi after RC chargeup, a few uSec
if (++n == 0)
goto err0;
n = 0;
while ((INPORT & IOBITMASK) != 0) // within 60uSec bus should go low, presence pulse
if (++n == 0)
goto err0;
n = 0;
while ((INPORT & IOBITMASK) == 0) // should go hi at end of 60-240us presence pulse
if (++n == 0)
goto err0;
ret = 1;
err0:
return(ret);
}
//--------------------------------------------------------------------------
// Send 8 bits of data to the 1-Wire bus
//
void OWWriteByte(unsigned char byte_value)
{
BYTE i;
sbi(IODDR, IOBIT); // output mode
cli(); // takes about 600 uSec for this loop
for (i = 1; i != 0; i <<= 1)
OWWriteBit( (byte_value & i) != 0 );
sei();
}
//--------------------------------------------------------------------------
// Send 1 bit of data to the 1-Wire bus
//
void OWWriteBit(unsigned char bit_value)
{
int n;
BYTE ie;
ie = SREG & 0x80;
cli();
sbi(IODDR, IOBIT); // output mode
cbi(OUTPORT, IOBIT); // start bit cell
n = (xCLOCKS_PER_USEC * 2) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
if (bit_value)
sbi(OUTPORT, IOBIT); // sending a 1
n = (xCLOCKS_PER_USEC * 70) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(OUTPORT, IOBIT);
n = (xCLOCKS_PER_USEC * 4) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
if (ie)
sei();
}
//--------------------------------------------------------------------------
// Read 1 bit of data from the 1-Wire bus
// Return 1 : bit read is 1
// 0 : bit read is 0
//
unsigned char OWReadBit()
{
BYTE b, ie;
register int n;
ie = SREG & 0x80;
cli();
sbi(IODDR, IOBIT); // make output
cbi(OUTPORT, IOBIT); // start bit cell
n = (xCLOCKS_PER_USEC * 10) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(OUTPORT, IOBIT); // for pull up
cbi(IODDR, IOBIT); // make input
n = (xCLOCKS_PER_USEC * 5) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
b = INPORT & IOBITMASK; // sample data
n = (xCLOCKS_PER_USEC * 60) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(IODDR, IOBIT); // make output, port bit is 1
n = (xCLOCKS_PER_USEC * 10) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
if (ie)
sei();
return(b != 0);
}
//--------------------------------------------------------------------------
unsigned char OWReadByte(void)
{
BYTE i, b = 0;
cli();
for (i = 8; i != 0; --i) {
b >>= 1;
if (OWReadBit() != 0)
b |= 0x80;
}
sei();
return b;
}
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------
// Find the 'first' devices on the 1-Wire bus
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : no device present
//
int OWFirst(void)
{
// reset the search state
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return(OWSearch());
}
//--------------------------------------------------------------------------
// Find the 'next' devices on the 1-Wire bus
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
int OWNext(void)
{
// leave the search state alone
return(OWSearch());
}
//--------------------------------------------------------------------------
// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
// search state.
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
int OWSearch(void)
{
unsigned char id_bit_number;
unsigned char id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction;
int last_zero, rom_byte_number, search_result;
// initialize for search
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
crc8 = 0;
// if the last call was not the last one
if (!LastDeviceFlag) {
// 1-Wire reset
if (!OWReset()) { // <<< do a bus reset
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
//OPEX_putline_P(PSTR("OWReset err"));
return FALSE;
}
// issue the search command
OWWriteByte(0xF0);
// loop to do the search
do {
// read a bit and its complement
id_bit = OWReadBit();
cmp_id_bit = OWReadBit();
// check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1)) // means no response from bus
break;
else {
// all devices coupled have 0 or 1
if (id_bit != cmp_id_bit)
search_direction = id_bit; // bit write value for search
else {
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy)
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -