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

📄 dallas_bitbang.c

📁 国外牛人公开的AVR代码
💻 C
字号:
//*****************************************************************************
// File Name	: dallas.c
// Title		: Dallas 1-Wire Library
// Revision		: 6
// Notes		: 
// Target MCU	: Atmel AVR series
// Editor Tabs	: 4
// 
//*****************************************************************************
 
//----- Include Files ---------------------------------------------------------
#include <avr/io.h>				// include I/O definitions (port names, pin names, etc)
#include <avr/interrupt.h>		// include interrupt support
#include <string.h>				// include string support
#include "rprintf.h"			// include rprintf function library
#include "timer128.h"			// include timer function library
#include "dallas.h"				// include dallas support

//----- Global Variables -------------------------------------------------------
static u08 last_discrep = 0;	// last discrepancy for FindDevices
static u08 done_flag = 0;		// done flag for FindDevices

u08 dallas_crc;					// current crc global variable
u08 dallas_crc_table[] =		// dallas crc lookup table
{
	0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
	157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
	35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
	190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
	70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
	219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
	101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
	248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
	140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
	17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
	175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
	50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
	202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
	87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
	233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
	116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
};

//----- Functions --------------------------------------------------------------

/*--------------------------------------------------------------------------
 * dallasFindNextDevice: find the next device on the bus
 * input................ rom_id - pointer to store the rom id found
 * returns.............. true or false if a device was found
 *-------------------------------------------------------------------------*/
u08 dallasFindNextDevice(dallas_rom_id_T* rom_id);

void dallasDelayUs(u16 us)
{
	while(us--) // 6 cycles
	{
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
	} // loop jump 2 cycles
}

void dallasInit(void)
{
}

u08 dallasReset(void)
{
	u08 presence = DALLAS_PRESENCE;

	cli();
	
	// pull line low
	sbi(DALLAS_DDR, DALLAS_PIN);
	cbi(DALLAS_PORT, DALLAS_PIN);
	
	// wait for presence
	dallasDelayUs(480);
	
	// allow line to return high
	cbi(DALLAS_DDR, DALLAS_PIN);
	sbi(DALLAS_PORT, DALLAS_PIN);
	
	// wait for presence
	dallasDelayUs(70);

	// if device is not present, pin will be 1
	if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN)
		presence = DALLAS_NO_PRESENCE;

	// wait for end of timeslot
	dallasDelayUs(410);

	sei();

	// now that we have reset, let's check bus health
	// it should be noted that a delay may be needed here for devices that
	// send out an alarming presence pulse signal after a reset
	cbi(DALLAS_DDR, DALLAS_PIN);
	sbi(DALLAS_PORT, DALLAS_PIN);
	//dallasDelayUs(200);
	if (!(inb(DALLAS_PORTIN) & (0x01<<DALLAS_PIN)))	// it should be pulled up to high
		return DALLAS_BUS_ERROR;

	return presence;
}

u08 dallasReadBit(void)
{
	u08 bit = 0;
	
	// pull line low to start timeslot
	sbi(DALLAS_DDR, DALLAS_PIN);
	cbi(DALLAS_PORT, DALLAS_PIN);
	
	// delay appropriate time
	dallasDelayUs(6);

	// release the bus
	cbi(DALLAS_DDR, DALLAS_PIN);
	sbi(DALLAS_PORT, DALLAS_PIN);
	
	// delay appropriate time	
	dallasDelayUs(9);

	// read the pin and set the variable to 1 if the pin is high
	if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN)
		bit = 1;
	
	// finish read timeslot
	dallasDelayUs(55);
	
	return bit;
}

void dallasWriteBit(u08 bit)
{
	// drive bus low
	sbi(DALLAS_DDR, DALLAS_PIN);
	cbi(DALLAS_PORT, DALLAS_PIN);
	
	// delay the proper time if we want to write a 0 or 1
	if (bit)
		dallasDelayUs(6);
	else
		dallasDelayUs(60);

	// release bus
	cbi(DALLAS_DDR, DALLAS_PIN);
	sbi(DALLAS_PORT, DALLAS_PIN);

	// delay the proper time if we want to write a 0 or 1
	if (bit)
		dallasDelayUs(64);
	else
		dallasDelayUs(10);
}

u08 dallasReadByte(void)
{
	u08 i;
	u08 byte = 0;

	cli();
	
	// read all 8 bits
	for(i=0;i<8;i++)
	{
		if (dallasReadBit())
			byte |= 0x01<<i;

		// allow a us delay between each read
		dallasDelayUs(1);
	}

	sei();

	return byte;
}

void dallasWriteByte(u08 byte)
{
	u08 i;

	cli();

	// write all 8 bits
	for(i=0;i<8;i++)
	{
		dallasWriteBit((byte>>i) & 0x01);
		
		// allow a us delay between each write
		dallasDelayUs(1);
	}
	
	sei();
}

