你的需要把結果校驗一下,有時候讀出來的值有問題的
//=========================DS18B20溫度傳感器=========================//
#define DS18B20_DQ_IN PIND & (1 << PD6)
/*******************************************************************************
* 函 數 名 : DS18B20_Reset
* 函數功能 : 復位DS18B20
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void DS18B20_Reset(void)
{
DDRD &= ~(1 << PD6); // 端口輸入
PORTD &= ~(1 << PD6); // 高阻態
delay_ms(1);
DDRD |= (1 << PD6); // 端口輸出,因為是輸入高阻態,設置成輸出時直接就會輸出低電平,拉低DQ
delay_us(500);
DDRD &= ~(1 << PD6); // 拉高DQ,釋放總線
delay_us(10);
}
/**
* @brief 單總線初始化
* @param 無
* @retval 從機響應位,0為響應,1為未響應
*/
uchar DS18B20_Check(void)
{
uchar i;
uchar AckBit = 1;
uchar TIMEOUT_MS = 500; // 進行超時判斷
DS18B20_Reset();
while (DS18B20_DQ_IN && TIMEOUT_MS > 0)
{
TIMEOUT_MS--;
AckBit = DS18B20_DQ_IN;
}
delay_ms(1);
return AckBit;//如何DS18B20存在返回0,否則返回1
}
/*******************************************************************************
* 函 數 名 : DS18B20_Init
* 函數功能 : 初始化DS18B20的IO口 DQ 同時檢測DS的存在
* 輸 入 : 無
* 輸 出 : 1:不存在,0:存在
*******************************************************************************/
uchar DS18B20_Init(void)
{
uchar a;
a = DS18B20_Check();
return a;
}
/*******************************************************************************
* 函 數 名 : DS18B20_Write_Byte
* 函數功能 : 寫一個字節到DS18B20
* 輸 入 : dat:要寫入的字節
* 輸 出 : 無
*******************************************************************************/
void DS18B20_Write_Byte(uchar dat)
{
uchar j;
uchar testb;
for (j = 1; j <= 8; j++)
{
testb = dat & 0x01;
dat = dat >> 1;
if (testb)
{
DDRD |= (1 << PD6); // 拉低DQ
delay_us(2);
DDRD &= ~(1 << PD6); //輸入高阻態,拉高DQ
delay_us(60);
}
else // Write 0
{
DDRD |= (1 << PD6); // 拉低DQ
delay_us(60);
DDRD &= ~(1 << PD6); //輸入高阻態,拉高DQ
delay_us(2);
}
}
}
/*******************************************************************************
* 函 數 名 : DS18B20_Read_Bit
* 函數功能 : 從DS18B20讀取一個位
* 輸 入 : 無
* 輸 出 : 1/0 1001 0000
*******************************************************************************/
uchar DS18B20_Read_Bit(void) // read one bit
{
uchar data;
DDRD |= (1 << PD6); // 拉低DQ
delay_us(2);
DDRD &= ~(1 << PD6); //輸入高阻態,拉高DQ
delay_us(2);
if (DS18B20_DQ_IN)
{
data = 1;
}
else
{
data = 0;
}
delay_us(50);
return data;
}
/*******************************************************************************
* 函 數 名 : DS18B20_Read_Byte
* 函數功能 : 從DS18B20讀取一個字節
* 輸 入 : 無
* 輸 出 : 一個字節數據
*******************************************************************************/
uchar DS18B20_Read_Byte(void) // read one byte
{
uchar i,j,dat;
dat=0;
for (i=0;i<8;i++)
{
j=DS18B20_Read_Bit();
if(j==1)
{
dat|=(0x01<<i);
}
}
return dat;
}
// 0xCC進行設備尋址(只有一個從機時使用)
// 0x44溫度變換(讀取溫度前要執行溫度變換,將溫度值放到暫存器里)
// 0xBE溫度讀取(將暫存器里的溫度讀出)
//DS18B20指令
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
/*******************************************************************************
* 函 數 名 : DS18B20_Start
* 函數功能 : 開始溫度轉換
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void DS18B20_Start(void)// ds1820 start convert
{
DS18B20_Check();
DS18B20_Write_Byte(DS18B20_SKIP_ROM);// skip rom
DS18B20_Write_Byte(DS18B20_CONVERT_T);// convert
}
/*******************************************************************************
* 函 數 名 : DS18B20_GetTemperture
* 函數功能 : 從ds18b20得到溫度值
* 輸 入 : 無
* 輸 出 : 溫度數據
*******************************************************************************/
uchar DS18B20_Crc(uchar *addr, uchar len)
{
uchar crc = 0, inbyte, i, mix;
while (len--)
{
// inbyte 存儲當前參與計算的新字節
inbyte = *addr++;
for (i = 8; i; i--)
{
// 將新字節與CRC從低位到高位, 依次做異或運算, 每次運算完CRC右移一位
// 如果運算結果值為1, 則將CRC與 1000 1100 作異或
// 第3,4位代表異或運算, 第7位其實就是運算結果移入的1
mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix)
{
crc ^= 0x8C;
}
inbyte >>= 1;
}
}
return crc;
}
float DS18B20_GetTemperture(void)
{
uint temp;
uchar a, b;
static float value;
uchar tab[9], CRC8;
DS18B20_Start(); // ds1820 start convert
DS18B20_Check();
DS18B20_Write_Byte(DS18B20_SKIP_ROM); // skip rom
DS18B20_Write_Byte(DS18B20_READ_SCRATCHPAD); // convert
tab[0] = a = DS18B20_Read_Byte(); // LSB
tab[1] = b = DS18B20_Read_Byte(); // MSB
tab[2] = DS18B20_Read_Byte(); //
tab[3] = DS18B20_Read_Byte(); //
tab[4] = DS18B20_Read_Byte(); //
tab[5] = DS18B20_Read_Byte(); //
tab[6] = DS18B20_Read_Byte(); //
tab[7] = DS18B20_Read_Byte(); //
tab[8] = DS18B20_Read_Byte(); // CRC
CRC8 = DS18B20_Crc(tab,8);
if (CRC8 != tab[8]) // CRC校驗
{
return value;
}
temp = (b << 8) | a;
if ((temp & 0xf800) == 0xf800)
{
temp = (~temp) + 1;
value = temp * (-0.0625);
}
else
{
value = temp * 0.0625;
}
return value;
}
//=========================DS18B20溫度傳感器=========================// |