㈠ 單片機DS18B20溫度計C語言程序
;單片機DS18B20溫度計C語言程序
;標簽:單片機 c語言 ds18b20 溫度計 51 mcu
http://www.dzkfw.com.cn
#include<reg51.h>
#include<intrins.h>
#include <math.H> //要用到取絕對值函數abs()
//通過DS18B20測試當前環境溫度, 並通過數碼管顯示當前溫度值, 目前顯示範圍: -55~ +125度
sbit wela = P2^7; //數碼管位選
sbit la = P2^6; //數碼管段選
sbit ds = P2^2;
int tempValue;
//0-F數碼管的編碼(共陽極)
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//0-9數碼管的編碼(共陽極), 帶小數點
unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,
0x19, 0x12, 0x02,0x78, 0x00, 0x10};
//延時函數, 對於11.0592MHz時鍾, 例i=10,則大概延時10ms.
void delay(unsigned int i)
{
unsigned int j;
while(i--)
{
for(j = 0; j < 125; j++);
}
}
//初始化DS18B20
//讓DS18B20一段相對長時間低電平, 然後一段相對非常短時間高電平, 即可啟動
void dsInit()
{
//對於11.0592MHz時鍾, unsigned int型的i, 作一個i++操作的時間大於?us
unsigned int i;
ds = 0;
i = 100; //拉低約800us, 符合協議要求的480us以上
while(i>0) i--;
ds = 1; //產生一個上升沿, 進入等待應答狀態
i = 4;
while(i>0) i--;
}
void dsWait()
{
unsigned int i;
while(ds);
while(~ds); //檢測到應答脈沖
i = 4;
while(i > 0) i--;
}
//向DS18B20讀取一位數據
//讀一位, 讓DS18B20一小周期低電平, 然後兩小周期高電平,
//之後DS18B20則會輸出持續一段時間的一位數據
bit readBit()
{
unsigned int i;
bit b;
ds = 0;
i++; //延時約8us, 符合協議要求至少保持1us
ds = 1;
i++; i++; //延時約16us, 符合協議要求的至少延時15us以上
b = ds;
i = 8;
while(i>0) i--; //延時約64us, 符合讀時隙不低於60us要求
return b;
}
//讀取一位元組數據, 通過調用readBit()來實現
unsigned char readByte()
{
unsigned int i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)
{
j = readBit();
//最先讀出的是最低位數據
dat = (j << 7) | (dat >> 1);
}
return dat;
}
//向DS18B20寫入一位元組數據
void writeByte(unsigned char dat)
{
unsigned int i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)
{
b = dat & 0x01;
dat >>= 1;
//寫"1", 將DQ拉低15us後, 在15us~60us內將DQ拉高, 即完成寫1
if(b)
{
ds = 0;
i++; i++; //拉低約16us, 符號要求15~60us內
ds = 1;
i = 8; while(i>0) i--; //延時約64us, 符合寫時隙不低於60us要求
}
else //寫"0", 將DQ拉低60us~120us
ds = 0;
i = 8; while(i>0) i--; //拉低約64us, 符號要求
ds = 1;
i++; i++; //整個寫0時隙過程已經超過60us, 這里就不用像寫1那樣, 再延時64us了
}
}
//向DS18B20發送溫度轉換命令
void sendChangeCmd()
{
dsInit(); //初始化DS18B20, 無論什麼命令, 首先都要發起初始化
dsWait(); //等待DS18B20應答
delay(1); //延時1ms, 因為DS18B20會拉低DQ 60~240us作為應答信號
writeByte(0xcc); //寫入跳過序列號命令字 Skip Rom
writeByte(0x44); //寫入溫度轉換命令字 Convert T
}
//向DS18B20發送讀取數據命令
void sendReadCmd()
{
dsInit();
dsWait();
delay(1);
writeByte(0xcc); //寫入跳過序列號命令字 Skip Rom
writeByte(0xbe); //寫入讀取數據令字 Read Scratchpad
}
//獲取當前溫度值
int getTmpValue()
{
unsigned int tmpvalue;
int value; //存放溫度數值
float t;
unsigned char low, high;
sendReadCmd();
//連續讀取兩個位元組數據
low = readByte();
high = readByte();
//將高低兩個位元組合成一個整形變數
//計算機中對於負數是利用補碼來表示的
//若是負值, 讀取出來的數值是用補碼表示的, 可直接賦值給int型的
value
tmpvalue = high;
tmpvalue <<= 8;
tmpvalue |= low;
value = tmpvalue;
//使用DS18B20的默認解析度12位, 精確度為0.0625度, 即讀回數據的最低位代表0.0625度
t = value * 0.0625;
//將它放大100倍, 使顯示時可顯示小數點後兩位, 並對小數點後第三進行4舍5入
//如t=11.0625, 進行計數後, 得到value = 1106, 即11.06 度
//如t=-11.0625, 進行計數後, 得到value = -1106, 即-11.06 度
value = t * 100 + (value > 0 ? 0.5 : -0.5); //大於0加0.5, 小於0減0.5
return value;
}
unsigned char const timeCount = 3; //動態掃描的時間間隔
//顯示當前溫度值, 精確到小數點後一位
//若先位選再段選, 由於IO口默認輸出高電平, 所以當先位選會使數碼管出現亂碼
void display(int v)
{
unsigned char count;
unsigned char datas[] = {0, 0, 0, 0, 0};
unsigned int tmp = abs(v);
datas[0] = tmp / 10000;
datas[1] = tmp % 10000 / 1000;
datas[2] = tmp % 1000 / 100;
datas[3] = tmp % 100 / 10;
datas[4] = tmp % 10;
if(v < 0)
{
//關位選, 去除對上一位的影響
P0 = 0xff;
wela = 1; //打開鎖存, 給它一個下降沿量
wela = 0;
//段選
P0 = 0x40; //顯示"-"號
la = 1; //打開鎖存, 給它一個下降沿量
la = 0;
//位選
P0 = 0xfe;
wela = 1; //打開鎖存, 給它一個下降沿量
wela = 0;
delay(timeCount);
}
for(count = 0; count != 5; count++)
{
//關位選, 去除對上一位的影響
P0 = 0xff;
wela = 1; //打開鎖存, 給它一個下降沿量
wela = 0;
//段選
if(count != 2)
{
P0 = table[datas[count]]; //顯示數字
}
else
{
P0 = tableWidthDot[datas[count]]; //顯示帶小數點數字
}
la = 1; //打開鎖存, 給它一個下降沿量
la = 0;
//位選
P0 = _crol_(0xfd, count); //選擇第(count + 1) 個數碼管
wela = 1; //打開鎖存, 給它一個下降沿量
wela = 0;
delay(timeCount);
}
}
void main()
{
unsigned char i;
while(1)
{
//啟動溫度轉換
sendChangeCmd();
//顯示5次
for(i = 0; i < 40; i++)
{
display(tempValue);
}
tempValue = getTmpValue();
}
http://www.dzkfw.com.cn/myxin/51c_language.chm 單片機c語言最好用的教程
㈡ 51單片機兩個I/O口分別接ds18b20程序
//DS從機程序
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SLAVE 0x01
#define BN 6
sbit LCD_RS = P2^; /*定義LCD控制埠*/
sbit LCD_RW = P2^6;
sbit LCD_EN = P2^7;
sbit DS1=P1^0;
sbit DS2=P1^1;
sbit key3=P3^5;
sbit tem=P3^3;
sbit win=P3^4;
sbit key1=P3^6;
sbit key2=P3^7;
uint temp1,temp2,tempH,tempL; // variable of temperature
uchar flag1,aa,we;
uchar A1,A2,A3,A4,B1,B2,B3,B4; // sign of the result positive or negative
uchar dis1[16]={76,45,84,'0','0','.','0',32,32,72,45,84,'0','0','.','0'};
uchar dis2[16]={48,49,32,'0','0','.','0',32,32,48,50,32,'0','0','.','0'};
uchar code tab[] = {'0','1','2','3','4','5','6','7','8','9'};
uchar trbuf[6];
bit tready;
bit rready;
void str(void);
void sre(void);
void delay(int ms)
{
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/*******************************************************************/
/* */
/*檢查LCD忙狀態 */
/*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數據。 */
/* */
/*******************************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0&0x80);
LCD_EN = 0;
return result;
}
/*******************************************************************/
/* */
/*寫指令數據到LCD */
/*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */
/* */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*寫顯示數據到LCD */
/*RS=H,RW=L,E=高脈沖,D0-D7=數據。 */
/* */
/*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/* 設定顯示位置 */
/* */
/*******************************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos|0x80); //數據指針=80+地址變數
}
/*******************************************************************/
/* */
/* LCD初始化設定 */
/* */
/*******************************************************************/
void lcd_init()
{
lcd_wcmd(0x38); //16*2顯示,5*7點陣,8位數據
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //顯示開,關游標
delay(5);
lcd_wcmd(0x06); //移動游標
delay(5);
lcd_wcmd(0x01); //清除LCD的顯示內容
delay(5);
lcd_wcmd(0x06); //向右移動游標
delay(5);
}
/*******************************************************************/
/* */
/* 閃動子程序 */
/* */
/*******************************************************************/
void flash()
{
delay(600); //控制停留時間
lcd_wcmd(0x08); //關閉顯示
delay(200); //延時
lcd_wcmd(0x0c); //開顯示
delay(200); //延時
lcd_wcmd(0x08); //關閉顯示
delay(200); //延時
lcd_wcmd(0x0c); //開顯示
delay(200);
}
/*void delay(uint count) //delay
{
uint i;
while(count)
{
i=100;
while(i>0)
i--;
count--;
}
} */
///////功能:串口初始化,波特率9600,方式1///////
void Init(void)
{
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
TR1=1;
SCON=0xf0;
ES=1;
EA=1;
}
void dsreset(uchar DS) //send reset and initialization command 18B20復位,初始化函數
{
uint i;
if(DS==1)
{
DS1=0;
i=103;
while(i>0)i--;
DS1=1;
i=4;
while(i>0)i--;
}
if(DS==2)
{
DS2=0;
i=103;
while(i>0)i--;
DS2=1;
i=4;
while(i>0)i--;
}
}
bit tmpreadbit(uchar DS) //read a bit 讀DS2 1位數據函數
{
uint i;
bit dat;
if(DS==1)
{
DS1=0;i++; //i++ for delay
DS1=1;i++;i++;
dat=DS1;
i=8;while(i>0)i--;
}
if(DS==2)
{
DS2=0;i++; //i++ for delay
DS2=1;i++;i++;
dat=DS2;
i=8;while(i>0)i--;
}
return (dat);
}
uchar tmpread(uchar DS) //read a byte date 讀1位元組函數
{
uchar i,j,dat;
dat=0;
if(DS==1)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(1);
dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好一個位元組在DAT里
}
}
if(DS==2)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(2);
dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好一個位元組在DAT里
}
}
return(dat);
}
void tmpwritebyte(uchar dat,uchar DS) //write a byte to ds18b20 向1820寫一個位元組數據函數
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(DS==1)
{
if(testb) //write 1
{
DS1=0;
i++;i++;
DS1=1;
i=8;while(i>0)i--;
}
else
{
DS1=0; //write 0
i=8;while(i>0)i--;
DS1=1;
i++;i++;
}
}
if(DS==2)
{
if(testb) //write 1
{
DS2=0;
i++;i++;
DS2=1;
i=8;while(i>0)i--;
}
else
{
DS2=0; //write 0
i=8;while(i>0)i--;
DS2=1;
i++;i++;
}
}
}
}
void tmpchange(uchar DS) //DS18B20 begin change 開始獲取數據並轉換
{
if(DS==1)
{
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1); // address all drivers on bus 寫跳過讀ROM指令
tmpwritebyte(0x44,1);
} // initiates a single temperature conversion 寫溫度轉換指令
if(DS==2)
{
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2); // address all drivers on bus 寫跳過讀ROM指令
tmpwritebyte(0x44,2);
} // initiates a single temperature conversion 寫溫度轉換指令
}
uint tmp1(void) //get the temperature 讀取寄存器中存儲的溫度數據
{
float tt;
uchar a,b;
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1);
tmpwritebyte(0xbe,1);
a=tmpread(1); //讀低8位
b=tmpread(1); //讀高8位
temp1=b;
temp1<<=8; //two byte compose a int variable 兩個位元組組合為1個字
temp1=temp1|a;
tt=temp1*0.0625; //溫度在寄存器中是12位,解析度是0.0625
temp1=tt*10+0.5; //乘10表示小數點後只取1位,加0.5是四折五入
//temp1=temp1+5; //誤差補償
return temp1;
}
uint tmp2( void) //get the temperature 讀取寄存器中存儲的溫度數據
{
float tt;
uchar a,b;
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2);
tmpwritebyte(0xbe,2);
a=tmpread(2); //讀低8位
b=tmpread(2); //讀高8位
temp2=b;
temp2<<=8; //two byte compose a int variable 兩個位元組組合為1個字
temp2=temp2|a;
tt=temp2*0.0625; //溫度在寄存器中是12位,解析度是0.0625
temp2=tt*10+0.5; //乘10表示小數點後只取1位,加0.5是四折五入
//temp2=temp2+5; //誤差補償
return temp2;
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
uchar display(uint temp1,uint temp2) //顯示程序
{
uchar i;
A1=temp1/100;
A2=temp1%100/10;
A3=temp1%100%10;
B1=temp2/100;
B2=temp2%100/10;
B3=temp2%100%10;
trbuf[0]=A1;
trbuf[1]=A2;
trbuf[2]=A3;
trbuf[3]=B1;
trbuf[4]=B2;
trbuf[5]=B3;
dis1[3]=tab[tempL*10/100];
dis1[4]=tab[tempL*10%100/10];
dis1[6]=tab[tempL*10%100%10];
dis1[12]=tab[tempH*10/100];
dis1[13]=tab[tempH*10%100/10];
dis1[15]=tab[tempH*10%100%10];
dis2[3]=tab[A1];
dis2[4]=tab[A2];
dis2[6]=tab[A3];
dis2[12]=tab[B1];
dis2[13]=tab[B2];
dis2[15]=tab[B3];
delay(1);
lcd_pos(0); //設置顯示位置為第一行的第1個字元
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis1[i]);
}
delay(2);
lcd_pos(0x40);
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis2[i]);
}
return (A1,A2,A3,B1,B2,B3);
}
void TemC()
{
if(temp1<=(tempL*10)||temp2<=(tempL*10)) tem=0;
else tem=1;
if (temp1>=(tempH*10)||temp2>=(tempH*10)) win=0;
else win=1;
}
uchar chan()
{
if(key1==0)
{
tempL++;
while(key1==0);
if(tempL>35)
tempL=0;
}
if(key2==0)
{
tempH++;
while(key2==0);
if(tempH>35)
tempH=0;
}
return (tempH,tempL);
}
/******************************************************************************/
void main()
{ //uchar a;
//uchar i;
delay(10);
lcd_init();
Init();
tempH=35;
tempL=15;
while(1)
{
tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);
tready=1;
rready=1;
}
}
void ssio(void)interrupt 4
{
uchar a;
RI=0;
ES=0;
if(SBUF!=SLAVE)
{
ES=1;
goto reti;
}
SM2=0;
SBUF=SLAVE;
while(TI!=1);
TI=0;
while(RI!=1);
RI=0;
if(RB8==1)
{
SM2=1;
ES=1;
goto reti;
}
a=SBUF;
if(a==0x02)
{
if(tready==1)
SBUF=0x02;
else
SBUF=0x00;
while(TI!=1);
TI=0;
str();
goto reti;
}
else
{
SBUF=0x08;
while(TI!=1);
TI=0;
SM2=1;
ES=1;
}
reti:RI=0;
SM2=1;
ES=1;
}
void str(void)
{
uchar i;
tready=0;
while(1)
{
tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);
for(i=0;i<BN;i++)
{
SBUF=trbuf[i];
while(TI!=1);
TI=0;
}
while(RI!=1);
RI=0;
if(RB8==1)goto loop;
}
loop:SM2=1;
ES=1;
}
㈢ ds18b20的c語言程序
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P3^3; //定義DS18B20介面
int temp;
uchar flag1;
void display(unsigned char *lp,unsigned char lc);//數字的顯示函數;lp為指向數組的地址,lc為顯示的個數
void delay();//延時子函數,5個空指令
code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x08,0x00};
//共陰數碼管 0-9 - _ 空 表
unsigned char l_tmpdate[8]={0,0,10,0,0,0,0,0};//定義數組變數,並賦值1,2,3,4,5,6,7,8,就是本程序顯示的八個數
int tmp(void);
void tmpchange(void);
void tmpwritebyte(uchar dat);
uchar tmpread(void);
bit tmpreadbit(void);
void dsreset(void);
void delayb(uint count);
void main() //主函數
{
uchar i;
int l_tmp;
while(1)
{
tmpchange(); //溫度轉換
l_tmp=tmp();
if(l_tmp<0)
l_tmpdate[0]=10; //判斷溫度為負溫度,前面加"-"
else
{
l_tmpdate[0]=temp/1000; //顯示百位,這里用1000,是因為我們之前乖以10位了
if(l_tmpdate[0]==0)
l_tmpdate[0]=12;//判斷溫度為正溫度且沒有上百,前面不顯示
}
l_tmp=temp%1000;
l_tmpdate[1]=l_tmp/100;//獲取十位
l_tmp=l_tmp%100;
l_tmpdate[2]=l_tmp/10;//獲取個位
l_tmpdate[3]=11;
l_tmpdate[4]=l_tmp%10;//獲取小數第一位
for(i=0;i<10;i++){ //循環輸出10次,提高亮度
display(l_tmpdate,5);
}
}
}
void display(unsigned char *lp,unsigned char lc)//顯示
{
unsigned char i; //定義變數
P2=0; //埠2為輸出
P1=P1&0xF8; //將P1口的前3位輸出0,對應138譯門輸入腳,全0為第一位數碼管
for(i=0;i<lc;i++){ //循環顯示
P2=table[lp[i]]; //查表法得到要顯示數字的數碼段
delay(); //延時5個空指令
if(i==7) //檢測顯示完8位否,完成直接退出,不讓P1口再加1,否則進位影響到第四位數據
break;
P2=0; //清0埠,准備顯示下位
P1++; //下一位數碼管
}
}
void delay(void) //空5個指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
void delayb(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void) //DS18B20初始化
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) // 讀一位
{
uint i;
bit dat;
DS=0;i++; //小延時一下
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //讀一個位元組
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好//一個位元組在DAT里
}
return(dat); //將一個位元組數據返回
}
void tmpwritebyte(uchar dat)
{ //寫一個位元組到DS18B20里
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 寫1部分
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //寫0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //發送溫度轉換命令
{
dsreset(); //初始化DS18B20
delayb(1); //延時
tmpwritebyte(0xcc); // 跳過序列號命令
tmpwritebyte(0x44); //發送溫度轉換命令
}
int tmp() //獲得溫度
{
float tt;
uchar a,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //發送讀取數據命令
a=tmpread(); //連續讀兩個位元組數據
b=tmpread();
temp=b;
temp<<=8;
temp=temp|a; //兩位元組合成一個整型變數。
tt=temp*0.0625; //得到真實十進制溫度值,因為DS18B20
//可以精確到0.0625度,所以讀回數據的最低位代表的是
//0.0625度。
temp=tt*10+0.5; //放大十倍,這樣做的目的將小數點後第一位
//也轉換為可顯示數字,同時進行一個四捨五入操作。
return temp; //返回溫度值
}
void readrom() //read the serial 讀取溫度感測器的序列號
{ //本程序中沒有用到此函數
uchar sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms()
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
㈣ DS18B20在ARM7LPC2103下的C語言程序
DS18B20的C語言源程序
#include
sbit warmer="P1"^4;
sbit led_run=P1^0;
//sbit k_Power=P3^3;
sbit zf="P2"^0;
sbit ="P2"^1;
sbit shi="P2"^2;
sbit ge="P2"^3;
sbit dots="P2"^4;
sbit xs="P2"^5;
sbit DQ =P3^3; //定義通信埠
//延時函數
unsigned char tab[]={ 0xc0,0xf9,0xa4,0xb0, // 0, 1, 2, 3
0x99,0x92,0x82,0xf8,0x80,0x90, 0xff};
//4 5 6 7 8 9
unsigned int t="0";
unsigned char tflag;
unsigned char data disdata[4];
void delay(unsigned char i)
{
while(i--);
}
//初始化函數
Init_DS18B20(void)
{
unsigned char x="0";
DQ = 1; //DQ復位
delay(8); //稍做延時
DQ = 0; //單片機將DQ拉低
delay(80); //精確延時 大於 480us
DQ = 1; //拉高匯流排
delay(14);
x=DQ; //稍做延時後 如果x=0則初始化成功 x="1則初始化失敗"
delay(20);
}
//讀一個位元組
ReadOneChar(void)
{
unsigned char i="0";
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 給脈沖信號
dat>>=1;
DQ = 1; // 給脈沖信號
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
//寫一個位元組
WriteOneChar(unsigned char dat)
{
unsigned char i="0";
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
delay(4);
}
//讀取溫度
ReadTemperature(void)
{
unsigned char a="0";
unsigned char b="0";
Init_DS18B20();
WriteOneChar(0xCC); // 跳過讀序號列號的操作 發送指令0xcc
WriteOneChar(0x44); // 啟動溫度轉換 發送指令0x44
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度 發送指令0xbe
a=ReadOneChar(); //讀取溫度值低位
b=ReadOneChar(); //讀取溫度值高位
t=b;
t<<=8; //值左移8位
//a=a>>4; //低位右移4位,舍棄小數部分
//t=b<<4; //高位左移4位,舍棄符號位
//t=t|a;
t=t|a; //合並高低位數值
if(t<0xfff)
tflag="1";
else
{
tflag="0";
t=~t+1; //負值換算
}
t=t*(0.625); //溫度擴大10倍,精確到1位小數
return(t);
}
void display_temper(unsigned int i)
{
disdata[0]=i/1000; //百位數
disdata[1]=i%1000/100; //十位數
disdata[2]=i%100/10; //個位數
disdata[3]=i%10; //小數位
if(tflag==1)
tflag="0xff"; //正號,不顯示
else
tflag="0xbf"; //負號,顯示-
P2=0xff;
zf=0;
P0=tflag;
delay(150);
P0=0xff;
zf=1;
=0;
if(disdata[0]>0)P0=tab[disdata[0]];
delay(150);
=1;
shi=0;
P0=tab[disdata[1]];
delay(150);
shi=1;
ge=0;
P0=tab[disdata[2]];
delay(100);
ge=1;
dots=0;
P0=0x7f;
delay(150);
dots=1;
xs=0;
P0=tab[disdata[3]];
delay(150);
P0=0xff;
P2=0xff;
}
void main(void)
{unsigned int temp;
while(1) //主循環
{ temp="ReadTemperature"();
display_temper(temp);
}
}
來源:http://bbs.ednchina.com/ShowTopic.aspx?id=69283
㈤ DS18B20的程序
接上18B20溫度感測器後數碼管顯示出當前溫度
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2; //define interface
uint temp; // variable of temperature
uchar flag1; // sign of the result positive or negative
sbit la=P2^6;
sbit wela=P2^7;
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(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
///////功能:串口初始化,波特率9600,方式///////
void Init_Com(void)
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
void dsreset(void) //send reset and initialization command
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //read a bit
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //read a byte date
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好一個位元組在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20 begin change
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // address all drivers on bus
tmpwritebyte(0x44); // initiates a single temperature conversion
}
uint tmp() //get the temperature
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom() //read the serial
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
void display(uint temp) //顯示程序
{
uchar A1,A2,A2t,A3,ser;
ser=temp/10;
SBUF=ser;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
A3=A2t%10;
la=0;
P0=table[A1]; //顯示百位
la=1;
la=0;
wela=0;
P0=0x7e;
wela=1;
wela=0;
delay(1);
la=0;
P0=table1[A2]; //顯示十位
la=1;
la=0;
wela=0;
P0=0x7d;
wela=1;
wela=0;
delay(1);
P0=table[A3]; //顯示個位
la=1;
la=0;
P0=0x7b;
wela=1;
wela=0;
delay(1);
}
void main()
{
uchar a;
Init_Com();
do
{
tmpchange();
// delay(200);
for(a=10;a>0;a--)
{ display(tmp());
}
} while(1);
}