通過對CT107D實驗板的基本原理認識,以及掌握好了LED、數碼管等小部件的操作,我們就可以自信滿滿地學習更為復雜的外接元件了。面對板載重要器件,比如:DS18B20、DS1302、AT24C02、PCF8591等。我們要腳踏實地的逐一攻克。
首先,來看一下溫度傳感器——DS18B20。
上原理圖:
做為日常最常見的數字溫度傳感器,這無疑顯得非常重要,大賽組織方對此也很重視,往屆比賽試題多次涉及該傳感器的相關內容。
拿過一個新器件,第一步要查看其完整的官方說明文檔。看原理圖已知,DS18B20有三個管腳,其中兩個是電源線,只有一個數據引腳。因此它是典型的單總線傳輸器件。提到單總線IIC,就會涉及到單總線時序的操作,而該傳感器對時序的要求非常苛刻。對,我只能用苛刻這兩個字來形容,因為針對不同的硬件平臺,時序操作是大不相同的,最初我在此處深陷,困惑了很長一段時間。
說明文檔中,最重點是初始化、讀和寫的操作時序圖。
先看初始化操作時序:
初始化時序,也可作復位時序。由圖可見,主控器發(fā)送復位低脈沖的時間約為480微秒,主控器接收的時間大約為480微秒。編程時要注意高低電平之間的間隔延時,要嚴格按照時序圖操作。
再來看寫時序圖:
該圖明確說明了主控器在IIC總線中高低電平的間隔時間,不在具體熬述。
最后,讀時序圖:
原理如圖,主控器要占用總線45微秒來采樣,圖片說明很詳細。
分析完工作原理后,我們就可以敲代碼了。
傳感器驅動程序如下:
ds18b20.c
void delay(uint t)
{
uint i;
for(i = 0; i<t; i++)
{
_nop_(); //1.0us
}
}
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
delay(10);
DQ = 0;
delay(500);
DQ = 1;
delay(200);
initflag = DQ;
delay(250);
return initflag;
}
//通過單總線向器件寫一個字節(jié)
void wr_ds18b20(uchar dat)
{
uchar i;
for(i = 0; i<8; i++)
{
DQ = 0;
delay(2);
DQ = dat&0x01;
delay(60);
DQ = 1;
dat >>= 1;
}
delay(5);
}
//通過單總線從器件讀一個字節(jié)
uchar rd_ds18b20(void)
{
uchar i;
uchar ret;
uchar dat = '0';
for(i = 0; i<8; i++)
{
dat >>= 1;
DQ = 0;
delay(2);
DQ = 1;
ret = DQ;
delay(60);
DQ = 1;
if(ret)
dat |= 0x80;
}
return dat;
}
///溫度讀取及轉換函數
uchar rd_temperature(void)
{
uchar low, high;
uint temp;
float temperature;
DQ = 1;
init_ds18b20();
wr_ds18b20(0xcc);//跳過讀ROM
wr_ds18b20(0x44);//
delay(200);
init_ds18b20();
wr_ds18b20(0xcc);
wr_ds18b20(0xbe);//讀取溫度
low = rd_ds18b20(); //先讀低字節(jié)
high = rd_ds18b20(); //高字節(jié)
temp = high&0x0f;
temp <<= 8;
temp |= low;
temperature=temp*0.0625; //分辨率轉換
temp=temperature*10+0.5; //四舍五入,保留小數點一位
return temp;
}
驅動代碼參照時序圖都可以寫出來,這里關鍵的一點是延時函數。該函數的精確度決定了整個程序的時序精確度,如果延時不準確,那整個程序是失敗的,DS18B20不能正常工作。有許多同學說程序寫好了,沒有錯誤,用數碼管顯示溫度,溫度數值一直沒有變過。大多是因為時序的問題。應該仔細更改延時程序,反復進行調試。