#include <reg52.h>
#include <intrins.h>
sbit IO_18B20 = P3^2; //DS18B20通信引腳
/* 軟件延時函數,延時時間(t*10)us */
void DelayX10us(unsigned char t)
{
do {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
} while (--t);
}
/* 復位總線,獲取存在脈沖,以啟動一次讀寫操作 */
bit Get18B20Ack()
{
bit ack;
EA = 0; //禁止總中斷
IO_18B20 = 0; //產生500us復位脈沖
DelayX10us(50);
IO_18B20 = 1;
DelayX10us(6); //延時60us
ack = IO_18B20; //讀取存在脈沖
while(!IO_18B20); //等待存在脈沖結束
EA = 1; //重新使能總中斷
return ack;
}
/* 向DS18B20寫入一個字節,dat-待寫入字節 */
void Write18B20(unsigned char dat)
{
unsigned char mask;
EA = 0; //禁止總中斷
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次移出8個bit
{
IO_18B20 = 0; //產生2us低電平脈沖
_nop_();
_nop_();
if ((mask&dat) == 0) //輸出該bit值
IO_18B20 = 0;
else
IO_18B20 = 1;
DelayX10us(6); //延時60us
IO_18B20 = 1; //拉高通信引腳
}
EA = 1; //重新使能總中斷
}
/* 從DS18B20讀取一個字節,返回值-讀到的字節 */
unsigned char Read18B20()
{
unsigned char dat;
unsigned char mask;
EA = 0; //禁止總中斷
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次采集8個bit
{
IO_18B20 = 0; //產生2us低電平脈沖
_nop_();
_nop_();
IO_18B20 = 1; //結束低電平脈沖,等待18B20輸出數據
_nop_(); //延時2us
_nop_();
if (!IO_18B20) //讀取通信引腳上的值
dat &= ~mask;
else
dat |= mask;
DelayX10us(6); //再延時60us
}
EA = 1; //重新使能總中斷
return dat;
}
/* 啟動一次18B20溫度轉換,返回值-表示是否啟動成功 */
bit Start18B20()
{
bit ack;
ack = Get18B20Ack(); //執行總線復位,并獲取18B20應答
if (ack == 0) //如18B20正確應答,則啟動一次轉換
{
Write18B20(0xCC); //跳過ROM操作
Write18B20(0x44); //啟動一次溫度轉換
}
return ~ack; //ack==0表示操作成功,所以返回值對其取反
}
/* 讀取DS18B20轉換的溫度值,返回值-表示是否讀取成功 */
bit Get18B20Temp(int *temp)
{
bit ack;
unsigned char LSB, MSB; //16bit溫度值的低字節和高字節
ack = Get18B20Ack(); //執行總線復位,并獲取18B20應答
if (ack == 0) //如18B20正確應答,則讀取溫度值
{
Write18B20(0xCC); //跳過ROM操作
Write18B20(0xBE); //發送讀命令
LSB = Read18B20(); //讀溫度值的低字節
MSB = Read18B20(); //讀溫度值的高字節
*temp = ((int)MSB << 8) + LSB; //合成為16bit整型數
}
return ~ack; //ack==0表示操作應答,所以返回值為其取反值
}
|