目录
DS18B20的温度转换与读取流程
- DS18B20复位
- 写入字节0xcc,跳过ROM指令
- 写入字节0x44,开始温度转换
- 延时700~900ms
- DS18B20复位
- 写入字节0xcc,跳过ROM指令
- 写入字节0xbe,读取高速暂存器
- 读取暂存器的第0字节,即温度数据的LSB
- 读取暂存器的第1字节,即温度数据的MSB
- DS18B20复位,表示读取数据结束
- 将LSB和MSB整合成一个16位数据
- 判断读取结果的符号,进行正负温度的数据处理
//DS18B20温度采样与结果处理参考代码
void Read_Temperature()
{
unsigned char LSB,MSB ;
Init_DS18B20(); //DS18B20复位
Write_DS18B20(0xCC); //跳过ROM操作指令
Write_DS18B20(0x44); //开始温度转换
Delay(1000); //延时700ms左右,等待温度转换完成
Init_DS18B20(); //DS18B20复位
Write_DS18B20(0xCC); //跳过ROM操作指令
Write_DS18B20(0xBE); //开始读取高速暂存器
LSB = Read_DS18B20(); //读取温度数据的低8位
MSB = Read_DS18B20(); //读取温度数据的高8位
Init_DS18B20(); //DS18B20复位,停止暂存器数据读取
T_dat = 0x0000;
T_dat = MSB;
T_dat <<= 8;
T_dat = T_dat | LSB; //将LSB和MSB整合成为一个16位的整数
//首先通过温度数据的高5位判断采用结果是正温度还是负温度
if((T_dat & 0xf800) == 0x0000) //正温度的处理办法
{
T_dat >>= 4; //取出温度结果的整数部分
T_dat = T_dat*10; //放大10倍,然后加上小数部分
T_dat = T_dat + (LSB&0x0f)*0.625;
}
}
DS18B20的数据处理
以16位带符号位扩展的二进制补码形式读出
低4位为小数部分,中间7位为整数部分,高5位为符号位
分辨率为0.0625
高5位为扩展符号位,即BIT15~BIT11为00000,读出的数据为正温度,若为11111,则为负温度。在应用开发中,首先要对读出的温度数据的符号位进行判断,再根据正负温度的不同,进行相应的处理。
读出数据为正温度时,将LSB和MSB整合成的16位整数乘以0.0625;读出数据为负温度时,将LSB和MSB整合成的16位整数取反加一后,乘以0.0625;
在上电复位时,温度寄存器中的值为0x0550,即+85摄氏度
如果要求温度结果保留1位小数:
首先将温度结果的整数部分取出: T_dat >>= 4;即 T_dat = 0x0019 = 25。
然后将整数部分放大10倍: T_dat = T_dat × 10 ;即 T_dat = 250。
然后将小数部分取出: LSB&0x0f,其结果为0x06。
再将小数部分乘以0.0625的10倍,即0x06 × 0.625 = 3.73。
最后将整数部分和小数部分相加: T_dat = 250 + 3.73 = 253(因为 T_dat 是整型)
对于温度数据253,在数码管显示的时候,在十位出加上一个小数点,就变成了:25.3。如果要求温度结果只显示整数部分:
T_dat >>= 4;即 T_dat = 0x0019 = 25 摄氏度。
主程序
#include "reg52.h"
#include "absacc.h"
#include "onewire.h"
unsigned char SMGNoDot_CA[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x90,0x90}; //无小数点
unsigned char SMGDot_CA[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //显示小数点
unsigned int temp=0;
void delaySMG(unsigned int t)
{
while(t--);
}
void displaySMGbit(unsigned char pos,unsigned char dat) //第pos个数码管显示数字dat
{
XBYTE[0xe000]=0xff;
XBYTE[0xc000]=0x01<<pos;
XBYTE[0xe000]=dat;
}
void displayall(unsigned char dat)
{
XBYTE[0xe000]=0xff;
XBYTE[0xe000]=dat;
}
//
void displaySMGtemp() //显示温度
{
/*
displaySMGbit(7,SMGNoDot_CA[temp%10]);
delaySMG(100);
displaySMGbit(6,SMGDot_CA[(temp%100)/10]);
delaySMG(100);
displaySMGbit(5,SMGNoDot_CA[temp/100]);
delaySMG(100);
*/
displaySMGbit(7,SMGNoDot_CA[temp%10]);
delaySMG(100);
displaySMGbit(6,SMGNoDot_CA[temp/10]);
delaySMG(100);
displaySMGbit(5,0xff);
delaySMG(100);
//只需要3个数码管显示温度,其他数码管不亮
displaySMGbit(4,0xff);
delaySMG(100);
displaySMGbit(3,0xff);
delaySMG(100);
displaySMGbit(2,0xff);
delaySMG(100);
displaySMGbit(1,0xff);
delaySMG(100);
displaySMGbit(0,0xff);
delaySMG(100);
displayall(0xff);
}
void delay(unsigned int t)
{
while(t--)
{
displaySMGtemp();//让动态扫描没有间断
}
}
void read_DS18B20_temp()
{
unsigned char LSB,MSB;
init_ds18b20();//初始化
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
delay(1000);
init_ds18b20();//初始化
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
temp=MSB;
temp<<=8;
temp=temp|LSB;
temp>>=4;
/*
if((temp&0xf800)==0x0000) //取出来高五位
{
temp>>4;//把小数移走 ,右移4位,相当于*0.0625
temp=temp*10;
temp=temp+(LSB&0x0f)*0.625;//低四位取出来为小数,此时分辨率放大了10倍
}
*/
}
void main()
{
XBYTE[0x8000]=0x00;
while(1)
{
read_DS18B20_temp();
displaySMGtemp();
}
}
注意事项
- 先将 赛点资源的onewire.c文件和onewire.h文件复制到自己建立的工程下。
- 打开 onewire.h文件,检查文件代码是否完整,并确认总线引脚定义是否和CT107D的硬件对应,即P1^4。如果不对应,则将其修改过来。
- 打开 onewire.c文件, 研读各个底层驱动代码的具体实现,初步判断是时序的延时是否合理,如有明显错误,则将其修改过来。
- 根据DS18B20的工作原理和操作流程,编写读取温度结果和处理温度数据的函数
- 根据得到的温度结果,刷新数码管显示。这个部分,可以用MM模式来实现,可以用IO模式来实现。
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned char rd_temperature(void); //; ;
bit init_ds18b20(void);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
#endif
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;
}
这里的延时是进行修改过的,扩大了十倍