视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
ds18b20详细解释程序
2025-09-24 00:08:55 责编:小OO
文档
#include

#include

#define uchar unsigned char

#define uint unsigned int

sbit DQ = P2^2; //数据口define interface

sbit dula = P2^6; //数码管段选

sbit wela = P2^7; //数码管位选

uint temp; //温度值 variable of temperature

//不带小数点

unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//带小数点

unsigned char code table1[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

/*************精确延时函数*****************/

void delay(unsigned char i)

{

while(--i);

}

/******************************************

此延时函数针对的是12Mhz的晶振

delay(0):延时518us 误差:518-2*256=6

delay(1):延时7us (原帖写"5us"是错的)

delay(10):延时25us 误差:25-20=5

delay(20):延时45us 误差:45-40=5

delay(100):延时205us 误差:205-200=5

delay(200):延时405us 误差:405-400=5

*******************************************/

/*****************DS18B20******************/

void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command

{

DQ = 1; //DQ复位,不要也可行。

delay(1); //稍做延时

DQ = 0; //单片机拉低总线

delay(250); //精确延时,维持至少480us

DQ = 1; //释放总线,即拉高了总线

delay(100); //此处延时有足够,确保能让DS18B20发出存在脉冲。

}

uchar Read_One_Byte() //读取一个字节的数据read a byte date

//读数据时,数据以字节的最低有效位先从总线移出

{

uchar i = 0;

uchar dat = 0;

for(i=8;i>0;i--)

{

DQ = 0; //将总线拉低,要在1us之后释放总线

//单片机要在此下降沿后的15us内读数据才会有效。

_nop_(); //至少维持了1us,表示读时序开始

dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。

DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上

delay(1); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分

if(DQ) //控制器进行采样

{

dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0

}

delay(10); //此延时不能少,确保读时序的长度60us。

}

return (dat);

}

void Write_One_Byte(uchar dat)

{

uchar i = 0;

for(i=8;i>0;i--)

{

DQ = 0; //拉低总线

_nop_(); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始

DQ = dat&0x01;

//从字节的最低位开始传输

//指令dat的最低位赋予给总线,必须在拉低总线后的15us内,

//因为15us后DS18B20会对总线采样。

delay(10); //必须让写时序持续至少60us

DQ = 1; //写完后,必须释放总线,

dat >>= 1;

delay(1);

}

}

uint Get_Tmp() //获取温度get the temperature

{

float tt;

uchar a,b;

Init_Ds18b20(); //初始化

Write_One_Byte(0xcc); //忽略ROM指令

Write_One_Byte(0x44); //温度转换指令

Init_Ds18b20(); //初始化

Write_One_Byte(0xcc); //忽略ROM指令

Write_One_Byte(0xbe); //读暂存器指令

a = Read_One_Byte(); //读取到的第一个字节为温度LSB

b = Read_One_Byte(); //读取到的第一个字节为温度MSB

temp = b; //先把高八位有效数据赋于temp

temp <<= 8; //把以上8位数据从temp低八位移到高八位

temp = temp|a; //两字节合成一个整型变量

tt = temp*0.0625; //得到真实十进制温度值

//因为DS18B20可以精确到0.0625度

//所以读回数据的最低位代表的是0.0625度

temp = tt*10+0.5; //放大十倍

//这样做的目的将小数点后第一位也转换为可显示数字

//同时进行一个四舍五入操作。

return temp;

}

/****************数码码动态显示函数**************/

void Display(uint temp) //显示程序

{

uchar A1,A2,A3;

A1 = temp/100; //百位

A2 = temp%100/10; //十位

A3 = temp%10; //个位

dula = 0;

P0 = table[A1]; //显示百位

dula = 1; //打开段选,对应74573的锁存位,高电平不锁存

dula = 0;

wela = 0;

P0 = 0x7e;

wela = 1; //打开位选

wela = 0;

delay(0);

dula = 0;

P0 = table1[A2]; //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)

dula = 1;

dula = 0;

wela = 0;

P0 = 0x7d;

wela = 1;

wela = 0;

delay(0);

P0 = table[A3]; //显示个位

dula = 1;

dula = 0;

P0 = 0x7b;

wela = 1;

wela = 0;

delay(0);

}

void main()

{

while(1)

{

Display(Get_Tmp());

}

}下载本文

显示全文
专题