STM32F4 HAL库开发 -- 温度传感器(DS18B20)
參看:《嵌入式-STM32開發指南》第三部分 外設篇 - 第2章 溫度傳感器DS18B20
這篇文章講的非常詳細了。
一、簡介
1、概述
DS18B20 是 DALLAS 最新單線數字溫度傳感器,新的"一線器件"體積更小、適用電壓更寬、更經濟。Dallas 半導體公司的數字化溫度傳感器 DS1820 是世界上第一片支持 "一線總線"接口的溫度傳感器。
DS18B20采用的單總線協議,也就是只需占用主機一個I/O口,無需其他外圍電路,直接將環境溫度轉換為數字信號,使用戶可輕松地組建傳感器網絡,為測量系統的構建引入全新概念。另外,以"一線總線"的數字方式傳輸,大大提高了系統的抗干擾性。適合于惡劣環境的現場溫度測量,如:環境控制、設備或過程控制、測溫類消費電子產品等。
2、特性
(1) 具有獨特的單總線接口,與主機主需要一個線即可實現雙向通信;
(2) 測溫范圍為-55+125℃,在-10+85℃時,精度為±0.5℃;
(3) 可編程的分辨率為 9~12 位,對應的可分辨溫度分別為 0.5℃、0.25℃、0.125℃和 0.0625℃;
(4) 在9 位分辨率時,最多在93.75ms 內把溫度值轉換為數字,在12 位分辨率時,最多在 750ms 內把溫度值轉換為數字;
(5) 負壓特性,電源極性接反時,溫度計不會因發熱而燒毀,但不能正常工作。
(6) 工作電壓范圍寬,電壓范圍為3.0~5.5V,還可用數據線供電;
(7) 支持多點組網,多個DS18B20可以并聯實現多點組網測溫。值得注意的是,如果數量過多,需要解決供電問題,否則電壓過低會導致信號傳輸不穩定;
(8) 測量結果采用數字信號輸出,同時具有CRC校驗,具較強的抗干擾和糾錯能力。
3、外形結構
DS18B20 內部結構主要由四部分組成:64 位光刻 ROM、溫度傳感器、非揮發的溫度報警觸發器 TH 和 TL、配置寄存器。DS18B20 的管腳排列如下圖所示。
其中與操作有關的有:64位光刻ROM、9個字節的RAM存儲器、溫度傳感器、EERPOM(溫度報警寄存器TH和TL、配置寄存器)
二、HAL庫完整代碼
/* Includes*********************************************************************/ #include "stm32f103_DS18B20.h"/* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ static void DS18B20_Mode_IPU(void); static void DS18B20_Mode_Out_PP(void); static void DS18B20_Rst(void); static uint8_t DS18B20_Presence(void); static uint8_t DS18B20_ReadBit(void); static uint8_t DS18B20_ReadByte(void); static void DS18B20_WriteByte(uint8_t dat); static void DS18B20_SkipRom(void); static void DS18B20_MatchRom(void);#define CPU_FREQUENCY_MHZ 72 // STM32時鐘主頻 void delay_us(__IO uint32_t delay) {int last, curr, val;int temp;while (delay != 0){temp = delay > 900 ? 900 : delay;last = SysTick->VAL;curr = last - CPU_FREQUENCY_MHZ * temp;if (curr >= 0){do{val = SysTick->VAL;}while ((val < last) && (val >= curr));}else{curr += CPU_FREQUENCY_MHZ * 1000;do{val = SysTick->VAL;}while ((val <= last) || (val > curr));}delay -= temp;} }static void delay_us_bak(uint16_t time) {uint8_t i;while(time){ for (i = 0; i < 10; i++){}time--;} }/*** @brief DS18B20 初始化函數* @param None* @retval None*/ uint8_t DS18B20_Init(void) {DS18B20_Dout_GPIO_CLK_ENABLE();DS18B20_Mode_Out_PP();DS18B20_Dout_HIGH();DS18B20_Rst();return DS18B20_Presence (); }/*** @brief 使DS18B20-DATA引腳變為上拉輸入模式* @param None* @retval None*/ static void DS18B20_Mode_IPU(void) {GPIO_InitTypeDef GPIO_InitStruct;/* 串口外設功能GPIO配置 */GPIO_InitStruct.Pin = DS18B20_Dout_PIN;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct); }/*** @brief 使DS18B20-DATA引腳變為推挽輸出模式* @param None* @retval None*/ static void DS18B20_Mode_Out_PP(void) {GPIO_InitTypeDef GPIO_InitStruct;/* 串口外設功能GPIO配置 */GPIO_InitStruct.Pin = DS18B20_Dout_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct); }/*** @brief 主機給從機發送復位脈沖* @param None* @retval None*/ static void DS18B20_Rst(void) {/* 主機設置為推挽輸出 */DS18B20_Mode_Out_PP();DS18B20_Dout_LOW();/* 主機至少產生480us的低電平復位信號 */delay_us(750);/* 主機在產生復位信號后,需將總線拉高 */DS18B20_Dout_HIGH();/*從機接收到主機的復位信號后,會在15~60us后給主機發一個存在脈沖*/delay_us(15); }/*** @brief 檢測從機給主機返回的存在脈沖* @param None* @retval 0:成功,1:失敗*/ static uint8_t DS18B20_Presence(void) {uint8_t pulse_time = 0;/* 主機設置為上拉輸入 */DS18B20_Mode_IPU();/* 等待存在脈沖的到來,存在脈沖為一個60~240us的低電平信號 * 如果存在脈沖沒有來則做超時處理,從機接收到主機的復位信號后,會在15~60us后給主機發一個存在脈沖*/while( DS18B20_Data_IN() && pulse_time<100 ){pulse_time++;delay_us(1);} /* 經過100us后,存在脈沖都還沒有到來*/if( pulse_time >=100 )return 1;elsepulse_time = 0;/* 存在脈沖到來,且存在的時間不能超過240us */while( !DS18B20_Data_IN() && pulse_time<240 ){pulse_time++;delay_us(1);} if( pulse_time >=240 )return 1;elsereturn 0; }/*** @brief 從DS18B20讀取一個bit* @param None* @retval 讀取到的數據*/ static uint8_t DS18B20_ReadBit(void) {uint8_t dat;/* 讀0和讀1的時間至少要大于60us */ DS18B20_Mode_Out_PP();/* 讀時間的起始:必須由主機產生 >1us <15us 的低電平信號 */DS18B20_Dout_LOW();delay_us(10);/* 設置成輸入,釋放總線,由外部上拉電阻將總線拉高 */DS18B20_Mode_IPU();//Delay_us(2);if( DS18B20_Data_IN() == SET )dat = 1;elsedat = 0;/* 這個延時參數請參考時序圖 */delay_us(45);return dat; }/*** @brief 從DS18B20讀一個字節,低位先行* @param None* @retval 讀取到的數據*/ static uint8_t DS18B20_ReadByte(void) {uint8_t i, j, dat = 0; for(i=0; i<8; i++) {j = DS18B20_ReadBit(); dat = (dat) | (j<<i);}return dat; }/*** @brief 寫一個字節到DS18B20,低位先行* @param dat:待寫入數據* @retval None*/ static void DS18B20_WriteByte(uint8_t dat) {uint8_t i, testb;DS18B20_Mode_Out_PP();for( i=0; i<8; i++ ){testb = dat&0x01;dat = dat>>1; /* 寫0和寫1的時間至少要大于60us */if (testb){ DS18B20_Dout_LOW();/* 1us < 這個延時 < 15us */delay_us(8);DS18B20_Dout_HIGH();delay_us(58);} else{ DS18B20_Dout_LOW();/* 60us < Tx 0 < 120us */delay_us(70);DS18B20_Dout_HIGH(); /* 1us < Trec(恢復時間) < 無窮大*/delay_us(2);}} }/*** @brief 跳過匹配 DS18B20 ROM* @param None* @retval None*/ static void DS18B20_SkipRom ( void ) {DS18B20_Rst(); DS18B20_Presence(); DS18B20_WriteByte(0XCC); /* 跳過 ROM */ }/*** @brief 執行匹配 DS18B20 ROM* @param None* @retval None*/ static void DS18B20_MatchRom ( void ) {DS18B20_Rst(); DS18B20_Presence(); DS18B20_WriteByte(0X55); /* 匹配 ROM */ }/** 存儲的溫度是16 位的帶符號擴展的二進制補碼形式* 當工作在12位分辨率時,其中5個符號位,7個整數位,4個小數位** |---------整數----------|-----小數 分辨率 1/(2^4)=0.0625----|* 低字節 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |*** |-----符號位:0->正 1->負-------|-----------整數-----------|* 高字節 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |** * 溫度 = 符號位 + 整數 + 小數*0.0625*/ /*** @brief 在跳過匹配 ROM 情況下獲取 DS18B20 溫度值 * @param None* @retval 溫度值*/ float DS18B20_GetTemp_SkipRom ( void ) {uint8_t tpmsb, tplsb;short s_tem;float f_tem;DS18B20_SkipRom ();DS18B20_WriteByte(0X44); /* 開始轉換 */DS18B20_SkipRom ();DS18B20_WriteByte(0XBE); /* 讀溫度值 */tplsb = DS18B20_ReadByte(); tpmsb = DS18B20_ReadByte(); s_tem = tpmsb<<8;s_tem = s_tem | tplsb;if( s_tem < 0 ) /* 負溫度 */f_tem = (~s_tem+1) * 0.0625; elsef_tem = s_tem * 0.0625;return f_tem; }/*** @brief 在匹配 ROM 情況下獲取 DS18B20 溫度值 * @param ds18b20_id:用于存放 DS18B20 序列號的數組的首地址* @retval None*/ void DS18B20_ReadId ( uint8_t * ds18b20_id ) {uint8_t uc;DS18B20_WriteByte(0x33); //讀取序列號for ( uc = 0; uc < 8; uc ++ )ds18b20_id [ uc ] = DS18B20_ReadByte(); }/*** @brief 在匹配 ROM 情況下獲取 DS18B20 溫度值 * @param ds18b20_id:存放 DS18B20 序列號的數組的首地址* @retval 溫度值*/ float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id ) {uint8_t tpmsb, tplsb, i;short s_tem;float f_tem;DS18B20_MatchRom (); //匹配ROMfor(i=0;i<8;i++)DS18B20_WriteByte ( ds18b20_id [ i ] ); DS18B20_WriteByte(0X44); /* 開始轉換 */DS18B20_MatchRom (); //匹配ROMfor(i=0;i<8;i++)DS18B20_WriteByte ( ds18b20_id [ i ] ); DS18B20_WriteByte(0XBE); /* 讀溫度值 */tplsb = DS18B20_ReadByte(); tpmsb = DS18B20_ReadByte(); s_tem = tpmsb<<8;s_tem = s_tem | tplsb;if( s_tem < 0 ) /* 負溫度 */f_tem = (~s_tem+1) * 0.0625; elsef_tem = s_tem * 0.0625;return f_tem; }總結
以上是生活随笔為你收集整理的STM32F4 HAL库开发 -- 温度传感器(DS18B20)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学微信,抖音也上线PC版
- 下一篇: 什么时候觉得自己该离职了?