關(guān)于DS18B20溫度傳感器,在沒(méi)有硬件設(shè)備的輔助下,寫內(nèi)部程序有些困難,因?yàn)榭床坏綄?shí)際信號(hào)波形。對(duì)于單片機(jī),我。。。漸漸的有些心灰意冷。。雖然掌握了1_WIRE總線,卻少了很多喜悅,下雨了。。。它是我的愛(ài)好,我付出了很多,可是我看不到實(shí)際的前景。。以我個(gè)人之力,要步入尖端芯片領(lǐng)域,很困難,在這里,采棉花是個(gè)普遍性的大問(wèn)題,大型機(jī)械設(shè)備缺陷很多,如果以微控制芯片提高精度,我想效益會(huì)相當(dāng)可觀,可是技術(shù)瓶頸難以逾越。。。硬件研發(fā),失敗了,所有投入赴之東流,成功了,回報(bào)豐厚,F(xiàn)在,各行各業(yè)都處于飽和,沒(méi)有成熟先進(jìn)的技術(shù),很難有立足之地,,,,,我開(kāi)始重新審視我的選擇。。。。。。艱難。。
/*
建立時(shí)間: 2013年5月2日;
前言: 我用軟件仿真,測(cè)算延時(shí)時(shí)間,效果不錯(cuò),但是根據(jù)教程,復(fù)位時(shí),先釋放總線
(wd高電平),然后主機(jī)拉低wd,持續(xù)時(shí)間為400--960微妙.后主機(jī)拉高wd,持續(xù)15-
60微妙,后 從機(jī),會(huì)拉低電平持續(xù)時(shí)間是60--240微妙(此時(shí)表示復(fù)位成功),如果
從機(jī)沒(méi)有將總線拉低,則復(fù)位失敗.然后,主機(jī)拉高電平60--240微妙.復(fù)位結(jié)束;
可,實(shí)驗(yàn)證明,在,從機(jī),拉低總線電平后,持續(xù)一定時(shí)間,從機(jī)還會(huì)將總線拉高!這
是教程中的一個(gè)重大錯(cuò)誤!
temperature sensor reset module finishing time: 23:08:00
( 溫度 傳感器 復(fù)位 模塊 完成 時(shí)間 )
temperature sensor 操作過(guò)程:
1. reset DS18B20;
2. 發(fā)出Skip ROM 命令(CCH); (跳躍ROM命令)
3. 發(fā)出Convert T命令(44H); (溫度轉(zhuǎn)換命令)
4. reset DS18B20;
5. 發(fā)出Skip ROM命令(CCH);(跳躍ROM命令)
6. 發(fā)出讀取命令(BEH);
7. 讀出兩個(gè)字節(jié)的溫度;
8. 溫度格式轉(zhuǎn)換;
2013年5月8日22:56:44
DS18B20 Temperature sensor read data module accomplish;
( 溫度 傳感器 讀 數(shù)據(jù) 模塊 完成 )
現(xiàn)在還有溫度顯示模塊沒(méi)有完成,硬件是1602液晶屏......
2013年5月9日19:32:31
今天,溫度傳感器的程序主體結(jié)構(gòu)全部完成!!!!!
不容易啊,值得慶祝一下!!!!!!
一共寫了7天程序!{陸陸續(xù)續(xù)};
喝個(gè) 品酸乳果汁.......
*/
#include <reg52.h>
typedef unsigned char uint8 ;
typedef unsigned int uint16;
sbit wd = P3^2; //定義數(shù)據(jù)單總線;
sbit e =P1^5; // 定義1602液晶顯示器數(shù)據(jù)使能端口;
sbit rs=P1^0; // 定義數(shù)據(jù)/指令選擇端口;
sbit rw=P1^1; // 定義 讀/寫 選擇端口;
sbit BF=P0^7; // 定義繁忙位;
bit w=0; //定義一個(gè)全局一位變量;
//===========1602液晶顯示器模塊;===============
busy() //液晶屏繁忙檢測(cè)函數(shù);
{ e=0;
rs=0;
rw=0;
P0=0xff;
do
{ e=0; //使能位清零;
rs=0; //指令;
rw=1; //讀;
e=1; //數(shù)據(jù)傳輸啟動(dòng);
}while(BF); //如果BF==0;則液晶處于空閑狀態(tài);
e=0;
}
play_data(uint8 wr) //液晶寫入數(shù)據(jù);
{
busy(); //繁忙檢測(cè);
P0=wr; //裝載數(shù)據(jù);
rs=1; //數(shù)據(jù);
rw=0; //寫入;
e=1; //傳輸開(kāi)始;
e=0; //傳輸結(jié)束;
}
play_cmd(uint8 cmd) //液晶寫入指令;
{
busy(); //繁忙檢測(cè);
P0=cmd; //裝載數(shù)據(jù);
rs=0; //指令;
rw=0; //寫入;
e=1; //傳輸開(kāi)始;
e=0; //傳輸結(jié)束;
}
reset_1602() //1602液晶顯示器初始化函數(shù);
{
play_cmd(0x38);
play_cmd(0x0c);
play_cmd(0x06);
play_cmd(0x01);
}
//=========溫度傳感器延時(shí)模塊============================
// sbit led= P1^0;
delay(uint8 num ) //如果unm等于1;延時(shí)16.28微妙;
{
while(num--); //如果num大于一,則16.28+(num-1)*6.51.
}
delay2() //此函數(shù)延時(shí)3.26微秒;
{
uint8 j=0;
j=9;
}
delay3()
{
uint16 s=60000;
while(s--);
}
reset_1820() //========復(fù)位溫度傳感器; ========
{
while(wd)
{
wd=1;
delay(140); //拉高總線,延時(shí)大概921微妙左右;(延時(shí)值自定);
wd=0; //總線由單片機(jī)拉低,下為延時(shí)函數(shù),大概800微秒左右;
delay(61); //1個(gè)此函數(shù)會(huì)延時(shí)400微妙左右;
delay(61); //兩個(gè)是800微妙左右;
wd=1; //主機(jī)拉高總線,68微秒左右;
delay(9); //延時(shí)68微妙左右
if(wd==0) //如果wd是0就終止復(fù)位;(代表復(fù)位成功);
{
while(wd==0); //總線一旦為低,那么就等待從機(jī)再將總線拉高.
break; //終止while循環(huán);(reset function end)
}
else
{
wd=1;
delay(20); //延時(shí)140微妙;
}
}
delay(30); //此時(shí)總線為高電平并延時(shí)205微妙,復(fù)位成功!;
// if(wd)led=0;//此語(yǔ)句為檢驗(yàn)是否復(fù)位成功;P1^0外接9012三極管接led小燈;
}
write_byte(uint8 dat)
{
uint8 i=0;
for(i=0;i<8;i++)
{
wd=0; //A點(diǎn);
delay2(); //延時(shí)
wd=dat & 0x01;
dat>>=1;
delay(6); //A點(diǎn)到此處用時(shí)65.11微秒;
wd=1; //總線釋放;
delay2(); //延時(shí)3.26微秒;
}
} //========此函數(shù)執(zhí)行完成之后總線為高電平;
uint8 read_byte() //=====讀8位數(shù)據(jù);===================
{
uint8 j=0, dat =0;
for(j=0;j<8;j++)
{
dat>>=1;
wd=0; // A點(diǎn) mcu拉低電平3.26微秒;
delay2(); // 延時(shí)3.26微秒;
wd=1;
if(wd)
{
dat|=0x80;
} //讀完數(shù)據(jù)后A點(diǎn)到此處是11.93微秒,保持在15微秒之內(nèi);
delay(9); // A點(diǎn)到此處80.29微秒; 理想時(shí)間范圍是60--120微秒;
wd=1; //釋放總線;
delay2(); //延時(shí)3.26微秒;
}
return dat;
}
start_sensor() //啟動(dòng)傳感器;
{
reset_1820();
write_byte(0xcc); //跳躍命令;
write_byte(0x44); //轉(zhuǎn)換temperature(溫度)命令;
}
uint8 read_temp() //從溫度傳感器度溫度數(shù)據(jù)過(guò)程;
{
uint8 ak[2];
uint16 dat=0 , j=0;
reset_1820(); //復(fù)位溫度傳感器
write_byte(0xcc); //跳躍rom命令;
write_byte(0xbe) ; // 發(fā)出讀數(shù)據(jù)命令;
ak[0]=read_byte(); //讀取第一個(gè)字節(jié)數(shù)據(jù);
ak[1]=read_byte(); //讀取第二個(gè)字節(jié)數(shù)據(jù);
dat=ak[1]; //要把兩個(gè)八位數(shù)據(jù)載入1個(gè)16位變量里;
dat<<=8;
dat|=ak[0];
j= dat;
//==========以下是把溫度傳感器內(nèi)部數(shù)據(jù)編譯成16進(jìn)制編碼;
if((j>>11)==0x1f) //此語(yǔ)句是負(fù)溫度進(jìn)入.0x1f是二進(jìn)制5個(gè)全1;
{
dat=(~dat)+1; //負(fù)溫度要取反加一操作;
dat/=16; //傳感器給的溫度系數(shù)要除以16后,得到的數(shù)才是常規(guī)溫度系數(shù);
w=0; //此語(yǔ)句是在主函數(shù)中用來(lái)判斷是正溫度還是負(fù)溫度;
return dat; //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
}
j=dat;
if((j>>11)==0) //如果是零則是正溫度;
{
dat/=16; //數(shù)據(jù)直接除以16,就得到了常規(guī)溫度系數(shù);
w=1; //1代表正;
return dat; //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
}
return 130; //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
}
delay_ms() //延時(shí)1秒;
{
uint8 i=250;
uint16 j=608;
while(j--)
{ while(i--);
i=250;
}
}
error() //測(cè)溫出錯(cuò);
{
uint8 i=5, j=0 ,ak[]="Error!";
while(i--)
{
play_cmd(0x82);
while(ak[j]!='\0')
{
play_data(ak[j++]);
} j=0;
delay3();
play_cmd(0x01);
delay3();
}
}
main()
{
uint8 dat=0 ,j=3,len=0 ,num[]="start.....";
reset_1602();
while(j--) //這是啟動(dòng)電源時(shí),液晶顯示:start....(并閃爍3次)
{ play_cmd(0x82);
while(num[len]!='\0')
{
play_data(num[len++]);
}
len=0;
delay3();
play_cmd(0x01);
delay3();
}
while(1)
{
start_sensor(); //啟動(dòng)溫度傳感器;
delay_ms(); //等待1秒;
dat = read_temp(); //讀取溫度數(shù)據(jù)并賦給dat變量;
if(dat==130) //如果返回來(lái)的數(shù)據(jù)是130,表明采集溫度出錯(cuò);
{
error();
}
else if(w==1) //如果w是1,就代表正溫度.輸出;
{
play_cmd(0x83);
play_data(dat/10+'0');
play_data(dat%10+'0');
}
else //否則,就是負(fù)溫度,輸出時(shí)前面加一個(gè)負(fù)號(hào);
{
play_cmd(0x82);
play_data('-');
play_data(dat/10+'0');
play_data(dat%10+'0');
}
} //我的親娘四舅奶奶啊!!!!!!終于完成了!!!!2013年5月9日19:32:10
}