【51单片机】单总线温度采集

一、目标

1、学习单总线温度传感器DB18B20的原理和通信时序;

2、使用51单片机的一个 IO 口模拟单总线时序与温度传感器DS18B20通信,将检测的环境温度读取出来。

二、原理介绍

1.单总线温度传感器DS18B20介绍

DS18B20是美国DALLAS公司生产的数字温度传感器,体积小、低功耗、抗干扰能力强。可直接将温度转化成数字信号传送给单片机处理,因而可省去传统的信号放大、A/D转换等外围电路。
DS18B20转换时间与分辨率有关。当设定为9位时,转换时间为93.75ms;设定10位时,转换时间为187.5 ms;当设定11位时,转换时间为375ms;当设定为12位时,转换时间为750ms。
在这里插入图片描述

当DS18B20采集的温度为+125℃时,输出为*0x07d0,则:
实际温度=(0x07d0)/16=(0×163+7×162+13×161+0×160)/16=125℃
当DS18B20采集的温度为-55℃时,输出为0xfc90,由于是补码,则先将11位数据取反加1得0x0370,注意符号位不变,也不参加运算,则:
实际温度=(0x0370)/16=(0×163+3×162+7×161+0×160)/16=55℃。
注意,负号则需对采集的温度进行判断后,再予以显示。

2.DS18B20的工作时序

DS18B20的工作时序包括初始化时序、写时序和读时序。

(1)初始化时序,单片机将数据线电平拉低480960µs后释放,等待1560µs,单总线器件即可输出一持续60~240µs的低电平,单片机收到此应答后即可进行操作。

(2)写时序,当单片机将数据线电平从高拉到低时,产生写时序,有写“0”和写“1”两种时序。写时序开始后,DS18B20在15~60µs期间从数据线上采样。如果采样到低电平,则向DS18B20写的是“0”;如果采样到高电平,则向DS18B20写的是“1”。这两个独立时序间至少需拉高总线电平1µs时间。

(3)读时序,当单片机从DS18B20读取数据时,产生读时序。此时单片机将数据线电平从高拉到低使读时序被初始化。如果在此后15µs内,单片机在数据线上采样到低电平,则从DS18B20读的是“0”;如果在此后的15µs内,单片机在数据线上采样到高电平,则从DS18B20读的是“1”。

3.DS18B20的命令

DS18B20片内都有唯一的64位光刻ROM编码,出厂时已刻好。它是DS18B20的地址序列码,目的是使每个DS18B20的地址都不相同,这样就可实现在一根总线上挂接多个DS18B20的目的。
DS18B20所有命令均为8位长,常用的命令代码如下:
在这里插入图片描述
如果主机只对一个DS18B20进行操作,就不需要读取ROM编码以及匹配ROM编码,只要用跳过ROM(CCH)命令,就可按如下表执行如下温度转换和读取命令:
在这里插入图片描述

三、实现

实现单总线温度测量系统

代码

