我在藍橋杯的板子上看到,他的是寄生電源供電,也就是沒有外接電源,靠總線高電平供電,低電平電容放電。編程之處略有不同。
網上很多資料,我還是隻說最難懂的點
一、注意事項
1.溫度轉換命令【44h】後面要加延時,而且總線要置1,提供上拉電流。
send(0xcc);
send(0x44);
DAT = 1;
delay1s();
2.
爲了提高可移植性,可以這樣寫
uchar way;
send(0xcc);
send(0xb4);
way = read();//讀取溫度狀態
DAT = 1; //釋放總線
if(way == 1)
{
#define waibu
}
#ifdef waibu
......
#else
......
#endif
......
3.注意:
每次命令都得初始化
常用命令
初始化時序:
總線拉低500微秒,再釋放總線(拉高)。然後進入接收模式。如果設備正常會發送應答信號,也就是低電平把總線拉低200微秒。
uchar i = 0;
DAT = 1;
DAT = 0;
delay600us();
DAT = 1;
dealay100us();
while(DAT == 1)
{
if(i == 5)
{
return 0;
}
i++
}
return 1;
寫時序:
1.總線置一
2.總線置零
3.等5微秒
4.總線保持60微妙(寫0)
總線拉高,保持60微秒(寫1)
5.總線置1保持1微秒以上
DAT = 1;
DAT = 0;
delay5us();
DAT = 0;
//DAT = 1; 寫1
delay60us();
DAT = 1;
讀時序:
1.總線置一
2.總線置零
3.等4微秒
4.總線置一(釋放總線)
5.等
讀一個位:
DAT = 1;
DAT = 0;
delay();
DAT = 1;
delay();
uchar dat;
dat = DAT;
DAT = 1;
讀一個字節:
uchar readByte()
{
uchar i,dat=0;
uchar da=0;
for(i=0;i<8;i++)
{
DATA=0;
_nop_();
DATA=1;
delay4us();
da=DATA;
da<<=7;
dat=(dat>>1)|da;
delay60us();
}
return dat;
}
溫度換算是負溫度減一取反乘精度
正溫度直接乘精度
注意:在上電覆位的時候,溫度寄存器中的值爲0x0550,即+85攝氏度。所以在應用開發中,有些朋友一直讀到的數據都是85.5攝氏度,就說明DS18B20根本沒有進行溫度轉換,你讀到的是上電覆位的初始值。
——————————————分割線————————————————
乾貨來了!!!!!!!!!!!!!!!!!!!!正式開始編程!
首先,先測試一下能不能用
那麼就是初始化一下看看返回值是不是0
經過兩天的測試,檢測不到這個玩意。。
全文完
大家自己做,應該是可以的。代碼沒問題,
後來檢測到了,大家繼續往後看
#include "ds18b20.h"
////單總線延時函數
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
void Delay_OneWire1(unsigned int t)
{
while(t--);
}
void Delay_us(void)
{
unsigned char i;
i = 30;
while (--i);
}
//通過單總線向DS18B20寫一個字節
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//從DS18B20讀取一個字節
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
// unsigned char index = 0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
Delay_us();
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80); // 延時大於480us
DQ = 1;
Delay_OneWire(5); // 14
initflag = DQ; // initflag等於1初始化失敗
Delay_OneWire(50);
return initflag;
}
————————分割線————————————————
更新於2020.3.29
服了,又可以了。我腦子瓦特了
箭頭這裏是電阻上拉的意思。所以不能等時間太久,不然就等不到,所以才顯示的檢測不到硬件。
這裏原來是50,我改成5了,立馬就檢測到了
返回值是0
唉
然後我們檢測一下供電方式。這裏也是一個大坑,無力吐槽藍橋杯這個板子的奇葩設計。。
uchar rd_temperature(void)
{
uchar dq;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xb4);
Delay_OneWire(5);
dq = DQ;
return dq;
}
看起來是寄生電源供電,實際上是外部電源供電。。。
因爲寄生電源供電的話,vdd和gnd都接地,這個不是
所以這段代碼的返回值是1。。。
我都是用串口檢測的
下一步開始測溫度
int rd_temperature(void)
{
uchar LOW = 0,HIGH = 0;
int temp = 0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay1000ms() ;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LOW = Read_DS18B20();
HIGH = Read_DS18B20();
temp = (HIGH << 8) | (LOW);
return temp;
}
主函數這裏數據處理一下
int GOODORNOT = 0;
Init();
uartInit();
while(1)
{
GOODORNOT = rd_temperature();
GOODORNOT = GOODORNOT*0.0625+0.5;
uartSendByte((uchar)(GOODORNOT/10)+'0');
uartSendByte((uchar)(GOODORNOT%10)+'0');
delay(50000);
}
成功
全文完
有問題的可以留言評論