開發板:野火挑戰者_V2
GPIO:PE2
用來通過串列埠列印溫度值
我們先開啟 DS18B20 的手冊
/*
DS18B20 復位
將匯流排拉低 480us - 960us 啟動復位,然後等待 15us 檢測存在脈衝
*/
void Ds18b20_Reset(void)
{
//輸出模式下
DQ_GPIO_OUT();
//拉低匯流排 750us
DQ_Write(DQ_LEVEL_LOW);
HAL_Delay_Us(750);
//釋放匯流排,等待存在脈衝
DQ_Write(DQ_LEVEL_HIGHT);
HAL_Delay_Us(15);
}
/*
檢測存在脈衝
存在: 0
不存在: 1
*/
uint8_t Ds18B20_CheckPulse(void)
{
/* 超時計數,若裝置不存在,需要退出,不能一直等待 */
uint8_t Time_Count = 0;
//將 GPIO 改成輸入模式下
DQ_GPIO_IN();
/* 對應時序中的 DS18B20 等待 (15 - 60)us */
while (DQ_Read && Time_Count < 100)
{
Time_Count++;
HAL_Delay_Us(1);
}
/* 已經過去了 100us 存在脈衝還沒到來,代表裝置不存在 */
if (Time_Count >= 100)
return 1;
/* 脈衝到來,復位超時計數 */
else
Time_Count = 0;
/* 對應時序中的 DS18B20 存在脈衝 (60 - 240)us */
while (!DQ_Read && Time_Count < 240)
{
Time_Count++;
HAL_Delay_Us(1);
}
/* 由時序圖可知,存在脈衝最長不得超過 240us */
if (Time_Count >= 240)
return 1;
else
return 0; //檢測到存在脈衝
}
/*
讀取 1bit
先將匯流排拉低 15us 後,讀取匯流排狀態
*/
uint8_t Ds18b20_Read_Bit(void)
{
uint8_t dat;
//輸出模式
DQ_GPIO_OUT();
//先拉低匯流排 15us 後讀取匯流排狀態
DQ_Write(DQ_LEVEL_LOW);
HAL_Delay_Us(15);
//下面要讀取匯流排值,將引腳設定成輸入模式
DQ_GPIO_IN();
if (DQ_Read == SET)
dat = 1;
else
dat = 0;
//讀取週期至少 60us
HAL_Delay_Us(50);
return dat;
}
/*
從 DS18B20 上讀取 1Byte
低位到高位
*/
uint8_t Ds18B20_Read_Byte(void)
{
uint8_t data = 0x00,mask;
for (mask = 0x01;mask != 0;mask <<= 1)
{
if (Ds18b20_Read_Bit() == SET)
data |= mask;
else
data &= ~mask;
}
return data;
}
/*
寫位元組,低位先行
寫0: 由時序圖可知,拉低匯流排至少 60us 表示寫 0
寫1: 由時序圖可知,拉低匯流排大於 1us 並且小於 15us 後,緊接著拉高匯流排,總時間超過 60us
寫週期必須有 1us 的恢復時間
*/
void Ds18B20_Write_Byte(uint8_t data)
{
uint8_t mask;
for (mask = 0x01;mask != 0;mask <<= 1)
{
DQ_GPIO_OUT();
//寫0
if ((data & mask) == RESET)
{
/* 拉低匯流排至少 60us */
DQ_Write(DQ_LEVEL_LOW);
HAL_Delay_Us(70);
//2us 的恢復時間
DQ_Write(DQ_LEVEL_HIGHT);
HAL_Delay_Us(2);
}
else //寫1
{
/* 拉低匯流排大於 1us 並且小於 15us */
DQ_Write(DQ_LEVEL_LOW);
HAL_Delay_Us(9);
/* 拉高匯流排,總時間超過 60us */
DQ_Write(DQ_LEVEL_HIGHT);
HAL_Delay_Us(55);
}
}
}
DS18B20是通過ROM指令進行操作的,下圖展示獲取溫度的一種流程
/*
獲取溫度
此獲取方法為跳過 ROM 讀取,適合於匯流排上只有一個裝置
*/
float Ds18b20_Get_Temp(void)
{
uint8_t tpmsb, tplsb;
short s_tem;
float f_tem;
Ds18b20_Reset();
Ds18B20_CheckPulse();
Ds18B20_Write_Byte(SKIP_ROM); /* 跳過 ROM */
Ds18B20_Write_Byte(CONVERT_TEMP); /* 開始轉換 */
Ds18b20_Reset();
Ds18B20_CheckPulse();
Ds18B20_Write_Byte(SKIP_ROM); /* 跳過 ROM */
Ds18B20_Write_Byte(READ_SCRATCHPAD); /* 讀溫度值 */
tplsb = Ds18B20_Read_Byte();
tpmsb = Ds18B20_Read_Byte();
s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;
if( s_tem < 0 ) /* 負溫度 */
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = s_tem * 0.0625;
return f_tem;
}
想要完整工程,點選評論