目录
1、DS18B20原理图
2、获取温度的操作步骤
3、温度传感器显示(法一)
4、温度传感器显示(法二)
DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
其中P14与DQ数据线连接。
初始化操作:
(1) 先将数据线置高电平"1"。
(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
(3) 数据线拉到低电平"0"。
(4) 延时750微秒(该时间的时间范围可以从480到960微秒)。
(5) 数据线拉到高电平"1"。
(6) 延时等待(如果初始化成功则在15到60微秒时间之内产生一个由DS18B20所返回的低电平"0"。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7) 若CPU读到了数据线上的低电平"0"后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480秒。
(8) 将数据线再次拉高到高电平"1"后结束。
写操作:
(1) 数据线先置低电平"0"。
(2) 延时确定的时间为15微秒。
(3) 按从低位到高位的顺序发送字节(一次只发送一位)。
(4) 延时时间为45微秒。
(5) 将数据线拉到高电平。
(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7) 最后将数据线拉高。
读操作:
(1)将数据线拉高"1"。
(2)延时2微秒。
(3)将数据线拉低"0"。
(4)延时3微秒。
(5)将数据线拉高"1"。
(6)延时5微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时60微秒。
上述操作代码部分不需要自己写,官方会给出驱动文件,里面有单总线延时函数、初始化操作、写操作、读操作。
官方驱动文件:
#include "onewire.h"
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
while(t--);
}
//DS18B20芯片初始化
bit Init_DS18B20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从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);
}
return dat;
}
重要的操作指令
CCH:跳过ROM指令,忽略64位ROM地址,直接向DS18B20发起各种温度转换指令。
44H:温度转换指令,启动DS18B20进行温度转换,转换时间最长为500ms(典型值为200ms),结果保存在高速RAM中。
BEH:读暂存器指令,读取高速暂存存储器9个字节的内容。
具体步骤
STEP1:DS18B20复位操作 init_ds18b20();
STEP2:跳过ROM操作指令 Write_DS18B20(0xCC);
STEP3:延时,等待温度装换完成 Write_DS18B20(0x44);
STEP4:复位,开始下一轮操作 init_ds18b20();
STEP5:跳过ROM操作指令 Write_DS18B20(0xCC);
STEP6:读取暂存器中的数据 Write_DS18B20(0xBE);
STEP7:读取温度数据低与高8位字节 low = Read_DS18B20(); high = Read_DS18B20();
获取温度的代码
uchar temperature(void){
uchar low,high;
char temp;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay500us();
Delay500us();
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp|=(low>>4);
return temp;
}
对于获取温度的函数需要自己写,上述代码获取温度精确度为1,一般来说都是整数温度,如果有精确度要求可以自行修改温度获取函数来完成竞赛题目要求。
下面的代码是结合给出的驱动文件,部分修改得出的如下(整数温度值),这个是把驱动结合后形成的一个.c文件。
#include
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P1^4;
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar f1,f2,f3,f4,f5,f6,f7,f8;
void delay();
void allinit();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
uchar temperature(void);
void init_ds18b20(void);
void Delay100us();
void Delay500us();
void main(){
uchar T1;
allinit();
f1=11;f2=11;f3=11,f4=11,f5=11,f6=0,f7=0,f8=0;
while(1){
T1=temperature();
f6=T1/100;
f7=T1%100/10;
f8=T1%10;
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void Delay100us()
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
void Delay500us()
{
unsigned char i, j;
_nop_();
_nop_();
i = 6;
j = 93;
do
{
while (--j);
} while (--i);
}
void delay(){
int i,j;
for(i=0;i<1;i++)
for(j=0;j<400;j++);
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay100us();
DQ = 1;
dat >>= 1;
}
Delay100us();
}
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==1)
{
dat |= 0x80;
}
Delay100us();
}
return dat;
}
void init_ds18b20(void)
{
DQ=0;
Delay500us();
DQ=1;
Delay500us();
}
uchar temperature(void){
uchar low,high;
char temp;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay500us();
Delay500us();
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp|=(low>>4);
return temp;
}
最后,对于温度传感器来说,只要明白获取温度的函数,记着重要的操作指令、步骤,这一部分大致就这些内容。
对于官方给出的驱动,可以分模块实现功能,下面给出分模块实现温度显示:
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台
日 期: 2011-8-9
*/
#include "onewire.h"
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
t=t*12;
while(t--);
}
//DS18B20芯片初始化
bit Init_DS18B20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从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);
}
return dat;
}
unsigned char Get_wendu(){
unsigned char high,low;
unsigned char temp;
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(low>>4)|(high<<4);
return temp;
}
onewire.h
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include "stc15f2k60s2.h"
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char Get_wendu();
#endif
text.c
#include
#include"onewire.h"
#define uchar unsigned char
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar tem;
uchar f1,f2,f3,f4,f5,f6,f7,f8;
void delay();
void allinit();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void main(){
allinit();
while(1){
tem=Get_wendu();
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;
f7=tem/10;
f8=tem%10;
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void delay(){
unsigned char i,j;
for(i=0;i<2;i++)
for(j=0;j<200;j++);
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
结果与体会:
对于onewire.c文件来说,增加了一个温度获取函数,又对延时函数进行放大。
对于onewire.h文件来说,增加了温度获取函数的说明。