u08 dallasReadRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08 *data)
{
	u08 i;
	u08 error;

	union int16_var_U
	{
		u16 i16;
		u08 i08[2];
	} int16_var;

	// first make sure we actually have something to do
	if (data == NULL)
		return DALLAS_NULL_POINTER;
	if (len == 0)
		return DALLAS_ZERO_LEN;

	// reset the bus and request the device
	error = dallasMatchROM(rom_id);
	if (error != DALLAS_NO_ERROR)
		return error;
	
	// enter read mode
	dallasWriteByte(DALLAS_READ_MEMORY);
	
	// write address one byte at a time
	int16_var.i16 = addr;
	dallasWriteByte(int16_var.i08[0]);
	dallasWriteByte(int16_var.i08[1]);
	
	// read data from device 1 byte at a time
	for(i=0;i<len;i++)
		data[i] = dallasReadByte();

	return DALLAS_NO_ERROR;
}

u08 dallasWriteRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08* data)
{
	u08 i;
	u08 error;

	union int16_var_U
	{
		u16 i16;
		u08 i08[2];
	} int16_var;

	// first make sure we actually have something to do
	if (data == NULL)
		return DALLAS_NULL_POINTER;
	if (len == 0)
		return DALLAS_ZERO_LEN;

	// reset the bus and request the device
	error = dallasMatchROM(rom_id);
	if (error != DALLAS_NO_ERROR)
		return error;
	
	// enter write mode
	dallasWriteByte(DALLAS_WRITE_MEMORY);

	// write address one byte at a time
	int16_var.i16 = addr;
	dallasWriteByte(int16_var.i08[0]);
	dallasWriteByte(int16_var.i08[1]);
	
	// write data one byte at a time
	for(i=0;i<len;i++)
	{
		dallasWriteByte(data[i]);
		
		// future: Check CRC16, for now just read it so we can go on
		dallasReadByte();
		dallasReadByte();

		// verify the data
		if (dallasReadByte() != data[i])
			return DALLAS_VERIFY_ERROR;
	}

	return DALLAS_NO_ERROR;
}

void dallasWaitUntilDone(void)
{
	//timerPause(6);
	
	// wait until we recieve a one
	cli();
	while(!dallasReadBit());
	sei();
}

u08 dallasReadROM(dallas_rom_id_T* rom_id)
{
	u08 i;

	// reset the 1-wire bus and look for presence
	i = dallasReset();
	if (i != DALLAS_PRESENCE)
		return i;
	
	// send READ ROM command
	dallasWriteByte(DALLAS_READ_ROM);

	// get the device's ID 1 byte at a time
	for(i=0;i<8;i++)
		rom_id->byte[i] = dallasReadByte();

	return DALLAS_NO_ERROR;
}

u08 dallasMatchROM(dallas_rom_id_T* rom_id)
{
	u08 i;

	// reset the 1-wire and look for presence
	i = dallasReset();
	if (i != DALLAS_PRESENCE)
		return i;

	// send MATCH ROM command
	dallasWriteByte(DALLAS_MATCH_ROM);

	// write id one byte at a time
	for(i=0;i<8;i++)
		dallasWriteByte(rom_id->byte[i]);

	return DALLAS_NO_ERROR;
}

void dallasPrintROM(dallas_rom_id_T* rom_id)
{
	s08 i;

	// print out the rom in the format: xx xx xx xx xx xx xx xx
	for(i=7;i>=0;i--)
	{
		rprintfu08(rom_id->byte[i]);
		rprintfChar(' ');
	}

	// print out the rom in the format: 0xXXXXXXXXXXXXXXXX
	rprintfProgStrM(" (0x");
	for(i=7;i>=0;i--)
	{
		rprintfu08(rom_id->byte[i]);
	}
	rprintfProgStrM("ULL)");

}

u08 dallasAddressCheck(dallas_rom_id_T* rom_id, u08 family)
{
//	u08 i;

//	dallas_crc = 0;
	
//	for(i=1;i<7;i++)
//	{
//		dallasCRC(rom_id->byte[i]);
//		rprintfu08(rom_id->byte[i]);
//		rprintfChar(' ');
//	}
//	rprintfCRLF();

//	rprintfu08(dallas_crc);
//	rprintfCRLF();
	
	//run CRC on address

	//make sure we have the correct family
	if (rom_id->byte[DALLAS_FAMILY_IDX] == family)
		return DALLAS_NO_ERROR;
	
	return DALLAS_ADDRESS_ERROR;
}

u08 dallasCRC(u08 i)
{
	// update the crc global variable and return it
	dallas_crc = dallas_crc_table[dallas_crc^i];
	return dallas_crc;
}

