直接貼程序不好嗎?還方便一些嘛。
給你一個例程:
main.c
#include<reg51.h>
#include"DS18B20.h"
#define SMG P0//數碼管IO
sbit LSA=P2^2;//138譯碼器
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code ZF[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//要顯示的數字
unsigned int XS[5]={0x3f,0x3f,0x3f,0x3f,0x3f};//顯示緩存
void FZ(int temp)//給數碼管顯示緩存放入數據
{
float tp;//要進行帶符號的小數運算,必須用有符號實型數據,32位
if(temp< 0)//當溫度值為負數
{
XS[0] = 0x40;//顯示負號-
temp=temp-1;//因為讀取的溫度是實際溫度的補碼,所以減1,再取反求出原碼
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;//留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數
//轉換為整型的時候把小數點后面的數自動去掉,不管是否
//大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就
//算加上.5,還是在小數點后面。
}
else
{
XS[0] = 0x70;//正數就顯示┣
tp=temp;
temp=tp*0.0625*100+0.5;
}
XS[1] = ZF[temp % 10000 / 1000];
XS[2] = ZF[temp % 1000 / 100] + 0x80;//顯示小數點
XS[3] = ZF[temp % 100 / 10];
XS[4] = ZF[temp % 10 / 1];
}
void DISPLAY()
{
LSC=1;LSB=0;LSA=0;//溫度正負號
SMG=XS[0];
Delay1ms(1);
SMG=0x00;
LSC=0;LSB=1;LSA=1;//溫度的十位
SMG=XS[1];
Delay1ms(1);
SMG=0x00;
LSC=0;LSB=1;LSA=0;//溫度的個位帶小數點
SMG=XS[2];
Delay1ms(1);
SMG=0x00;
LSC=0;LSB=0;LSA=1;//溫度的小數點后第一位
SMG=XS[3];
Delay1ms(1);
SMG=0x00;
LSC=0;LSB=0;LSA=0;//溫度的小數點后第二位
SMG=XS[4];
Delay1ms(1);
SMG=0x00;
}
void main()
{
while(1)
{
FZ(Ds18b20ReadTemp());//讀取溫度值并對顯示緩存賦值
DISPLAY();//數碼管顯示
}
}
DS18B20.c
#include"DS18B20.h"
void Delay1ms(unsigned int y)//延時yms
{
unsigned int x;
for(y;y>0;y--)
for(x=110;x>0;x--);
}
unsigned char Ds18b20Init()//初始化
{
unsigned int i;
DSPORT=0;//將總線拉低480us~960us
i=70;
while(i--);//延時642us
DSPORT=1;//然后拉高總線,如果DS18B20做出反應會將在15us~60us后總線拉低
i=0;
while(DSPORT)//等待DS18B20拉低總線
{
i++;
if(i>1000)//等待>1MS
{
return 0;//初始化失敗
}
}
return 1;//初始化成功
}
void Ds18b20WriteByte(unsigned char dat)//向18B20寫入一個字節
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0;//每寫入一位數據之前先把總線拉低1us
i++;
DSPORT=dat&0x01;//然后寫入一個數據,從最低位開始
i=6;
while(i--);//延時68us,持續時間最少60us
DSPORT=1;//然后釋放總線,至少1us給總線恢復時間才能接著寫入第二個數值
dat>>=1;
}
}
unsigned char Ds18b20ReadByte()//從DS18B20讀取一個字節
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j--)
{
DSPORT=0;//先將總線拉低1us
i++;
DSPORT=1;//然后釋放總線
i++;
i++;//延時6us等待數據穩定
bi=DSPORT;//讀取數據,從最低位開始讀取
byte=(byte>>1)|(bi<<7);
i=4;//讀取完之后等待48us再接著讀取下一個數
while(i--);
}
return byte;
}
void Ds18b20ChangTemp()//向DS18B20發送溫度轉換命令
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);//跳過ROM操作命令
Ds18b20WriteByte(0x44);//溫度轉換命令
}
void Ds18b20ReadTempCom()//發送讀取溫度命令
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);//跳過ROM操作命令
Ds18b20WriteByte(0xbe);//發送讀取溫度命令
}
int Ds18b20ReadTemp()//讀取溫度
{
int temp=0;
unsigned char tmh,tml;
Ds18b20ChangTemp();//先寫入轉換命令
Ds18b20ReadTempCom();//然后等待轉換完后發送讀取溫度命令
tml=Ds18b20ReadByte();//讀取溫度值共16位,先讀低字節
tmh=Ds18b20ReadByte();//再讀高字節
temp=tmh;//把兩次得到的8位數據,合并為16位實際數據
temp<<=8;
temp|=tml;
return temp;//溫度的英文單詞temperature
}
DS18B20.h
#ifndef __TEMP_H_
#define __TEMP_H_
#include<reg51.h>
sbit DSPORT=P3^7;
void Delay1ms(unsigned int );
unsigned char Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void Ds18b20ChangTemp();
void Ds18b20ReadTempCom();
int Ds18b20ReadTemp();
#endif
程序適用的電路:
|