建議你按照如下步驟調試程序:
1、忽略文段模塊的通訊,調通數碼顯示這塊。逐位顯示0-9的所有數字,包括帶小數點的情況
2、第一步都跳調通了,再去調試ds18b20。由于ds18b20的口位簡單,重點在于時序。
第一步很重要。另外如果擔心顯示出問題。可以把取得的溫度數據直接發送到串口去顯示,看看對不對。
以下是我做過的和18B20有關的代碼,用的12M晶振,STC89C52,實測過的
// 溫度傳感器接口
sbit DQ=P3^7; //數據傳輸線接單片機的相應的引腳
/*
********************************************************************************
** 函數名稱 : Init_DS18B20(void)
** 函數功能 : 初始化
********************************************************************************
*/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
Delay10us(60);//最小480,最大960
DQ=0; //發送復位脈沖
Delay10us(60);//最小480,最大960
DQ=1; //拉高數據線
Delay10us(6);//15-60us
// x=DQ; //用X的值來判斷初始化有沒有成功,18B20存在的話X=0,否則X=1
//delay(20);
while(DQ==0);
DQ=1;//讓傳感器釋放總線,避免影響下一步
}
/*
********************************************************************************
** 函數名稱 : ReadOneChar()
** 函數功能 : 讀一個字節
********************************************************************************
*/
unsigned char ReadOneChar() //主機數據線先從高拉至低電平1us以上,再使數據線升為高電平,從而產生讀信號
{
unsigned char dat=0;
unsigned char mask,fmask;
for(mask=0x01;mask!=0;mask<<=1)//一個周期需要至少60us,但采樣要在15us內完成
{
DQ=0;
_nop_();
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(DQ==0)//讀0
{
fmask=~mask;
dat=dat&fmask;
}
else
{
dat|=mask;
}
Delay10us(5);
DQ=1;
}
return dat;
}
/*
********************************************************************************
** 函數名稱 : WriteOneChar(unsigned char dat)
** 函數功能 : 寫一個字節
//一個寫周期為60-120us,主機在15--45us內對信號采樣
********************************************************************************
*/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //數據線從高電平拉至低電平,產生寫起始信號。15us之內將所需寫的位送到數據線上,
for(i=8;i>0;i--) //在15~60us之間對數據線進行采樣,如果是高電平就寫1,低寫0發生。
{
DQ=0; //在開始另一個寫周期前必須有1us以上的高電平恢復期。
DQ=dat&0x01;
Delay10us(6);//15-60us采樣
DQ=1;
dat>>=1;
}
delay(4);
}
/*
********************************************************************************
** 函數名稱 : ReadTemperature(void)
** 函數功能 : 讀溫度值(低位放tempL;高位放tempH;)
********************************************************************************
*/
void ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳過讀序列號的操作
WriteOneChar(0x44); //啟動溫度轉換
delayms(125); //轉換需要一點時間,延時
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳過讀序列號的操作
WriteOneChar(0xbe); //讀溫度寄存器(頭兩個值分別為溫度的低位和高位)
tempL=ReadOneChar(); //讀出溫度的低位LSB
tempH=ReadOneChar(); //讀出溫度的高位MSB
if(tempH>0x7f) //最高位為1時溫度是負
{
tempL=~tempL; //補碼轉換,取反加一
tempH=~tempH+1;
fg=0; //讀取溫度為負時fg=0
}
sdate = tempL/16+tempH*16; //整數部分
xiaoshu1 = (tempL&0x0f)*10/16; //小數第一位
xiaoshu2 = (tempL&0x0f)*100/16%10;//小數第二位
xiaoshu=xiaoshu1*10+xiaoshu2; //小數兩位
} |