DS18B20控制的實(shí)現(xiàn)
參考源碼如下:
#include
#define uint unsigned int
#define uchar unsigned char
sbit temp = P2^2;
// delayus(1);//7us
// delay(1);//24us
// delayms(1);//826ms
// delayus(10);//25us
// delay(10);//123us
// delayms(10);//8141ms
//delayus(15);//35us
//delayus(25);//55us
//delayus(3); //13us
//delayus(17);//39us
//delayus(18);//41us
void delayus(uchar i)
{
while(--i);
}
void delayms(uint i)
{
uint j;
for(;i>0;i--)
for(j=100;j>0;j--);
}
void delay(uint i)
{
uint j;
for(j;j
}
void ds18_reset()
{
temp = 0;
delayms(1);
temp = 1;
delayus(25);//55us
}
void ds18_ack()
{
while(temp);
while(!temp);
}
void ds18_writebit(char bitval)
{
temp = 0;
delayus(2);
if(bitval)temp =1;
delayus(15);
temp =1;
}
void ds18_writechar(uchar uc)
{
uint i = 0;
uchar tempdata;
for(i;i<8;i++)
{
tempdata = uc >> i;
tempdata &= 0x01;
ds18_writebit(tempdata);
}
// delayus(25);
}//從8位數(shù)據(jù)的低位開始寫
uchar ds18_readbit()
{
temp =0;
temp = 1;
delayus(1);
return temp;
}
uchar ds18_readchar()
{
uchar returntemp = 0x00;
uint i = 0;
for(i;i<8;i++)
{
if(ds18_readbit())
{
returntemp |= 0x01<
}else{
returntemp |= 0x00<
}
delayus(18);//每讀一個(gè)位,要延時(shí)40-40us//獲取應(yīng)該更小一點(diǎn),因?yàn)榍懊嬉痪涿菜埔呀?jīng)占用了一些時(shí)間了
}
return returntemp;
}//首先讀到的也是低位字節(jié)
void main()
{
uint mi = 0;
uchar ds18data[9]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
ds18_reset();
ds18_ack();
ds18_writechar(0xcc);
ds18_writechar(0x44);
while(ds18_readchar()!=0xff);//單片機(jī)開始溫度轉(zhuǎn)換后,單總線會(huì)被其一直拉低直到總線上在八us時(shí)間內(nèi)持續(xù)保持高電平說明轉(zhuǎn)換完成
//測(cè)試ds18b20的供電模式(返回值是1)
/* ds18_writechar(0xB4);
temp= 0;
temp = 1;
delayus(1);
if(temp)
{P1 = 0x00;}else{P1 = 0xf0;}
while(1);*/
ds18_reset();
ds18_ack();
ds18_writechar(0xcc);
ds18_writechar(0xBE);
delayus(1);
// P1 = 0xf0;
for(mi = 0;mi < 9;mi++)
{
ds18data[mi] = ds18_readchar();
}
for(mi = 0;mi < 9;mi++)
{
P1=0xaa;
delayms(1500);
P1 = ~ds18data[mi];
delayms(15000);//
}
P1 = 0x00;
ds18_reset();
while(1);
}
其中應(yīng)注意一下幾點(diǎn):
1.延時(shí)函數(shù)應(yīng)該通過仿真確定實(shí)際延時(shí)時(shí)間,由于keil將c語(yǔ)言編譯后會(huì)進(jìn)行一些優(yōu)化,所以某些寫法的延時(shí)函數(shù)不會(huì)是與傳入?yún)?shù)呈線性關(guān)系的
2.串行向ds18b20寫入數(shù)據(jù)時(shí)候,高地位的寫入順序是要注意的(之前因?yàn)樽x出來(lái)是從高位開始,寫的時(shí)候也從高位開始,產(chǎn)生了問題,實(shí)際上寫給18b20的時(shí)候是從低位開始傳輸?shù)?
3.給ds18b20 “Convert T"(0x44) 命令后,應(yīng)該重新開始一次reset周期之后讀取ds18b20的暫存器,若是在0x44后直接讀取,則沒成功,并且每次開機(jī)都應(yīng)該先給ds18b20發(fā)送一個(gè)“Convert T"命令,否則會(huì)讀出內(nèi)部暫存器默認(rèn)值的。
4.參考一些資料重寫后,發(fā)現(xiàn)數(shù)據(jù)讀出來(lái)都是1,于是懷疑是讀出數(shù)據(jù)的問題,檢查并且debug了許久未得其原因,后來(lái)考慮到可能是芯片沒有響應(yīng),所以每次讀到都是總線的高電平。于是檢查了寫函數(shù),發(fā)現(xiàn)ds18_writechar()中調(diào)用的是ds18_writebit(temp),那么寫入的一直是1,ds18b20還會(huì)思考呢,給我都是1的命令,我命令表中沒有啊
5.單片機(jī)用于debug的方法不怎么多,在沒有邏輯分析儀的情況下,實(shí)時(shí)通過led輸出八位數(shù)據(jù)也是不錯(cuò)的選擇
6.單總線協(xié)議對(duì)時(shí)序和延時(shí)的要求確實(shí)比較高。
附上讀出rom和ram的數(shù)據(jù)
rom:
0010 1000 //從數(shù)據(jù)手冊(cè)中得知此八位為0x28 , 為系列碼
1110 1010
1100 0000
1011 1011
0000 0100
0000 0000
0000 0000
0100 0001
ram:
1100 1001
0000 0001//1 1100 1001 = 1B9 * 0.0625 = 28.5625 // 完美!!!!!
0100 1011
0100 0110
0111 1111//第五六位為11,溫度轉(zhuǎn)換精度為12位
1111 1111
0000 0111
0001 0000
0110 0100
經(jīng)過兩天,各種讀文檔,各種參考程序,終于能正確的寫出了這么一個(gè)單總線協(xié)議的函數(shù)了