一、DS18B20传感器相关
1.单总线温度传感器DS18B20简介2.DS18B20的内部存储结构
9字节高速暂存器RAM单元 3.DS18B20的温度数据处理 二、DS18B20的工作时序
1.初始化时序:2.写时序:3.读时序: 三、DS18B20的常用指令四、DS18B20的程序分析五、程序代码
main.conewire.conewire.h
一、DS18B20传感器相关 1.单总线温度传感器DS18B20简介
DS18B20是美国DALLAS公司生产的数字温度传感器,体积小、低功耗、抗干扰能力强。可直接将温度转化成数字信号传送给单片机处理,因而可省去传统的信号放大、A/D转换等外围电路。
DS18B20测量温度范围-55~+128℃,在-10~+ 85℃范围内,测量精度可达士0.5℃,非常适合于恶劣环境的现场温度测量,也可用于各种狭小空间内设备的测温,如环境控制、过程监测过程监测、测温类消费电子产品以及多点温度测控系统。
DS18B20的内部有64位的ROM单元和9字节的高速暂存器RAM单元。64位ROM单元包含了DS18B20唯一的序列号。
9字节高速暂存器RAM单元其中9个字节具体分布如下:
第1字节和第2字节是在单片机发给DS18B20温度转换命令发布后,经转换所得的温度值,以两字节补码形式存放其中。
一般情况下,用户多使用第1字节和第2字节。单片机通过单总线可读得该数据,读取时低位在前,高位在后。
第3、4字节分别是由软件写入用户报警的上下限值TH和TL。
第5个字节为配置寄存器,可对其更改DS18B20的测温分辨率。
高速暂存器的第6、7、8字节未用,为全1。
第9字节是前面所有8个字节的CRC码,用来保证正确通信。
数据手册中给出的储存格式:
其中DS18B20以16位带符号位扩展的二进制补码形式读出。
低4位为小数部分,中间7位为整数部分。
高5位为扩展符号位,即BIT15~BIT11为00000,读出的数据为正温度,若为11111,则为负温度。在应用开发中,首先要对读出的温度数据的符号位进行判断,再根据正负温度的不同,进行相应的处理。
在上电复位的时候,温度寄存器中的值为0x0550,即+85摄氏度。
从输出数据与温度值的关系表中可知,DS18B20的分辨率为0.0625。
读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。
读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625,因为温度数据是以补码形式表示的。
DS18B20对工作时序要求严格,延时时间需准确,否则容易出错。DS18B20的工作时序包括初始化时序、写时序和读时序。
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; }
*关于工作时序的三个程序:程序均来自蓝桥杯比赛官方提供的代码,
因为官方例程所使用的为普通8051单片机,为12T单片机,即12个时钟周期机器做一个指令周期,
但是蓝桥杯单片机比赛所使用的芯片为STC的1T的芯片,运算速度是传统51的12倍,所以这里将官方的延时乘以12即可正常使用(组委会挖的小坑)
微处理器读取单个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.判断读取结果的符号,进行正负温度的数据处理。
//@mzw //板载DS18B20温度传感器检测当前环境温度,并显示在数码管中 #includeonewire.c#include #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--); } 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倍,方便小数位的显示 // 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(); //数码管显示 } }
#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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)