1-wire实现DS18B20温度读取

1.DS18B20介绍

DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出。

测温范围:-55°C 到 +125°C

通信接口:1-Wire(单总线)

其它特征:可形成总线结构、内置温度报警功能、可寄生供电

2.DS18B20引脚及电路介绍

3.DS18B20内部结构

内部结构首先包含一个power-supply-sense内部寄生供电,当VDD不接电源时,DS18B20内部采取寄生供电,本此实验不采用寄生供电,VDD接电源正极,当DQ把数据传送进DS18B20内部后,首先回进到ROM里面,而这里的ROM作用通过DQ线进行写数据和读数据,经过逻辑控制,将要写的数据传入到SCRATCHPAD中相当于一个RAM存数据的盒子,通过写进去的数据向DS18B20发号指令,最右边包含温度传感器,温度报警设置温度的阈值,配置寄存器设置温度精度,以及CRC校验。

3.1DS18B20存储器结构

 4.1-Wire单总线介绍

单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线

单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线

一根通信线:DQ

通信特点:异步、半双工 

4.1单总线通信规范

设备的DQ均要配置成开漏输出模式

注意:什么是开漏输出模式?

推挽输出:不需要上拉电阻,不可“线与”,不可电平转换

开漏输出:需要上拉电阻,可以进行“线与”,可以电平转换

DQ添加一个上拉电阻,阻值一般为4.7KΩ左右

若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路

注意:什么是强上拉输出电路?

上拉电阻是把一个信号通过一个电阻接到电源(Vcc),下拉电阻是一个信号通过一个电阻接到地(GND)。   强上拉、弱上拉的强弱只是上拉电阻的阻值不同,没有什么严格区分

4.2单总线时序结构

4.2.1单总线初始化

初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线

 unsigned char  OneWire_Init(void)
{
    unsigned char i;
    unsigned char AckBit;//应答位
    OneWire_DQ=1;
    OneWire_DQ=0;
  i = 247;while (--i);//500us  Delay500 us
    OneWire_DQ=1;
    i = 32;while (--i);//Delay 70us
    AckBit=OneWire_DQ;//从机响应
    i = 247;while (--i);  //500us
    
    return AckBit;
}

4.2.2单总线发送1bit数据(接受1bit)

发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us

 

 void OneWire_SendBit(unsigned char Bit)
{
    unsigned char i;
    OneWire_DQ=0;
    i = 4;while (--i);//Delay10us
    OneWire_DQ=Bit;
    i = 24;while (--i);//Delay50us
    OneWire_DQ=1;    
}

 接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us

 

 unsigned char OneWire_ReceiveBit(void)
{
    unsigned char i;
    unsigned char Bit;
    OneWire_DQ=0;
    i = 2;while (--i);//Delay5us
    OneWire_DQ=1;
    i = 2;while (--i);//Delay5us
    Bit=OneWire_DQ;//接受数据
    i = 24;while (--i);//Delay50us
    return Bit;
}

4.2.3单总线发送1字节(接受一字节)

注意:I2C发送字节:先发送高位再发送低位,1-Wire先发送低位,再发送高位

发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)

接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

 

void OneWire_SendByte(unsigned char Byte)//发送一个字节
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        OneWire_SendBit(Byte&(0x01<<i));
    }
}

unsigned char OneWire_ReceiveByte(void)
{
    unsigned char i;
    unsigned char Byte=0x00;
    for(i=0;i<8;i++)
    {
        if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
    }
    return Byte;
}

 5.DS18B20实现温度读取

5.1操作流程

为了实现DS18B20温度读取,我们要使用到DS18B20内部的寄存器,这里我们只需要用到ROM指令中的SKIP ROM[CCh],功能指令中的CONVERT温度变化[44h],READ SCRATCHPAD [BEh]功能读取命令

初始化:从机复位

主机判断从机是否响应 ROM操作:ROM指令+本指令需要的读写操作

功能操作:功能指令+本指令需要的读写操作

5.2温度变换和温度读取

温度变换:初始化→跳过ROM →开始温度变换

温度读取:初始化→跳过ROM →读暂存器→连续的读操作

这里对温度进行读取,要先读取温度的LSB低8位,再读取温度的高八位MSB

6.DS18B20温度读取程序

6.1子程序包含

这里只展示main.c主函数,onewire.c和onewire.h,DS18B20.c和DS18B20.h

6.2onewire.c子函数

#include <REGX52.H>


sbit  OneWire_DQ=P3^7;

unsigned char  OneWire_Init(void)
{
	unsigned char i;
	unsigned char AckBit;//应答位
	OneWire_DQ=1;
	OneWire_DQ=0;
  i = 247;while (--i);//500us  Delay500 us
	OneWire_DQ=1;
	i = 32;while (--i);//Delay 70us
	AckBit=OneWire_DQ;//从机响应
	i = 247;while (--i);  //500us
	
	return AckBit;
}

void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	OneWire_DQ=0;
	i = 4;while (--i);//Delay10us
	OneWire_DQ=Bit;
	i = 24;while (--i);//Delay50us
	OneWire_DQ=1;	
}

unsigned char OneWire_ReceiveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	OneWire_DQ=0;
	i = 2;while (--i);//Delay5us
	OneWire_DQ=1;
	i = 2;while (--i);//Delay5us
	Bit=OneWire_DQ;//接受数据
	i = 24;while (--i);//Delay50us
	return Bit;
}

void OneWire_SendByte(unsigned char Byte)//发送一个字节
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));
	}
}

unsigned char OneWire_ReceiveByte(void)
{
	unsigned char i;
	unsigned char Byte=0x00;
	for(i=0;i<8;i++)
	{
		if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
	}
	return Byte;
}

6.3onewire.h子函数

#ifndef  __ONEWIRE_H__
#define  __ONEWIRE_H__

unsigned char  OneWire_Init(void);
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReceiveBit(void);
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte(void);

#endif

6.4DS18B20.c子函数

#include <REGX52.H>
#include "onewire.h"

#define   DS18B20_SKIP_ROM     0xCC
#define   DS18B20_CONVERT_T    0x44
#define   DS18B20_READ_CONVERT_T  0xBE
void DS18B20_ConvertT()
{
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM );//发送skip RoM地址
  OneWire_SendByte(DS18B20_CONVERT_T);//发送温度转化地址
}

float DS18B20_ReadT(void)
{
	unsigned char TLSB,TMSB;
	int Temp;
	float T;
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);//发送skip RoM地址
  OneWire_SendByte(DS18B20_READ_CONVERT_T);//发送读温度暂存器的地址
	TLSB=OneWire_ReceiveByte();
	TMSB=OneWire_ReceiveByte();
	Temp=(TMSB<<8)|TLSB;//拼接为16位
	T=Temp/16.0;//得到准确的温度
	
	return T;
}


6.5DS18B20.h子函数

#ifndef  __DS18B20_H__
#define  __DS18B20_H__

void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);

#endif

6.6main主函数

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "DS18B20.h"

float T;
void main()
{
	DS18B20_ConvertT();
	Delay(1000);
  	LCD_Init();
		LCD_ShowString(1,1,"Temperature:");
	while(1)
	{
	DS18B20_ConvertT();
	T=DS18B20_ReadT();
	if(T<0){
		LCD_ShowChar(2,1,'-');
		T=-T;
	}
	else{
		LCD_ShowChar(2,1,'+');
	}
	LCD_ShowNum(2,2,T,3);
	LCD_ShowChar(2,5,'.');
	LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示温度小水但后面4位小数
	}
}

.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值