?? ds18b20.c
字號:
//文件名:ds18b20.c
//功能:實現溫度顯示
//硬件連接:外部電源供電,且只有1個DS18B20
//原理:單總線協議(讀取溫度七步驟,如程序注釋)
//注意:此程序晶振為12M,其他晶振需跟據DS18B20資料修改
//編寫:王曉榮
//日期:20070626
////////////////////////////////////////////////////////////////////////////
#include <REGX51.H>
#include <intrins.h> // 聲明_nop_() 便于實現延時
#define DS18B20 P1_0
unsigned char xdata LEDSEG _at_ 0xfeff; //P2.0
unsigned char xdata LEDBIT _at_ 0xfdff; //P2.1
unsigned char code LEDMAP[] =
{
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
0x07, 0x7f, 0x6f, 0x00, 0x79, 0x46, 0x40,
// 滅 "E" "+" "-"
};
bit DS18B20_FLG = 0; //“1”:DS18B20存在 ;“0”:不存在
bit TEMP_FLG = 0; //“1”:溫度為負
bit T1S_FLG = 0; //“1”:1秒鐘到
unsigned int t1s;
unsigned char LEDBuf[6];
//定時中斷
Timer0() interrupt 1
{
t1s++;
if(4000 == t1s)
{
t1s =0;
T1S_FLG = 1;
}
}
void delay(unsigned int i)
{
while(i--);
}
//顯示子函數
display()
{
unsigned char i;
unsigned char outbit;
outbit = 0x01; // 從右邊開始顯示
for (i = 0; i < 4; i++)
{
LEDBIT = 0x00; // 關所有LED
LEDSEG = LEDMAP[LEDBuf[i]];
LEDBIT = outbit;
delay(100);
outbit <<= 1; // 顯示下一位
}
}
/////////////////////////////////////////////////////////////////////////////
//DS18B20驅動
//初始化DS18B20步驟:
// 1)總線拉低,并延時480us-960us
// 2)總線拉高,等待回應,如DS18B20為“0”則初始化成功,
// 如等待60us仍無回應,則DS18B20不存在
Init_DS18B20(void)
{
bit re = 0;
unsigned char temp = 30;
DS18B20 = 1;
_nop_(); //無需精確
_nop_();
DS18B20 = 0; //拉低
delay(80); // ★務必在480us-960us之間
DS18B20 = 1; //拉高總線
delay(1); //無需精確
while(temp--) //等待60us以上
{
re = DS18B20; //如果x=0則初始化成功
if(0 == re)
{
DS18B20_FLG = 1;
delay(20); //無需精確
return(0);
}
}
}
//讀DS18B20一個字節
unsigned char Read_DS18B20(void)
{
unsigned char i = 0;
unsigned char d = 0;
for (i=8;i>0;i--)
{
DS18B20 = 0; // 給脈沖信號
d >>= 1;
_nop_();
DS18B20 = 1; // 給脈沖信號
_nop_(); // 需延時10us-14us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(DS18B20 == 1)
{
d = d | 0x80;
}
delay(10); // 需延時60us以上
}
delay(10);
return(d);
}
//寫一個字節
Write_DS18B20(unsigned char d)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DS18B20 = 1;
_nop_();
_nop_();
DS18B20 = 0;
_nop_(); // 需延時15us-60us
_nop_();
_nop_();
_nop_(); // ?奇怪:當此處延時超過30us時,會出錯
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
DS18B20 = d & 0x01;
delay(7); // 需延時60us-120us
d >>= 1;
}
DS18B20 = 1;
delay(7);
}
//溫度返回值被放大100倍
unsigned int TurnTemp(unsigned int temp)
{
int t;
if(temp > 32768) //當讀取的溫度為負時
{
t = (~temp + 1) * 25 / 4;
TEMP_FLG = 1;
}
else //當讀取的溫度為正時
{
t = temp * 25 / 4;
TEMP_FLG = 0;
}
return(t);
}
//讀取溫度
int ReadTemp(void)
{
unsigned char tempLowChar = 0;
unsigned char tempHighChar = 0;
unsigned int tempInt = 0;
int temp = 0;
DS18B20_FLG = 0;
Init_DS18B20(); //步驟1:初始化
if(DS18B20_FLG == 0) //如果沒有檢測到DS18B20返回
{
return(0);
}
Write_DS18B20(0xCC); //步驟2:跳過讀序號操作(單個DS18B20適用)
Write_DS18B20(0x44); //步驟3:啟動溫度轉換
TL0 = 256 - 250; //利用定時器實現1s延時
TH0 = TL0;
TR0 = 1;
T1S_FLG = 0;
while(!T1S_FLG) //步驟4:等待溫度轉換完成(必須大于500ms)
{
display();
}
TR0 = 0;
DS18B20_FLG = 0;
Init_DS18B20(); //步驟5:初始化
if(DS18B20_FLG == 0) //如果沒有檢測到DS18B20返回
{
return(0);
}
Write_DS18B20(0xCC); //步驟6:跳過讀序號操作(單個DS18B20適用)
Write_DS18B20(0xBE); //步驟7:讀取溫度寄存器設置(共可讀9個寄存器,前兩個就是溫度)
tempLowChar = Read_DS18B20(); //步驟8:讀取溫度數據低8位
tempHighChar = Read_DS18B20(); //步驟8:讀取溫度數據高4位
tempInt = tempHighChar;
tempInt <<= 8;
tempInt = tempInt | tempLowChar;
temp = TurnTemp(tempInt);
return(temp);
}
//DS18B20驅動
/////////////////////////////////////////////////////////////////////////////
//實現四位LED溫度顯示,其中最高位LED顯示溫度正負,最低位為溫度的一位小數
main()
{
unsigned int t =0;
IE = 0x82; //開1#中斷
TMOD = 0x02; //定時工作方式2
while(1)
{
t = ReadTemp();//讀溫度
if(DS18B20_FLG == 0)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 0; //顯示“E0”
}
else
{
if(TEMP_FLG)
{
if(t > 5500)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 1; //顯示“E1”
}
else
{
LEDBuf[3] = 13; //顯示“-”
LEDBuf[2] = t/1000; //顯示溫度的十位
LEDBuf[1] = (t/100)%10; //顯示溫度的個位
LEDBuf[0] = (t/10)%10; //顯示溫度的小數位
}
}
else
{
if(t > 20000)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 1; //顯示“E2”
}
else
{
LEDBuf[3] = 12; //顯示“+”
LEDBuf[2] = t/1000; //顯示溫度的十位
LEDBuf[1] = (t/100)%10; //顯示溫度的個位
LEDBuf[0] = (t/10)%10; //顯示溫度的小數位
}
}
}
display();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -