「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

1)實驗平臺:【正點原子】 NANO STM32F103 開發板

2)摘自《正點原子STM32 F1 開發指南(NANO 板-HAL 庫版)》關注官方微信號公眾號,獲取更多資料:正點原子

「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

第二十六章 DS18B20 數字溫度傳感器實驗

STM32 中容量內部沒自帶溫度傳感器,所以,本章我們將向大家介紹如何通過 STM32 來

讀取外部數字溫度傳感器的溫度,來得到較為準確的環境溫度。在本章中,我們將學習使用單

總線技術,通過它來實現 STM32 和外部溫度傳感器(DS18B20)的通信,並把從溫度傳感器得

到的溫度顯示在數碼管上。本章分為如下幾個部分:

26.1 DS18B20 簡介

26.2 硬件設計

26.3 軟件設計

26.4 下載驗證

26.1 DS18B20 簡介

DS18B20 是由 DALLAS 半導體公司推出的一種的“一線總線”接口的溫度傳感器。與傳

統的熱敏電阻等測溫元件相比,它是一種新型的體積小、適用電壓寬、與微處理器接口簡單的

數字化溫度傳感器。一線總線結構具有簡潔且經濟的特點,可使用戶輕鬆地組建傳感器網絡,

從而為測量系統的構建引入全新概念,測量溫度範圍為-55~+125℃ ,精度為±0.5℃。現場溫

度直接以“一線總線”的數字方式傳輸,大大提高了系統的抗干擾性。它能直接讀出被測溫度,

並且可根據實際要求通過簡單的編程實現 9~l2 位的數字值讀數方式。它工作在 3—5.5 V 的電

壓範圍,採用多種封裝形式,從而使系統設計靈活、方便,設定分辨率及用戶設定的報警溫度

存儲在 EEPROM 中,掉電後依然保存。其內部結構如圖 26.1.1 所示:

「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

圖 26.1.1 DS18B20 內部結構圖

ROM 中的 64 位序列號是出廠前被光記好的,它可以看作是該 DS18B20 的地址序列碼,每

DS18B20 的 64 位序列號均不相同。64 位 ROM 的排列是:前 8 位是產品家族碼,接著 48 位是

DS18B20 的序列號,最後 8 位是前面 56 位的循環冗餘校驗碼(CRC=X8+X5 +X4 +1)。ROM 作

用是使每一個 DS18B20 都各不相同,這樣就可實現一根總線上掛接多個。

所有的單總線器件要求採用嚴格的信號時序,以保證數據的完整性。DS18B20 共有 6 種信

號類型:復位脈衝、應答脈衝、寫 0、寫 1、讀 0 和讀 1。所有這些信號,除了應答脈衝以外,

都由主機發出同步信號。並且發送所有的命令和數據都是字節的低位在前。這裡我們簡單介紹

這幾個信號的時序:

1)復位脈衝和應答脈衝

單總線上的所有通信都是以初始化序列開始。主機輸出低電平,保持低電平時間至少 480

us,,以產生復位脈衝。接著主機釋放總線,4.7K 的上拉電阻將單總線拉高,延時 15~60 us,

並進入接收模式(Rx)。接著 DS18B20 拉低總線 60~240 us,以產生低電平應答脈衝,

若為低電平,再延時 480 us。

2)寫時序

寫時序包括寫 0 時序和寫 1 時序。所有寫時序至少需要 60us,且在 2 次獨立的寫時序之間

至少需要 1us 的恢復時間,兩種寫時序均起始於主機拉低總線。寫 1 時序:主機輸出低電平,

延時 2us,然後釋放總線,延時 60us。寫 0 時序:主機輸出低電平,延時 60us,然後釋放總線,

延時 2us。

3)讀時序

單總線器件僅在主機發出讀時序時,才向主機傳輸數據,所以,在主機發出讀數據命令後,

必須馬上產生讀時序,以便從機能夠傳輸數據。所有讀時序至少需要 60us,且在 2 次獨立的讀

時序之間至少需要 1us 的恢復時間。每個讀時序都由主機發起,至少拉低總線 1us。主機在讀

時序期間必須釋放總線,並且在時序起始後的 15us 之內採樣總線狀態。典型的讀時序過程為:

主機輸出低電平延時 2us,然後主機轉入輸入模式延時 12us,然後讀取單總線當前的電平,然

後延時 50us。

在瞭解了單總線時序之後,我們來看看 DS18B20 的典型溫度讀取過程,DS18B20 的典型

溫度讀取過程為:復位→發 SKIP ROM 命令(0XCC)→發開始轉換命令(0X44)→延時→復

位→發送 SKIP ROM 命令(0XCC)→發讀存儲器命令(0XBE)→連續讀出兩個字節數據(即

溫度)→結束。

DS18B20 的介紹就到這裡,更詳細的介紹,請大家參考 DS18B20 的技術手冊。

26.2 硬件設計

由於開發板上標準配置是沒有 DS18B20 這個傳感器的,只有接口,所以要做本章的實驗,

大家必須找一個 DS18B20 插在預留的 18B20 接口上。

本章實驗功能簡介:開機的時候先檢測是否有 DS18B20 存在,如果沒有,則提示錯誤。

只有在檢測到 DS18B20 之後才開始讀取溫度並顯示在 LCD 上,如果發現了 DS18B20,則程

序每隔 100ms 左右讀取一次數據,並把溫度顯示在 LCD 上。同樣我們也是用 DS0 來指示程序

正在運行。

所要用到的硬件資源如下:

1) 指示燈 DS0、DS3

2) 數碼管

3) DS18B20 溫度傳感器

前兩部分,在之前的實例已經介紹過了,而DS18B20溫度傳感器屬於外部器件(板上沒有

直接焊接),這裡也不介紹。本章,我們僅介紹DS18B20接口和STM32的連接電路,如圖26.2.1

所示:

「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

圖 26.2.1 DS18B20 接口與 STM32 的連接電路圖

從上圖可以看出,我們使用的是 STM32 的 PB9 來連接 U2 的 1WIRE_DQ 引腳,圖中 U2

為 DHT11(數字溫溼度傳感器)和 DS18B20 共用的一個接口,DHT11 我們將在下一章介紹。

DS18B20 只用到 U2 的 3 個引腳(U2 的 1、2 和 3 腳),將 DS18B20 傳感器插入到這個上

面就可以通過 STM32 來讀取 DS18B20 的溫度了。連接示意圖如圖 26.2.2 所示:

「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

圖 26.2.2 DS18B20 連接示意圖

注意:DS18B20 的平面部分(有字的那面)應該朝內,而曲面部分朝外。然後插入如圖所

示的三個孔內。

26.3 軟件設計

打開我們的 DS18B20 數字溫度傳感器實驗工程可以看到我們添加了 ds18b20.c 文件以及其

頭文件 ds18b20.h 文件,所有 ds18b20 驅動代碼和相關定義都分佈在這兩個文件中。

打開 ds18b20.c,該文件代碼如下:

//復位 DS18B20

void DS18B20_Rst(void)

{

DS18B20_IO_OUT(); //設置為輸出

DS18B20_DQ_OUT=0; //拉低 DQ

delay_us(750); //拉低 750us

DS18B20_DQ_OUT=1; //DQ=1

delay_us(15); //15US

}

//等待 DS18B20 的回應

//返回 1:未檢測到 DS18B20 的存在

//返回 0:存在

u8 DS18B20_Check(void)

{

u8 retry=0;

DS18B20_IO_IN(); //設置為輸入

while (DS18B20_DQ_IN&&retry<200)

{

retry++;

delay_us(1);

};

if(retry>=200)return 1;

else retry=0;

while (!DS18B20_DQ_IN&&retry<240)

{

retry++;

delay_us(1);

};

if(retry>=240)return 1;

return 0;

}

//從 DS18B20 讀取一個位

//返回值:1/0

u8 DS18B20_Read_Bit(void)

{

u8 data;

DS18B20_IO_OUT(); //設置為輸出

DS18B20_DQ_OUT=0;

delay_us(2);

DS18B20_DQ_OUT=1;

DS18B20_IO_IN(); //設置為輸入

delay_us(12);

if(DS18B20_DQ_IN)data=1;

else data=0;

delay_us(50);

return data;

}

//從 DS18B20 讀取一個字節

//返回值:讀到的數據

u8 DS18B20_Read_Byte(void)

{

u8 i,j,dat;

dat=0;

for (i=1;i<=8;i++)

{

j=DS18B20_Read_Bit();

dat=(j<<7)|(dat>>1);

}

return dat;

}

//寫一個字節到 DS18B20

//dat:要寫入的字節

void DS18B20_Write_Byte(u8 dat)

{

u8 j;

u8 testb;

DS18B20_IO_OUT(); //設置為輸出

for (j=1;j<=8;j++)

{

testb=dat&0x01;

dat=dat>>1;

if(testb) // 寫 1

{

DS18B20_DQ_OUT=0;

delay_us(2);

DS18B20_DQ_OUT=1;

delay_us(60);

}

else //寫 0

{

DS18B20_DQ_OUT=0;

delay_us(60);

DS18B20_DQ_OUT=1;

delay_us(2);

}

}

}

//開始溫度轉換

void DS18B20_Start(void)

{

DS18B20_Rst();

DS18B20_Check();

DS18B20_Write_Byte(0xcc);// skip rom

DS18B20_Write_Byte(0x44);// convert

}

//初始化 DS18B20 的 IO 口 DQ 同時檢測 DS 的存在

//返回 1:不存在

//返回 0:存在

u8 DS18B20_Init(void)

{

GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_GPIOB_CLK_ENABLE(); //開啟 GPIB 時鐘

GPIO_Initure.Pin=GPIO_PIN_9; //PB9

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推輓輸出

GPIO_Initure.Pull=GPIO_PULLUP; //上拉

GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速

HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化

DS18B20_Rst();

return DS18B20_Check();

}

//從 ds18b20 得到溫度值

//精度:0.1C

//返回值:溫度值 (-550~1250)

short DS18B20_Get_Temp(void)

{

u8 temp;

u8 TL,TH;

short tem;

DS18B20_Start (); //開始轉換

DS18B20_Rst();

DS18B20_Check();

DS18B20_Write_Byte(0xcc); // skip rom

DS18B20_Write_Byte(0xbe); // convert

TL=DS18B20_Read_Byte(); // LSB

TH=DS18B20_Read_Byte(); // MSB

if(TH>7)

{

TH=~TH;

TL=~TL;

temp=0;//溫度為負

}else temp=1;//溫度為正

tem=TH; //獲得高八位

tem<<=8;

tem+=TL;//獲得底八位

tem=(double)tem*0.625;//轉換

if(temp)return tem; //返回溫度值

else return -tem;

}

該部分代碼就是根據我們前面介紹的單總線操作時序來讀取 DS18B20 的溫度值的,DS18B20

的溫度通過 DS18B20_Get_Temp 函數讀取,該函數的返回值為帶符號的短整形數據,返回值的

範圍為-550~1250,其實就是溫度值擴大了 10 倍。

然後我們打開 ds18b20.h,該文件下面主要是一些 IO 口位帶操作定義以及函數申明,沒有

什麼特別需要講解的地方。最後打開 main.c,該文件代碼如下:

// 共陰數字數組

// 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全滅

u8 smg_num[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,

0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00};

short temperature;//溫度值

u8 smg_wei=4;//數碼管位選

u8 num=0;//數碼管數值

u16 led_t=0;//led 時間

u16 temp_t=0;//採樣時間

u8 flag=0;//溫度正負標誌位

int main(void)

{

HAL_Init(); //初始化 HAL 庫

Stm32_Clock_Init(RCC_PLL_MUL9); //設置時鐘,72M

delay_init(72); //初始化延時函數

uart_init(115200);

//串口初始化為 115200

LED_Init();

//初始化與 LED 連接的硬件接口

LED_SMG_Init(); //數碼管初始化

printf("NANO STM32\\r\\n");

printf("DS18B20 TEST\\r\\n");

while(DS18B20_Init()) //DS18B20 初始化

{

printf("DS18B20 Error\\r\\n");

delay_ms(200);

LED3=!LED3;//LED3 閃爍表示 DS18B20 初始化失敗

}

LED3=1;

printf("DS18B20 OK\\r\\n");

TIM3_Init(19,7199); //數碼管 2ms 定時顯示

while(1)

{

}

}

//回調函數,定時器中斷服務函數調用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if(htim==(&TIM3_Handler))

{

temp_t++;

if(temp_t==500)//DS18B20 1S 採樣

{

temp_t=0;

temperature=DS18B20_Get_Temp();//獲取溫度值

if(temperature<0)//若溫度為負數

{

temperature=-temperature;

flag=1;

}else flag=0;

}

switch(smg_wei)

{

case 4: if(flag)num = 0x02; //顯示"-"以表示負溫度

else num=0x00;

break;

case 5: num = smg_num[temperature/10/10];break; //溫度值

case 6: num = smg_num[temperature/10%10]|0x01; break;

case 7: num =smg_num[temperature%10];break;

}

LED_Write_Data(num,smg_wei);//寫數據到數碼管

LED_Refresh();//更新顯示

smg_wei++;

if(smg_wei==8) smg_wei=4;

led_t++;

if(led_t==250)//LED0 500ms 閃爍

{

led_t=0;

LED0=!LED0;

}

}

}

由於 DS18B20 的時序是使用軟件時序操作的,為了不打擾時序操作,我們將讀取溫度放到

在定時器中斷執行,以每隔 1S 時間採集溫度,數碼管同樣是以 2ms 時間動態掃描顯示採集的溫

度值,DS0 以每 500ms 閃爍一次,以表示程序正在運行。

至此,我們本章的軟件設計就結束了。

26.4 下載驗證

在代碼編譯成功之後,我們通過下載代碼到 ALIENTEK NANO STM32F1 開發板上,可以

看到數碼管顯示當前的溫度值(假定 DS18B20 已經接上去了),如圖 26.4.1 所示:

「正點原子NANO STM32F103開發板資料連載第26章 數字溫度傳感器

圖 26.4.1 DS18B20 實驗效果圖

該程序還可以讀取並顯示負溫度值的,只是由於本人在廣州,是沒辦法看到了(除非放到

冰箱),具備條件的讀者可以測試一下。


分享到:


相關文章: