一、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.判断读取结果的符号进行正负温度的数据读取
二、DS18B20的数据处理
DS18B20以16位带符号位扩展的二进制补码形式读出
低4位为小数部分,中间7位为整数部分,高5位为符号位
DS18B20的分辨率为0.0625。读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625
注意:在上电复位的时候,温度寄存器中的值为0X0550,即**+85**摄氏度
三、代码展示
main.c
#include "reg52.h" #include "onewire.h" typedef unsigned int uint; typedef unsigned char uchar; uint temp = 0; uchar SMG_duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x80,0xc6,0xc0,0x86,0x8e, 0xbf,0x7f};//分别是0-9(对应下标),A-F,“-”,“.” uchar SMGDot_AC[10] = {0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10}; //配置HC138 void SelectHC138(uchar channel) { switch(channel) { case 4: //LED P2 = (P2 & 0X1F) | 0X80; break; case 5: //蜂鸣器和继电器 P2 = (P2 & 0X1F) | 0Xa0; break; case 6: //位码 P2 = (P2 & 0X1F) | 0Xc0; break; case 7: //段码 P2 = (P2 & 0X1F) | 0Xe0; break; case 0: //锁住所有寄存器 P2 = (P2 & 0X1F) | 0X00; break; } } void Delay_SMG(uint t) { while(t--); } //在pos位码上,显示value段码 void DisplaySMG_Bit(uchar pos, uchar value) { SelectHC138(6); P0 = 0X01 << pos; SelectHC138(7); P0 = value; } void Initsys() { SelectHC138(5); P0 = 0X00;//关闭蜂鸣器和继电器 SelectHC138(4); P0 = 0XFF;//关闭LED } void Display_All(uchar dat) { SelectHC138(6); P0 = 0XFF; SelectHC138(7); P0 = dat; } void DisplaySMG_Temp() { DisplaySMG_Bit(7,SMG_duanma[temp % 10]); Delay_SMG(100); DisplaySMG_Bit(6,SMGDot_AC[(temp % 100) / 10]); Delay_SMG(100); DisplaySMG_Bit(5,SMG_duanma[temp / 100]); Delay_SMG(100); DisplaySMG_Bit(4,0XFF); Delay_SMG(100); DisplaySMG_Bit(3,0XFF); Delay_SMG(100); DisplaySMG_Bit(2,0XFF); Delay_SMG(100); DisplaySMG_Bit(1,0XFF); Delay_SMG(100); DisplaySMG_Bit(0,0XFF); Delay_SMG(100); Display_All(0XFF); } void Delay_temp(uint t) { while(t--) { DisplaySMG_Temp(); } } //**********************读取温度***************************/ void read_DS18B20_temp() { uchar LSB,MSB; //LSB低八位,MSB高八位 //温度转换 init_ds18b20(); //初始化DS18B20 Write_DS18B20(0xcc); //跳过ROM Write_DS18B20(0x44); //开始温度转换 Delay_OneWire(200); //等待温度转换完成 //读温度 init_ds18b20(); //初始化DS18B20 Write_DS18B20(0xcc); //跳过ROM Write_DS18B20(0xbe); //开始读温度 //读温度 LSB = Read_DS18B20(); //读取低八位数据 MSB = Read_DS18B20(); //读取高八位数据 temp = MSB; temp <<= 8; //高八位右移8位 temp = temp | LSB; //将独立的高、低8位合并为16位 if((temp & 0xf800) == 0x0000) //判断temp的高五位来判断温度的正负,高5位全为0表示为正,全为1表示负 { temp >>= 4; temp = temp * 10; //temp先右移四位在乘上10相当于整数部分乘以0.625倍 temp = temp + (LSB & 0x0f) * 0.625; //整数部分 * 0.625 + 小数部分 *0.625 } } void main() { Initsys(); while(1) { read_DS18B20_temp(); DisplaySMG_Temp(); } }
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(50); DQ = 1; dat >>= 1; } Delay_OneWire(50); } //从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(50); } return dat; } //DS18B20设备初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(120); DQ = 0; Delay_OneWire(800); DQ = 1; Delay_OneWire(100); initflag = DQ; Delay_OneWire(50); return initflag; }
onewire.h
#ifndef __ONEWIRE_H #define __ONEWIRE_H unsigned char rd_temperature(void); //; ; Delay_OneWire(uint); bit init_ds18b20(void); unsigned char Read_DS18B20(void); void Write_DS18B20(unsigned char dat); #endif