文章目录
一、DS18B20传感器相关
1.单总线温度传感器DS18B20简介
DS18B20是美国DALLAS公司生产的数字温度传感器体积小、功耗低、抗干扰能力强。温度可直接将温度转换为数字信号并传输给单片机,从而节省传统信号的放大A/D转换等外围电路。 DS18B20测量温度范围-55~ 128℃,在-10~ 85℃测量精度可达士0.5℃,非常适合恶劣环境的现场温度测量,也可用于各种狭窄空间设备的温度测量,如环境控制、过程监测过程监测、温度测量消费电子产品和多点温度测量控制系统。
2.DS18B20内部存储结构
DS18B内部有64位ROM高速暂存器单元和9字节RAM单元。64位ROM单元包含了DS18B唯一的序列号20。
9字节高速临存器RAM单元
具体分布如下: 一般来说,用户使用第一字节和第二字节。单片机可以通过单总线读取数据,读取时低位在前,高位在后。 第6、7、8字节高速临存器未使用,为全1。
3.DS18B20温度数据处理
数据手册中给出的存储格式: 读出数据为负温度时,则需要将LSB和MSB16位整数,取反加1,乘以0.0625,因为温度数据以补码的形式表示。
二、DS18B20的工作时序
DS18B20对工作时间要求严格,延迟时间要准确,否则容易出错。DS18B工作时序包括初始时序、写时序和读时序。
1.初始化时序:
单片机将数据线电平拉低480-960us释放后,等待15-60us,单总线器件可连续输出60个~240us对于低电平,单片机收到此响应后即可操作。
//DS18B20设备初始化 bit init_ds18b20(void) {
bit initflag = 0; DQ = 1; Delay_OneWire(12*12); DQ = 0; Delay_OneWire(80*12); DQ = 1; Delay_OneWire(10*12); initflag = DQ; Delay_OneWire(5*12); return initflag; }
2.写时序:
当单片机从高到低拉数据线电平时,就会产生写时序,包括写0和写1。写时序开始后,DS18B20在15~60us期间从数据线采样。如果采样到低电平,则向DS18B20写的是0;果采样到高电平,则向DS18B20写的是“1”。这两个独立时序间至少需拉高总线电平1us时间。
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5*12);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5*12);
}
3.读时序:
当单片机从DS18B20读取数据时,产生读时序。此时单片机将数据线电平从高拉到低使读时序被初始化。如果在此后15us内,单片机在数据线上采样到低电平,则从DS18B20读的是“0”;如果在此后的15us内,单片机在数据线上采样到高电平,则从DS18B20读的是“1”。
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5*12);
}
return dat;
}
*芯片为STC的1T的芯片,运算速度是传统51的12倍,所以这里将官方的延时乘以12即可正常使用(组委会挖的小坑)
三、DS18B20的常用指令
四、DS18B20的程序分析
微处理器读取单个DS18B20的温度数据,可参考以下步骤: 1.DS18B20复位。 2.写入字节0xCC,跳过ROM指令。 3.写入字节0x44,开始温度转换。 4.延时700~900ms。 5.DS18B20复位。 6.写入字节0xCC,跳过ROM指令。 7.写入字节0xBE,读取高速暂存器。 8.读取暂存器的第0字节,即温度数据的LSB。 9.读取暂存器的第1字节,即温度数据的MSB。 10.DS18B20复位。,表示读取数据结束。 11.将LSB和MSB整合成为一个16位数据。 12.判断读取结果的符号,进行正负温度的数据处理。
五、程序代码
main.c
//@mzw //板载DS18B20温度传感器检测当前环境温度,并显示在数码管中 #include <reg52.h> #include <intrins.h> #include "onewire.h" sbit hc138_A=P2^5; sbit hc138_B=P2^6; sbit hc138_C=P2^7; unsigned char shuzi[10]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0-9 unsigned char shuzi1[10]={ 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//0-9//含小数点 #define uchar unsigned char int temp = 0x0000; //必须为16位int型数据 void HC138(unsigned int n) { switch(n) { case 4: hc138_A=0 ; hc138_B=0 ; hc138_C=1; break; case 5: hc138_A=1 ; hc138_B=0 ; hc138_C=1; break; case 6: hc138_A=0 ; hc138_B=1 ; hc138_C=1; break; case 7: hc138_A=1 ; hc138_B=1 ; hc138_C=1; break; } } /*****延时函数*****/ void delay(unsigned int k) { while(k--); } /*****DS18B20初始化函数*****/ void DS18B20_work() { unsigned char LSB , MSB ; init_ds18b20(); //DS18B20复位 Write_DS18B20(0xcc); //写入字节0xcc,跳过ROM指令 Write_DS18B20(0x44); //写入字节0x44,开始温度转换 delay(800); //延时700~900ms init_ds18b20(); //DS18B20复位 Write_DS18B20(0xcc); //写入字节0xcc,跳过ROM指令 Write_DS18B20(0xbe); //写入字节0xbe, 读取告诉暂存器 LSB=Read_DS18B20(); //读取温度数据的低8位 MSB=Read_DS18B20(); //读取温度数据的高8位 init_ds18b20(); //DS18B20复位,表示读取数据结束 temp = MSB ; temp = temp << 8 ; //左移8位,使MSB中的数据变为temp的高八位,低八位补零 temp = temp | LSB; //将LSB并入temp低八位,将LSB和MSB整合成为一个16位的整数 整合完毕 //首先通过温度数据的高5位判断采用结果是正温度还是负温度 if((temp & 0xf800) == 0x0000) //正温度的处理办法 { temp >>= 4; //取出温度结果的整数部分 temp = temp*10; //放大10倍 temp = temp + (LSB&0x0f)*0.625; //加上小数部分 } //此方法计算出的数据为实际温度的10倍,方便小数位的显示 /*****正常情况室温都大于0*****/ // temp = temp >>=4; 不带小数点的显示方法 } /*****数码管显示函数*****/ void Display() { char x = 0x01; int i = 0; for(i = 1;i<=8 ;i++) { HC138(6); P0 = x; x = _crol_(x,1); HC138(7); P0 = 0xff;delay(20); //数码管消隐放到这个地方好一点 switch (i) { case 1 :P0 = 0xff; break; case 2 :P0 = 0xff; break; case 3 :P0 = 0xff; break; case 4 :P0 = 0xff; break; case 5 :P0 = 0xff; break; case 6 :P0 = shuzi[temp / 100]; break;//temp的百位, 实际温度的十位 case 7 :P0 = shuzi1[temp % 100 / 10]; break;//temp的十位,实际温度的个位 case 8 :P0 = shuzi[temp % 10]; break;//temp的个位,实际温度的小数点后一位 } delay(500);P0 = 0xff; } } void main() { HC138(5); P0=0x00; //
蜂鸣器和继电器初始化、、全关 HC138(4); P0= 0xff; //LED小灯初始化、、全关 while(1) { DS18B20_work(); Display(); //数码管显示 } }
onewire.c
/* 程序说明: 单总线驱动程序 软件环境: Keil uVision 4.10 硬件环境: CT107单片机综合实训平台(外部
晶振12MHz) STC89C52RC单片机 日 期: 2011-8-9 */ #include "reg52.h" sbit DQ = P1^4; //单总线接口 //单总线延时函数 void Delay_OneWire(unsigned int t) //STC89C52RC { while(t--); } //通过单总线向DS18B20写一个字节 void Write_DS18B20(unsigned char dat) { unsigned char i; for(i=0;i<8;i++) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5*12); DQ = 1; dat >>= 1; } Delay_OneWire(5*12); } //从DS18B20读取一个字节 unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i=0;i<8;i++) { DQ = 0; dat >>= 1; DQ = 1; if(DQ) { dat |= 0x80; } Delay_OneWire(5*12); } return dat; } //DS18B20设备初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(12*12); DQ = 0; Delay_OneWire(80*12); DQ = 1; Delay_OneWire(10*12); initflag = DQ; Delay_OneWire(5*12); return initflag; }
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
bit init_ds18b20(void);
unsigned char rd_temperature(void); //; ;
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat); //STC89C52RC
unsigned char Read_DS18B20(void);
#endif