DS18B20設計1個溫度監測系統
項目要求
采集環境溫度(0~99.9℃)顯示在前3位數位管上。
原理圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB5EMRpmTwkERNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyYTOwEzN1IjMzEjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
代碼編寫
#include <reg52.h>
#include <intrins.h> //包含函數庫,用于調用_nop_()函數
#define uchar unsigned char
#define uint unsigned int
bit flag; //定義标志位,傳回值作為是否存在的标志
sbit ds=P2^2;
sbit dula=P2^6;
sbit wela=P2^7;
uint temp; //16位變量
uchar code table_du[]=
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayus(uint t) //us級延時函數
{
while(t--);
}
void delay_ms(uchar z) //ms級延時
{
uchar i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void ds_reset() //複位初始化程式
{
ds=1; //先将資料線置高電平1
delayus(5); //如果11.0592M,大約為66us
ds=0; //資料線拉低到低電平0
delayus(80); //延時約700us
ds=1; //資料線拉到高電平1
delayus(14); //延時約154us
if(ds==0)
flag=1; //标志位,表示18B20存在
else
flag=0;
delayus(20); //約200us
}
bit ds_read_bit() //讀取1位時序,用于下面讀位元組
{
bit dat; //定義一個位變量,作為傳回值
ds=0; //拉低總線到0
_nop_(); //一個機器周期,大約1us
_nop_(); //延時約1us,加上上面的總計約2us
ds=1; //主機采樣
_nop_(); //延時用于穩定資料
dat=ds; //ds的電平的高低即為資料
delayus(10); //約100us
return dat; //這裡之是以有傳回值是因為單片機從DS18B20讀出資料時,DS18B20要傳回資料給到單片機。
} //寫操作裡是因為單片機直接寫資料到DS18B20,不需要DS18B20傳回值。
uchar ds_read_byte() //讀1個位元組,即單片機從DS18B20讀資料,需要DS18B20傳回資料
{
uchar i,j,k;
for(i=0;i<8;i++) //1個位元組由8位組成,将讀的位資料一位一位的移入,
{ //移入8位就組成1位元組
j=ds_read_bit(); //例如:j=1010 0101
k=(j<<7)|(k>>1); //Ex: j=1010 0101|k=0000 0000=1010 0101
}
return k; //循環8次傳回的值為j=1010 0101
}
void ds_write_byte(uchar dat) //寫1個位元組,dat即為單片機向DS18B20中寫的資料
{
uchar i;
for(i=0;i<8;i++)
{
ds=0; //資料線先置低電平
_nop_(); //約1us
_nop_();
ds=dat&0x01; //每次隻能寫1位,即dat的最低位,資料讀寫均按照從低位到高位
delayus(6); //延時約70us
ds=1; //将資料線拉到高電平1,準備下次的寫入
dat=dat>>1; //右移1位
}
delayus(6); //約70us
}
uint read_temperature() //單片機讀取DS18B20溫度值
{
uchar a,b;
ds_reset(); //初始化
ds_write_byte(0xcc); //ROM操作指令,跳過ROM
ds_write_byte(0xbe); //存儲器操作指令,讀取溫度指令
a=ds_read_byte(); //執行/資料,低8位,a為8位變量。例a=0101 1010
b=ds_read_byte(); //高8位, b為8位變量。例b=1010 0101
temp=b; //16位變量存放溫度值(高8位+低8位)将b的值賦給temp。由于temp為16位變量,是以高位補0。temp=0000 0000 1010 0101
temp=temp<<8; //temp<<8為1010 0101 0000 0000
temp=temp|a; //temp|a為1010 0101 0101 1010
temp=temp*0.0625*10+0.5;//按照固定公式進行轉換運算,加0.5是用于四舍五入
return temp; //傳回溫度值
}
void display(uint temp) //數位管顯示程式
{ //将溫度值得每位分開進行單獨顯示
P0=table_du[temp/100]; //顯示十位
dula=1;
dula=0;
P0=0xfe; //點亮第一個數位管
wela=1;
wela=0;
delay_ms(10);
P0=table_du[temp%100/10]|0x80;//添加小數點,使dp=1.即dp g f e d c b a =1000 0000
dula=1;
dula=0;
P0=0xfd;
wela=1;
wela=0;
delay_ms(10);
P0=table_du[temp%100%10];
dula=1;
dula=0;
P0=0xfb;
wela=1;
wela=0;
delay_ms(10);
}
void main()
{
while(1)
{
ds_reset(); //初始化
ds_write_byte(0xcc); //跳過ROM
ds_write_byte(0x44); //啟動溫度轉換
display(read_temperature());
}
}