#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int 
#define out P0
sbit smg1=out^4;
sbit smg2=out^5;
sbit DQ=P3^7;
void delay5(uchar);
void init_ds18b20(void);
uchar readbyte(void);
void writebyte(uchar);
uchar retemp(void);
void main(void)
{
uchar i,temp;
delay5(1000);
while(1)
	{
	 temp=retemp();	
	 for(i=0;i<10;i++)	//连续扫描数码管10次
	 {
	 out=(temp/10)&0x0f;
	 smg1=0;
	 smg2=1;
	 delay5(1000);	//延时5ms
	 out=(temp%10)&0x0f;
	 smg1=1;
	 smg2=0;
	 delay5(1000);	//延时5ms
	 }
	}
}
/*--------------精确延时5us子程序---------*/
void delay5(uchar n)
{
	 do
	 {
	 _nop_();
	 _nop_();
	 _nop_();
	 n--;
	 }
	 while(n);
}
/*--------------初始化函数--------------------*/
void init_ds18b20(void)
{
	 uchar x=0; 
	 DQ =0;    
	 delay5(120); 
	 DQ =1;    
	 delay5(16);
	 delay5(80);
}
/*--------------读取一字节函数----------------*/
uchar readbyte(void)
{
	uchar i=0;
	uchar date=0;
	for (i=8;i>0;i--)
	 {
		  DQ =0;
		  delay5(1);
		  DQ =1;	//15微秒内拉释放总线
		  date>>=1;
		  if(DQ)
		  date|=0x80;
		  delay5(11);
	 }
 	return(date);
}
/*--------------写一字节函数------------------*/
void writebyte(uchar dat)
{
 uchar i=0;
 for(i=8;i>0;i--)
	 {
	  DQ =0;
	  DQ =dat&0x01;//写"1" 在15微秒内拉低
	  delay5(12);	   //写"0" 拉低60微秒
	  DQ = 1;	   
	  dat>>=1;
	  delay5(5);
	  }
}
/*--------------读取温度函数------------------*/
uchar retemp(void)
{
	uchar a,b,tt;
	uint t;
	init_ds18b20();
	writebyte(0xCC); 
	writebyte(0x44);
	init_ds18b20();
	writebyte(0xCC); 
	writebyte(0xBE); 
	a=readbyte();
	b=readbyte();
	t=b;
	t<<=8;
	t=t|a;
	tt=t*0.0625;
	return(tt);
}

Proteus仿真

在这里插入图片描述

四、总结

通过此次学习51单片机单总线温度采集的相关内容,掌握了单总线温度采集的使用方法,了解了如何利用单总线进行温度采集,掌握了如何利用单总线来实现温度采集,加深了对单总线温度采集的理解和掌握。
以上为我此次学习成果,如有问题,烦请指正。

  • 21
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是ds18b20和lcd1602多路温度采集的c语言编程示例: #include <reg51.h> #define DS18B20_PORT P1 sbit DS18B20_PIN = P1^2; void delay_us(unsigned int us) { while(us--) { _nop_(); _nop_(); _nop_(); _nop_(); } } void send_ds18b20(unsigned char dat) { unsigned char i; for(i = 0; i < 8; i++) { DS18B20_PIN = 0; _nop_(); _nop_(); DS18B20_PORT = dat & 0x01; delay_us(5); DS18B20_PIN = 1; dat >>= 1; } } unsigned char read_ds18b20() { unsigned char i, dat = 0; for(i = 0; i < 8; i++) { DS18B20_PIN = 0; _nop_(); _nop_(); DS18B20_PIN = 1; _nop_(); _nop_(); dat >>= 1; if(DS18B20_PIN) dat |= 0x80; delay_us(5); } return dat; } void start_ds18b20() { DS18B20_PIN = 0; delay_us(500); DS18B20_PIN = 1; delay_us(60); DS18B20_PIN = 0; delay_us(500); } void lcd_send_cmd(unsigned char cmd) { P2 = cmd; P0 = 0x04; delay_us(5); P0 = 0x00; delay_us(100); } void lcd_send_data(unsigned char dat) { P2 = dat; P0 = 0x05; delay_us(5); P0 = 0x01; delay_us(100); } void lcd_init() { lcd_send_cmd(0x38); lcd_send_cmd(0x0c); lcd_send_cmd(0x06); lcd_send_cmd(0x01); } void lcd_display_temp(unsigned char temp) { lcd_send_cmd(0x80); lcd_send_data('T'); lcd_send_data('e'); lcd_send_data('m'); lcd_send_data('p'); lcd_send_data(':'); lcd_send_data(' '); lcd_send_data(temp / 10 + '0'); lcd_send_data(temp % 10 + '0'); lcd_send_data(0xdf); lcd_send_data('C'); } void main() { unsigned char i, j, temp, temp_array[5]; lcd_init(); while(1) { start_ds18b20(); send_ds18b20(0xcc); // skip ROM send_ds18b20(0x44); // start conversion delay_us(1000); start_ds18b20(); send_ds18b20(0xcc); // skip ROM send_ds18b20(0xbe); // read scratchpad for(i = 0; i < 9; i++) { temp_array[i] = read_ds18b20(); } temp = temp_array[0] >> 4; lcd_display_temp(temp); delay_us(500); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值