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

📄 ds18b20.c

📁 这是一个远程温度计 MCU: AT89S52 温度传感器: DS18B20 晶振: 12MHz 使用串口连接,在PC端使用"超级终端"打开 设置如下: 波特率: 4800 数据
💻 C
字号:
#include <reg52.h>
#include <stdio.h>
#include "type.h"
#include "intrins.h"
#include "ds18b20.h"
#define CRC_METHOD	0		// 0 for none, 1 for table match, 2 for calculate
#define GET_TEMP_CALC_METHOD 0	// 0 for table match, 1 for float point

//中断服务程序执行时间长时,关中断必须使用,
//以下用于去掉所有的关中断操作
#undef ENABLE
#undef DISABLE
#define ENABLE()
#define DISABLE()

/*
运行在12时钟模式,机器晶振为12.000MHz,
其它环境,延时函数需作相应的调整
*/

#define Delay1us(void) _nop_()

/**********************************************************
** 延时,Fosc = 12Mhz时,以5us为倍数
** 参数: multiple
**      1 : 256 * 5 + 5 = 1285us
**      0 : 255 * 5 + 5 = 1280us 
**      n : 5 * n us (2<= n <=255)
**********************************************************/
static void Delay5us(uchar multiple)
{
	--multiple;
	do {
		_nop_();
		_nop_();
		_nop_();
	} while (--multiple != 0);
}



/*static void Delay10ms(uchar delay)
{
	uint i;

	for (; delay > 0; delay--) {
		for (i = 1110; i > 0; i--)
			_nop_();
	}
}
*/

//--------------DS18B20测温集成电路驱动------------------
#define IOPORT		DS18B20_IOPORT
#define _T_CONV		200	//ms
#define _T_SLOT		60	//us
#define _T_REC		1	//us
#define _T_WRITE_LOW0	60	//us
#define _T_WRITE_LOW1	10	//us
#define	_T_RDV		10	//us
#define _T_RESET_HIGH	480	//us
#define _T_RESET_LOW	480	//us
#define _T_PD_HIGH	15	//us
#define _T_PD_LOW	60	//us

// after a device reset
#define CMD_READ_ROM	0x33
#define CMD_MATCH_ROM	0x55
#define CMD_SKIP_ROM	0xCC
#define CMD_SEARCH_ROM	0xF0
#define CMD_ALARM_ROM	0xEC

// after a rom command
#define CMD_CONVERT_T	0x44
#define CMD_READ_SCRATCH  0xBE
#define CMD_WRITE_SCRATCH 0x4E
#define CMD_COPY_SCRATCH	0x48
#define CMD_RACALL_EEP	0xB8
#define CMD_READ_POWER	0xB4

static void PHY_WriteBit(bool b)
{
	IOPORT = 1;
	IOPORT = 0;
	Delay5us(_T_WRITE_LOW1 / 5);
	IOPORT = b;
	Delay5us((_T_SLOT - _T_WRITE_LOW1) / 5);
	IOPORT = 1;
}

static bool PHY_ReadBit(void)
{
	bool b;

	IOPORT = 1;
	IOPORT = 0;
	Delay1us();
	IOPORT = 1;
	Delay1us();
	Delay1us();
	//Delay5us(_T_RDV / 5);
	b = IOPORT;
	Delay5us((_T_SLOT - _T_RDV) / 5);
	return b;
}

static bool Device_Reset(void)
{
	DISABLE();
	IOPORT = 1;
	IOPORT = 0;
	Delay5us(_T_RESET_LOW / 5);
	IOPORT = 1;
	Delay5us(_T_PD_HIGH / 5);
	if (IOPORT == 1) {
		Delay5us((_T_PD_LOW) / 5);
		if (IOPORT == 1) {
			ENABLE();
			return false;
		}
		ENABLE();
		Delay5us((_T_RESET_HIGH - _T_PD_HIGH - _T_PD_LOW) / 5);
	} else {
		ENABLE();
		Delay5us((_T_RESET_HIGH - _T_PD_HIGH) / 5);
	}
	return true;
}

static void PHY_PutByte(uchar ch)
{
	uchar i, tmp;

	tmp = ch;
	DISABLE();
	for (i = 0; i < 8; i++) {
		PHY_WriteBit(tmp & 0x01);
		tmp >>= 1;
	}
	ENABLE();
}

static uchar PHY_GetByte(void)
{
	uchar i, ch = 0, mask = 0x01;

	DISABLE();
	for (i = 0; i < 8; i++) {
		if (PHY_ReadBit())
			ch |= mask;
		mask <<= 1;
	}
	ENABLE();
	return ch;
}

#if CRC_METHOD == 1
static bool DS18B20_CheckCRC8(uchar* buf, uchar len)
{
//查表异或
	uchar code TAB_CRC_8[] = {
		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
	};
	uchar i, crc_reg = 0;

	for (i = 0; i < len; i++) {
		crc_reg = TAB_CRC_8[crc_reg ^ buf[i]];
	}
	return (crc_reg == 0);
}

#elif CRC_METHOD == 2

//计算方式的CRC8
static uchar crcbyte(uchar ch, uchar crc_reg)
{
	bool bxor;
	uchar i;

	for (i = 0; i < 8; ++i) {
		bxor = (ch ^ crc_reg) & 0x01;
		crc_reg >>= 1;
		crc_reg ^= (bxor)? 0x8C: 0;
		ch >>= 1;
	}
	return crc_reg;
}


//入口参数:待校验的数据缓冲区和数据长度
static bool DS18B20_CheckCRC8(uchar * buf, uchar len)
{
	uchar i, crc_reg = 0;

	for (i = 0; i < len; i++) {
		crc_reg = crcbyte(buf[i], crc_reg);
	}
	return (crc_reg == 0);
}

#endif


// 初使化精度值
bool DS18B20_DeviceInit(uchar precision) {
	bool b;

	if (!(b = Device_Reset())) {
		return b;
	}
	PHY_PutByte(CMD_SKIP_ROM);
	PHY_PutByte(CMD_WRITE_SCRATCH);
	PHY_PutByte(40);
	PHY_PutByte(35);
	PHY_PutByte(precision);
	return (b);
}


//读取64Bit特征字
bool DS18B20_GetDeviceID(DS18B20_ID* pdevid)
{
	uchar i;
	bool b;

	if (!(b = Device_Reset())) {
		return b;
	}
	PHY_PutByte(CMD_READ_ROM);
	for (i = 0; i < DS18B20_DEVICE_ID_LENGTH; i++) {
		pdevid->buf[i] = PHY_GetByte();
	}
#if CRC_METHOD != 0
	b = DS18B20_CheckCRC8(
	  pdevid->buf, sizeof(DS18B20_ID)
	);
#endif
	return b;
}


//开始读取DS18B20暂存器
bool DS18B20_GetScratchStart(void)
{
	bool b;

	if (!(b = Device_Reset())) {
		return b;
	}
	PHY_PutByte(CMD_SKIP_ROM);
	PHY_PutByte(CMD_CONVERT_T);
	return (b);
}


//是否准备好读取暂存器
bool DS18B20_GetScratchReady(void) {
	if (PHY_GetByte() == 0xFF) {
		//if (PHY_GetByte() == 0xFF) {
			return true;
		//}
	}
	return false;
}


//读取暂存器
bool DS18B20_GetScratch(DS18B20_SCRATCH* pscrch)
{
	uchar i;
	bool b = false;

	if (!(b = Device_Reset())) {
		return b;
	}
	PHY_PutByte(CMD_SKIP_ROM);	
	PHY_PutByte(CMD_READ_SCRATCH);

	for (i = 0; i < sizeof(DS18B20_SCRATCH); i++)
		pscrch->buf[i] = PHY_GetByte();

#if CRC_METHOD != 0
	b = DS18B20_CheckCRC8(
	  pscrch->buf, sizeof(DS18B20_SCRATCH)
	);
#endif
	return b;
}

// 得到结果输出字符串
uchar* DS18B20_GetTemperature(uchar* s, DS18B20_SCRATCH* pscrch) {
#if GET_TEMP_CALC_METHOD == 1
	float thermal;
#else
	uchar frac;
	code int frac_table[] = {
		   0,  625, 1250, 1875,
		2500, 3125, 3750, 4375,
		5000, 5625, 6250, 6875,
		7500, 8125, 8750, 9375, 0
	};
#endif
	pscrch->scratch.temper = (pscrch->buf[1] << 8) | pscrch->buf[0];
#if GET_TEMP_CALC_METHOD == 1
	thermal *= pscrch->scratch.temper / 16.0;
	sprintf(s, "%03.4f", thermal);
#else
	frac = (pscrch->scratch.temper) & 0x0f;
	pscrch->scratch.temper >>= 4;
	if (pscrch->scratch.temper < 0) {
		if (frac != 0)
			pscrch->scratch.temper++;
		pscrch->scratch.temper = -pscrch->scratch.temper;
		sprintf(s,  "-%3d.%04d", pscrch->scratch.temper, frac_table[16 - frac]);
	} else {
		sprintf(s, "%3d.%04d", pscrch->scratch.temper, frac_table[frac]);
	}
#endif
	return s;
}

⌨️ 快捷键说明

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