u08 dallasFindDevices(dallas_rom_id_T rom_id[])
{
	u08 num_found = 0;
	dallas_rom_id_T id;

	// reset the rom search last discrepancy global
	last_discrep = 0;
	done_flag = FALSE;

	// check to make sure presence is detected before we start
	if (dallasReset() == DALLAS_PRESENCE)
	{
		// --> stang
		//while (dallasFindNextDevice(&rom_id[num_found]) && (num_found<DALLAS_MAX_DEVICES))
		//	num_found++;
		
		// continues until no additional devices are found
		while (dallasFindNextDevice(&id) && (num_found<DALLAS_MAX_DEVICES))
			memcpy(&rom_id[num_found++], &id, 8);
	}

	return num_found;
}

u08 dallasFindNextDevice(dallas_rom_id_T* rom_id)
{
	u08 bit;
	u08 i = 0;
	u08 bit_index = 1;
	u08 byte_index = 0;
	u08 bit_mask = 1;
	u08 discrep_marker = 0;
	
	// reset the CRC
	dallas_crc = 0;

	if (done_flag || dallasReset() != DALLAS_PRESENCE)
	{
		// no more devices parts detected
		return FALSE;
	}

	// send search ROM command
	dallasWriteByte(DALLAS_SEARCH_ROM);
	
	// loop until through all 8 ROM bytes
	while(byte_index<8)
	{
		// read line 2 times to determine status of devices
		//    00 - devices connected to bus with conflicting bits
		//    01 - all devices have a 0 in this position
		//    10 - all devices ahve a 1 in this position
		//    11 - there are no devices connected to bus
		i = 0;
		cli();
		if (dallasReadBit())
			i = 2;				// store the msb if 1
		dallasDelayUs(120);
		if (dallasReadBit())
			i |= 1;				// store the lsb if 1
		sei();
		
		if (i==3)
		{
			// there are no devices on the 1-wire
			break;
		}
		else
		{
			if (i>0)
			{
				// all devices coupled have 0 or 1
				// shift 1 to determine if the msb is 0 or 1
				bit = i>>1;
			}
			else
			{
				// if this discrepancy is before the last discrepancy on a
				// previous FindNextDevice then pick the same as last time
				if (bit_index<last_discrep)
					bit = ((rom_id->byte[byte_index] & bit_mask) > 0);
				else
					bit = (bit_index==last_discrep);
				
				// if 0 was picked then record position with bit mask
				if (!bit)
					discrep_marker = bit_index;
			}

			// isolate bit in rom_id->byte[byte_index] with bit mask
			if (bit)
				rom_id->byte[byte_index] |= bit_mask;
			else
				rom_id->byte[byte_index] &= ~bit_mask;

			// ROM search write
			cli();
			dallasWriteBit(bit);
			sei();

			// ncrement bit index counter and shift the bit mask
			bit_index++; 
			bit_mask <<= 1;
			
			if (!bit_mask)
			{
				// if the mask is 0 then go to new ROM
				// accumulate the CRC and incriment the byte index and bit mask
				dallasCRC(rom_id->byte[byte_index]);
				byte_index++;
				bit_mask++;
			}
		}
	}

	if ((bit_index < 65) || dallas_crc)
	{
		// search was unsuccessful - reset the last discrepancy to 0 and return false
		last_discrep = 0;
		return FALSE;
	}

	// search was successful, so set last_discrep and done_flag
	last_discrep = discrep_marker;
	done_flag = (last_discrep==0);

	return TRUE;
}

void dallasPrintError(u08 error)
{
	// if there was not an error, return
	if (error == DALLAS_NO_ERROR)
		return;
	
	// print header message
	rprintfProgStrM("ERROR ");
	rprintfChar(error);
	rprintfProgStrM(": ");

	// print custom error message
	switch (error)
	{
		case DALLAS_NO_PRESENCE:
			rprintfProgStrM("no presence detected");
			break;
		case DALLAS_INVALID_CHANNEL:
			rprintfProgStrM("Invalid Chan");
			break;
		case DALLAS_VERIFY_ERROR:
			rprintfProgStrM("Verify");
			break;
		case DALLAS_ADDRESS_ERROR:
			rprintfProgStrM("Bad Addr");
			break;
		case DALLAS_CRC_ERROR:
			rprintfProgStrM("Data CRC");	
			break;
		case DALLAS_DEVICE_ERROR:
			rprintfProgStrM("No response");
			break;
		case DALLAS_FORMAT_ERROR:
			rprintfProgStrM("Bad return format");
			break;
		case DALLAS_NULL_POINTER:
			rprintfProgStrM("Null Pointer");
			break;
		case DALLAS_ZERO_LEN:
			rprintfProgStrM("RAM rd/wr 0 bytes");
			break;
		case DALLAS_BUS_ERROR:
			rprintfProgStrM("Bus error, check pullup");
			break;
		case DALLAS_RESOLUTION_ERROR:
			rprintfProgStrM("resolution out of range");
			break;
		default:
			rprintfProgStrM("Unknown");
	}
	rprintfCRLF();
}

⌨️ 快捷键说明

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