温度传感器18B20(串口显示)

如果有问题或是更好的方法希望大家提出来,谢谢

/*温度传感器18B20--串口显示温度*/
#include<reg52.h>
#include <intrins.h> 

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef          char int8;
typedef          int int16;
sbit DQ=P3^2;	 //温度输入口

void nops()
{
    _nop_();
    _nop_();
    _nop_();
    _nop_();
}

void delay(uint16 n)
{
    while(n--);
}

void delay_ms(uint16 n)
{
	uint8 m=120;

	while (n--)
		while (m--);
}

void DS18b20_reset(void)
{
	bit flag=1;
		while (flag)
	 	{
 			DQ = 1;
			delay(1);	//7.5us
 			DQ = 0;
 			delay(50); //139.8us
 			DQ = 1; 
 			delay(6);  // 21us
 			flag = DQ;
   		}
	delay(45);    //延时500us
	DQ=1;
}


/*
 * 18B20写1个字节函数
 * 向1-WIRE总线上写一个字节
*/
void write_byte(uint8 val)
{
	uint8 i;

	for (i=0; i<8; i++)
	{
		DQ = 1;
		_nop_();  	 //两次传送间隔大于1us
		DQ = 0;
		nops(); //4us
		DQ = val & 0x01;      //最低位移出
		delay(6);           //66us  (30US)
		val >>= 1;          //右移一位
	}
	DQ = 1;
	delay(1);  
}


/*
 * 18B20读1个字节函数
 * 从1-WIRE总线上读取一个字节
*/
uint8 read_byte(void)
{
	uint8 i, value=0;

	for (i=0; i<8; i++)
	{
	    value >>= 1;
		DQ=1;
		_nop_();
		DQ = 0;
		nops();   //4us
		DQ = 1;
		nops();   //4us 
		if (DQ)
			value|=0x80;
		delay(6);           //66us
	}
	DQ=1;
	return value;
}


/*
 * 启动温度转换
*/
void start_temp_sensor(void)
{
   DS18b20_reset();
   write_byte(0xCC); // 发Skip ROM命令
   write_byte(0x44);// 发转换命令
}


/*
 * 读出温度
*/
int16 read_temp(void)
{
	uint8 temp_data[2]; // 读出温度暂放
	int16 temp;

	DS18b20_reset();  // 复位
	write_byte(0xCC); // 发Skip ROM命令
	write_byte(0xBE); // 发读命令
	temp_data[0]=read_byte();  //温度低8位
	temp_data[1]=read_byte();  //温度高8位

	temp = temp_data[1];
	temp <<= 8;
	temp |= temp_data[0];
	temp >>= 4;	  //注意是移动四位

	return temp;
}

/**
 * UART初始化
 * 波特率:9600
*/
void uart_init(void)
{
    TMOD = 0x21;        // 定时器1工作在方式2(自动重装)
    SCON = 0x50;        // 10位uart,允许串行接受

    TH1 = 0xFD;
    TL1 = 0xFD;

    TR1 = 1;
}

/**
 * UART发送一字节
*/
void UART_Send_Byte(uint8 dat)
{
	SBUF = dat;
	while (TI == 0);
	TI = 0;
}

/**
 * 将数据转换成ASC码并通过UART发送出去
*/
void UART_Send_Dat(uint8 dat)	 //100度以下温度可用
{
	UART_Send_Byte(dat/10%10 + '0');
	UART_Send_Byte(dat%10 + '0');
}

 

main()
{
	int16 ans;

	uart_init();
	start_temp_sensor();
	while (1)
	{
		delay_ms (1000); // 延时1秒

		ans=read_temp();
	
		if (ans < 0)
		{
			UART_Send_Byte('-');
			ans = -ans;
		}
	
		UART_Send_Dat(ans);
		UART_Send_Byte('\r');
		UART_Send_Byte('\n');
	}

}


 

DS18B20是单总线数字传感器,共有6种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。 这几个信号的时序如下: 1)复位脉冲和应答脉冲 单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15~60us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240us,以产生低电平应答脉冲,若为低电平,再延时480us。 2)写时序 写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。 3)读时序 单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。典型的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us。 DS18B20的温度读取过程一般为:复位->发SKIPROM命令(0XCC)->发开始转换命令(0X44)->延时->复位->发送SKIPROM命令(0XCC)->发读存储器命令(0XBE)->连续读出两个字节数据(即温度)->结束。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值