a片在线观看免费看视频_欧美婬片在线a_同性男男无遮挡无码视频_久久99狠狠色精品一区_《性妲己》电影在线观看_久久久99婷婷久久久久久_亚洲精品久久久久58_激情在线成人福利小电影_色婷婷久久综合五月激情网

0 賣盤信息
BOM詢價
您現在的位置: 首頁 > 技術方案 >工業控制 > 基于STM32單片機對DS18B20溫度傳感器的驅動設計方案

基于STM32單片機對DS18B20溫度傳感器的驅動設計方案

來源: elecfans
2021-11-17
類別:工業控制
eye 116
文章創建人 拍明

原標題:基于STM32單片機對DS18B20溫度傳感器的驅動設計方案

  基于STM32單片機對DS18B20溫度傳感器的驅動設計方案

  在當今物聯網與智能控制系統飛速發展的時代,溫度數據采集作為環境感知的重要組成部分,其精度與穩定性直接影響到整個系統的性能。DS18B20作為一款經典的數字溫度傳感器,以其獨特的單總線(One-Wire)通信方式、寬廣的測量范圍、高精度以及優秀的環境適應性,在工業控制、消費電子、醫療設備、智能家居等諸多領域得到了廣泛應用。本設計方案將深入探討如何基于功能強大的STM32系列微控制器,實現對DS18B20溫度傳感器的穩定、高效驅動,涵蓋硬件選型、軟件設計、通信協議解析、數據處理以及常見問題解決方案等多個方面。

image.png

  1. 系統概述與設計目標

  本系統旨在構建一個基于STM32微控制器驅動DS18B20溫度傳感器的高精度溫度采集模塊。其核心目標包括:

  高精度溫度采集: 利用DS18B20傳感器本身的高精度(可配置9-12位分辨率)確保測量結果的準確性。

  穩定可靠的通信: 實現STM32與DS18B20之間基于單總線協議的穩定數據傳輸,抵抗干擾。

  靈活的硬件接口: 設計合理的硬件連接方案,便于集成與擴展。

  高效的軟件驅動: 編寫模塊化、可移植的軟件代碼,實現DS18B20的初始化、溫度讀取、配置等功能。

  友好的數據輸出: 將采集到的溫度數據通過串口或其他接口輸出,便于上位機顯示或進一步處理。

  低功耗設計(可選): 考慮在特定應用場景下,如何通過軟件和硬件協同實現低功耗運行。

  2. 核心元器件選型與功能分析

  成功的嵌入式系統設計離不開對核心元器件的精確選擇與深刻理解。本章節將詳細闡述STM32微控制器與DS18B20溫度傳感器的選型依據、功能特性以及其在整個系統中的關鍵作用,并介紹其他必要的輔助元器件。

  2.1 微控制器單元(MCU):STM32系列

  2.1.1 選型推薦

  對于DS18B20的驅動,由于其單總線協議對時序的嚴格要求,以及未來可能的功能擴展(如LCD顯示、網絡通信等),推薦選用STM32F103C8T6STM32F401RCT6

  STM32F103C8T6: 這是一款基于ARM Cortex-M3內核的微控制器,屬于STM32F1系列的主流產品。

  CPU內核(Cortex-M3): 提供強大的處理能力,可以高效執行DS18B20的單總線時序操作和數據解析算法。

  GPIO(通用輸入輸出): 用于與DS18B20的DQ線直接連接,并通過軟件控制其輸出高低電平,或配置為輸入模式讀取數據。F103C8T6的GPIO可以配置為推挽輸出、開漏輸出、浮空輸入、上拉/下拉輸入等多種模式,這對于單總線協議中DQ線的控制至關重要。

  定時器(Timers): DS18B20的單總線協議對時序有嚴格要求,例如復位脈沖的持續時間、數據位的采樣點等。STM32的定時器可以提供精確的微秒級延時,確保通信的準確性。

  NVIC(嵌套向量中斷控制器): 可以管理外部中斷,雖然DS18B20通常不需要中斷來驅動,但在多任務系統中,或需要對通信錯誤進行實時響應時,中斷功能會非常有用。

  Flash存儲器和SRAM: 用于存儲程序代碼和運行時數據,包括DS18B20的驅動代碼、溫度數據、以及其他應用邏輯。

  高性價比: F103系列是STM32家族中性價比較高的入門級芯片,非常適合學習和中小型項目開發。它的成本效益使其成為許多原型設計和量產應用的首選。

  豐富的資源: 擁有72MHz的主頻,64KB的Flash存儲器和20KB的SRAM,以及多個通用GPIO、定時器、USART、SPI、I2C等外設。這些資源足以滿足DS18B20的時序要求,并為未來擴展其他傳感器、通信模塊(如藍牙、Wi-Fi)或顯示設備預留了足夠的硬件基礎。

  成熟的生態系統: ST公司為STM32F1系列提供了非常完善的開發工具鏈(如Keil MDK, STM32CubeIDE)和豐富的例程、庫函數(如HAL庫、LL庫),社區支持廣泛,方便開發者快速上手和調試。

  管腳兼容性: TSSOP48封裝,引腳數量適中,便于PCB設計和手工焊接。

  選擇理由:

  功能:

  STM32F401RCT6: 這是一款基于ARM Cortex-M4內核的微控制器,屬于STM32F4系列的入門級產品。

  FPU(浮點單元): 大幅提升浮點運算速度,對于需要精確溫度計算和顯示的應用非常有利。

  更高效的DMA(直接存儲器訪問): 可以實現數據在內存和外設之間的高速傳輸,減輕CPU負擔,提高系統整體效率。雖然DS18B20的通信量不大,但DMA在多任務系統中依然能發揮作用。

  更寬的工作溫度范圍和更高可靠性: 部分F4系列芯片設計用于更嚴苛的工業環境,這可能是一個額外優勢。

  更高性能: F401系列擁有84MHz的主頻,配備浮點單元(FPU),使其在進行復雜數學運算(如溫度數據的浮點轉換、濾波算法等)時效率更高。如果未來的應用需要更復雜的信號處理或圖形顯示,F401會提供更好的性能儲備。

  更大的存儲空間: 256KB的Flash和64KB的SRAM,為更大型的應用程序和數據存儲提供了充足的空間。

  更多高級外設: 比如更多的定時器、DMA控制器、以及更快的ADC等。雖然DS18B20本身不直接使用ADC,但如果系統中還有其他模擬傳感器,這些高級外設會很有用。

  適用于更復雜的系統: 如果考慮到未來項目可能擴展到更復雜的系統,例如需要運行RTOS(實時操作系統)、進行大量數據處理或與更高速外設通信,F401提供了更強的處理能力和更豐富的外設接口。

  選擇理由:

  功能: 除了F103的所有功能外,F401還具備:總結: 對于初學者和大多數基本溫度采集應用,STM32F103C8T6是更具性價比和易用性的選擇。如果項目對性能有更高要求,或者有未來擴展至更復雜系統的考慮,STM32F401RCT6將是更好的選擇。

  2.2 溫度傳感器:DS18B20

  2.2.1 選型推薦

  DS18B20是Maxim Integrated公司(現已被Analog Devices收購)生產的一款單總線數字溫度傳感器。

  選擇理由:

  單總線接口: 這是DS18B20最顯著的特點,只需一根數據線(DQ)即可與微控制器進行通信,大大簡化了硬件連接。DQ線同時用于供電(寄生電源模式)和數據傳輸,減少了布線復雜性。

  寬測量范圍: -55°C 至 +125°C,覆蓋了大多數日常及工業應用場景。

  高精度: 在-10°C至+85°C范圍內,精度可達±0.5°C。用戶可配置9位、10位、11位或12位的測量分辨率,對應的轉換時間分別為93.75ms、187.5ms、375ms、750ms,精度越高,轉換時間越長。

  數字輸出: 直接輸出數字溫度值,避免了傳統模擬溫度傳感器(如熱敏電阻、PT100)需要進行AD轉換的環節,簡化了硬件設計,提高了抗干擾能力,且無需校準。

  獨特ID: 每個DS18B20都有一個獨一無二的64位ROM序列碼,允許多個DS18B20并聯在同一根單總線上,并通過ROM匹配指令進行尋址,實現多點溫度測量。

  寄生電源模式: 在某些應用中,可以通過數據線(DQ)直接供電,無需額外電源線,進一步簡化了布線。但通常建議使用外部電源供電,以保證通信的穩定性和轉換的準確性,尤其是在長距離傳輸或多點測量時。

  封裝多樣性: 提供TO-92、SOP8、防水探頭(如不銹鋼封裝)等多種封裝形式,滿足不同應用環境的需求。TO-92封裝適合板載或短距離測溫,防水探頭則適合液體或潮濕環境。

  功能:

  溫度測量: 將測得的溫度值轉換為數字信號,存儲在其內部的2字節溫度寄存器中。

  用戶可編程分辨率: 用戶可以通過寫入配置寄存器來設置溫度轉換的分辨率。

  報警功能: 具有可編程的高低溫度報警觸發點(TH和TL寄存器),當測得的溫度超出設定范圍時,DS18B20會設置一個報警標志,并通過報警搜索命令被識別出來。

  暫存器(Scratchpad): 包含溫度寄存器、高/低報警觸發寄存器(TH/TL)、配置寄存器等。

  EEPROM: 用于存儲配置數據(TH/TL和分辨率設置),即使斷電也能保存。

  64位ROM序列碼: 唯一的硬件地址,用于區分總線上的多個DS18B20。2.3 輔助元器件

  2.3.1 上拉電阻

  選型推薦: 4.7kΩ ~ 10kΩ 精密電阻。 通常選擇4.7kΩ

  作用: DS18B20的單總線協議是一個開漏(Open-Drain)總線結構。這意味著DS18B20或微控制器只能將DQ線拉低(輸出邏輯0),而不能主動拉高(輸出邏輯1)。當DQ線空閑時,或者需要傳輸邏輯1時,必須依靠外部的上拉電阻將總線拉高到VCC電平。

  選擇理由:

  協議要求: DS18B20數據手冊明確指出需要一個上拉電阻。

  保證邏輯高電平: 沒有上拉電阻,DQ線將無法達到VCC電平,導致通信錯誤。

  平衡上升/下降時間: 電阻值過大會導致上升時間過長,影響通信速度和可靠性;電阻值過小會增加功耗,并可能對DS18B20的開漏輸出電流能力造成過大負擔。4.7kΩ是經過驗證的典型值,能在確保可靠通信的同時保持較低功耗。對于長距離傳輸或多點連接,可能需要適當減小電阻值或增加有源上拉電路。

  功能:

  當總線空閑時,通過電阻將DQ線拉高至邏輯高電平。

  當DS18B20或STM32釋放總線(停止拉低)時,迅速將DQ線拉高。

  為DS18B20提供寄生電源模式下的充電電流。2.3.2 濾波電容

  選型推薦: 100nF(0.1μF)陶瓷電容,并聯在DS18B20的VCC和GND之間。對于更長的引線或噪聲較大的環境,可以在電源入口增加一個10μF或47μF的電解電容

  作用: 濾波電容用于濾除電源線上的高頻噪聲,提供穩定的電源,以及在DS18B20進行內部操作(如溫度轉換)時提供瞬時電流。

  選擇理由:

  去耦: 微控制器和傳感器在工作時會產生瞬態電流需求,導致電源線上的電壓波動。100nF陶瓷電容具有低ESR(等效串聯電阻)和良好的高頻特性,能有效地進行高頻去耦,保證VCC的穩定性。

  抗干擾: 減少外部電磁干擾(EMI)對DS18B20電源的沖擊,提高測量的準確性和通信的穩定性。

  寄生電源模式下的儲能: 在寄生電源模式下,DS18B20在溫度轉換期間會消耗較大的電流。這個電容可以作為能量儲存器,在DQ線被拉低時,為DS18B20提供所需的瞬時能量。

  功能:

  旁路高頻噪聲。

  提供穩定的電源,確保DS18B20內部電路的正常工作。

  在電流高峰時為DS18B20提供瞬時能量,防止電源跌落。2.3.3 排針/排母

  選型推薦: 2.54mm間距的直插或彎角排針/排母。

  作用: 提供便捷的硬件連接接口,便于DS18B20模塊與STM32開發板之間的插拔連接,也方便進行調試和測試。

  選擇理由:

  標準化: 2.54mm(0.1英寸)是電子元器件的常用間距,兼容性好。

  易于連接: 方便使用杜邦線進行連接,或者直接插在面包板、洞洞板上進行原型開發。

  靈活性: 方便更換DS18B20傳感器或將模塊集成到更大的系統中。

  功能:

  提供機械連接和電氣連接。

  方便調試和維護。

  3. 硬件連接方案

  DS18B20與STM32的硬件連接相對簡單,主要涉及供電、地線和數據線(DQ)。

  3.1 基本連接

  VCC (電源): 連接到STM32開發板的3.3V或5V電源(DS18B20支持3.0V至5.5V供電)。為確保穩定,通常建議連接到5V,因為DS18B20手冊規定在溫度轉換時需要較大的瞬間電流,5V電源可以提供更穩定的供電能力。

  GND (地線): 連接到STM32開發板的GND。

  DQ (數據線): 連接到STM32的任意一個通用GPIO口。例如,可以連接到PA1

  上拉電阻: 一個4.7kΩ的上拉電阻(Rpu)必須連接在DQ線和VCC之間。這是單總線協議的強制要求。

  濾波電容: 一個100nF(0.1μF)的陶瓷電容并聯在DS18B20的VCC和GND引腳之間,盡可能靠近DS18B20,用于電源去耦。3.2 連接示意圖

  +-----------------+           |     STM32       |           |                 |  DS18B20  |                 |  (TO-92/SOP8)  |                 |  -----------  |                 | |           | |                 | |    VCC----|------VCC (3.3V/5V) |           | |                 | |    GND----|------GND |           | |                 | |    DQ-----|------PA1 (GPIO) |           | |                 |  -----------  |                 |           |                 |           +-----------------+                  |                  | Rpu (4.7kΩ)                  |                 --- VCC                 ---                  |                 --- 100nF                 --- 電容                  |                 GND

  說明:

  圖中DS18B20的VCC引腳接STM32的電源,GND接STM32的地。

  DS18B20的DQ引腳通過一個4.7kΩ上拉電阻接到VCC,然后直接連接到STM32的某個GPIO引腳(例如PA1)。

  100nF的濾波電容并聯在DS18B20的VCC和GND引腳之間。3.3 多點連接

  DS18B20的單總線特性允許在同一根DQ線上連接多個傳感器。此時,每個DS18B20仍然需要自己的上拉電阻和濾波電容(雖然通常情況下,一個總線上的多個DS18B20可以共用一個主上拉電阻,但為每個傳感器提供局部濾波電容仍然是好的實踐)。STM32通過發送ROM指令(如跳過ROM、匹配ROM、搜索ROM)來與特定的DS18B20通信。

  4. 單總線(One-Wire)通信協議解析

  DS18B20的驅動核心在于理解并精確實現其單總線通信協議。該協議定義了一系列嚴格的時序要求,包括初始化、ROM指令和功能指令。所有通信都以最低有效位(LSB)優先傳輸。

  4.1 單總線時序基礎

  單總線協議是主從協議,STM32作為主設備,DS18B20作為從設備。所有通信都由主設備發起。

  4.1.1 協議信號概述

  復位(Reset)和存在(Presence)脈沖: 這是每次通信開始的第一個時序。

  主設備將DQ線拉低至少480微秒(us),然后釋放(上拉電阻將其拉高)。

  DS18B20檢測到總線被拉低后,會等待15-60us,然后將DQ線拉低60-240us作為存在脈沖,表示其已準備好通信。

  主設備在DS18B20釋放總線后(即DQ線再次被上拉電阻拉高)15-60us內讀取DQ線的狀態。如果檢測到低電平,則表示存在DS18B20。

  寫入時隙(Write Time Slot): 主設備向從設備發送數據。每個寫入時隙至少需要60us,并在120us內完成。

  寫入邏輯1: 主設備將DQ線拉低1-15us,然后釋放總線(拉高)。

  寫入邏輯0: 主設備將DQ線拉低60-120us,然后釋放總線(拉高)。

  在每次寫入時隙結束后,總線必須保持空閑至少1us。

  讀取時隙(Read Time Slot): 主設備從從設備讀取數據。每個讀取時隙至少需要60us,并在120us內完成。

  主設備將DQ線拉低1-15us,然后立即釋放總線(拉高)。

  主設備在拉低總線后15us內采樣DQ線的狀態。如果從設備要發送0,則DQ線將保持低電平;如果發送1,則DQ線將保持高電平。

  在每次讀取時隙結束后,總線必須保持空閑至少1us。4.2 ROM指令

  ROM指令用于選擇或識別總線上的DS18B20設備。

  0x33 - READ ROM: (讀取ROM碼) 主機發出此命令后,DS18B20將自己的64位ROM碼傳輸給主機。此命令只適用于總線上只有一個DS18B20的情況。

  0xCC - SKIP ROM: (跳過ROM碼) 主機發出此命令后,DS18B20直接執行后續的功能命令,不再等待ROM碼匹配。適用于總線上只有一個DS18B20,或者你確定要與所有DS18B20通信。

  0x55 - MATCH ROM: (匹配ROM碼) 主機發出此命令后,需要接著發送一個64位的ROM碼。總線上只有與該ROM碼匹配的DS18B20才會響應后續的功能命令。用于多點測溫時精確選擇目標DS18B20。

  0xF0 - SEARCH ROM: (搜索ROM碼) 用于在多點測溫系統中查找所有DS18B20的64位ROM碼。這是一個復雜的過程,通常通過專門的算法實現。4.3 功能指令

  功能指令用于控制DS18B20進行溫度轉換、讀寫暫存器等操作。在發送功能指令前,必須先發送ROM指令(通常是SKIP ROM或MATCH ROM)。

  0x44 - CONVERT T: (啟動溫度轉換) DS18B20開始進行溫度轉換。轉換過程需要一定時間(取決于分辨率設置,最長750ms)。在轉換期間,DQ線會保持低電平,轉換完成后會拉高。

  0xBE - READ SCRATCHPAD: (讀取暫存器) 主機發出此命令后,DS18B20將其內部9字節的暫存器內容傳輸給主機。暫存器內容包括:

  字節0和字節1:溫度數據(LSB和MSB)。

  字節2和字節3:TH(高溫報警閾值)和TL(低溫報警閾值)。

  字節4:配置寄存器(分辨率設置)。

  字節5、字節6、字節7:保留。

  字節8:CRC校驗碼(對前8個字節的CRC校驗)。

  0x4E - WRITE SCRATCHPAD: (寫入暫存器) 主機發出此命令后,需要接著發送TH、TL和配置寄存器三個字節的數據。

  0x48 - COPY SCRATCHPAD: (復制暫存器) 將暫存器中的TH、TL和配置寄存器數據復制到EEPROM中,斷電后仍然保存。

  0xB8 - RECALL E2: (召回EEPROM數據) 將EEPROM中存儲的TH、TL和配置寄存器數據召回到暫存器中。通常在DS18B20上電后自動執行,但也可以手動觸發。

  0xEC - READ POWER SUPPLY: (讀取電源供電模式) DS18B20會返回其當前的供電模式(外部供電或寄生供電)。4.4 溫度數據解析

  DS18B20輸出的溫度數據是2字節(16位)補碼形式。其中,低字節包含溫度的低8位,高字節包含溫度的高8位。

  數據格式:

  S Sign (符號位,1為負,0為正)

  MSB (最高有效位)

  LSB (最低有效位)例如,當分辨率為12位時,數據格式如下:

  Bit 15Bit 14Bit 13Bit 12Bit 11Bit 10Bit 9Bit 8Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0

  SSSSSSSST7T6T5T4T3T2T1T0

  導出到 Google 表格

  其中,Bit 0 到 Bit 7 是溫度的低8位,Bit 8 到 Bit 10 是溫度的高3位(12位分辨率),Bit 11 到 Bit 15 是符號位。

  轉換為攝氏度:讀取到16位數據后,需要進行符號擴展和除以對應的權重。

  對于正溫度:直接將16位數據乘以對應分辨率的權重。

  12位分辨率:1/16=0.0625 (circtextC/count)

  11位分辨率:1/8=0.125 (circtextC/count)

  10位分辨率:1/4=0.25 (circtextC/count)

  9位分辨率:1/2=0.5 (circtextC/count)

  對于負溫度:先取反加1(補碼轉換),然后乘以權重,結果為負值。示例(12位分辨率):假設讀取到數據為0x0191 (二進制 0000 0001 1001 0001) 這是正數,直接換算:0x0191=401 (十進制) 溫度 = 401times0.0625=25.0625 (circtextC)

  假設讀取到數據為0xFE6F (二進制 1111 1110 0110 1111) 這是一個負數(最高位為1)。 取反:0000 0001 1001 0000加1:0000 0001 1001 0001 (十進制 401) 溫度 = ?401times0.0625=?25.0625 (circtextC)

  5. 軟件驅動設計與實現

  軟件驅動是實現DS18B20功能的關鍵。本節將詳細介紹基于STM32HAL庫的軟件驅動設計,包括GPIO配置、延時函數、單總線基本操作(復位、讀寫位/字節)以及DS18B20高級功能實現。

  5.1 開發環境與庫選擇

  開發環境: Keil MDK-ARM或STM32CubeIDE。推薦使用STM32CubeIDE,它集成了STM32CubeMX,方便進行圖形化配置。

  庫選擇: STM32HAL庫。 HAL庫是ST官方推薦的高級抽象層庫,提供了簡單易用的API,可以快速開發。雖然LL庫(Low-Layer)能提供更精細的控制和更高的效率,但對于DS18B20這種對時序精度要求高,但數據量不大的應用,HAL庫的性能也足夠。5.2 GPIO配置

  DS18B20的DQ線是雙向的,既可以作為輸出(主設備拉低DQ線),也可以作為輸入(主設備讀取DQ線)。因此,STM32的GPIO需要頻繁地在輸出和輸入模式之間切換。

  C

  // 定義DS18B20連接的GPIO端口和引腳#define DS18B20_PORT    GPIOA#define DS18B20_PIN     GPIO_PIN_1// 設置DQ線為輸出模式 (推挽輸出)void DS18B20_SetPinOutput(void){    GPIO_InitTypeDef GPIO_InitStruct = {0};    GPIO_InitStruct.Pin = DS18B20_PIN;    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽輸出    GPIO_InitStruct.Pull = GPIO_NOPULL;          // 無上拉/下拉,依靠外部4.7kΩ上拉電阻    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速模式    HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);}// 設置DQ線為輸入模式 (浮空輸入)void DS18B20_SetPinInput(void){    GPIO_InitTypeDef GPIO_InitStruct = {0};    GPIO_InitStruct.Pin = DS18B20_PIN;    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;     // 浮空輸入    GPIO_InitStruct.Pull = GPIO_NOPULL;          // 無上拉/下拉,外部已有上拉    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速模式    HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);}// 拉低DQ線#define DS18B20_DQ_LOW()    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET)// 拉高DQ線 (實際上是釋放,依靠上拉電阻拉高)#define DS18B20_DQ_HIGH()   HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET)// 讀取DQ線狀態#define DS18B20_DQ_READ()   HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)

  GPIO模式選擇的說明:

  輸出模式: 必須配置為推挽輸出(GPIO_MODE_OUTPUT_PP)。雖然DS18B20是開漏設備,但STM32的GPIO在推挽模式下既可以輸出高電平也可以輸出低電平。當需要拉低總線時,輸出低電平;當需要釋放總線時,輸出高電平,但實際上DQ線是通過外部上拉電阻拉高的,所以即使STM32的輸出高電平能力與DS18B20的開漏特性不完全匹配,只要我們配合外部上拉電阻,并確保在需要DS18B20響應時STM32釋放DQ線(即配置為輸入或輸出高電平),就能正常工作。

  輸入模式: 必須配置為浮空輸入(GPIO_MODE_INPUT)。這是因為DQ線需要由DS18B20或外部上拉電阻來控制高低電平,STM32只需被動讀取其狀態。如果配置為上拉/下拉輸入,可能會干擾總線上的電平。

  速度: 配置為高速(GPIO_SPEED_FREQ_HIGH),以確保GPIO電平切換足夠快,滿足DS18B20的嚴格時序要求。5.3 精確延時函數

  DS18B20通信對延時精度要求很高,HAL庫的HAL_Delay()函數基于系統時鐘節拍(毫秒級),不適合微秒級延時。需要編寫一個基于CPU空轉或DWT(Data Watchpoint and Trace Unit)的微秒級延時函數。

  方法一:基于DWT_CYCCNT寄存器的微秒延時(推薦,精度高)

  DWT_CYCCNT是ARM Cortex-M內核自帶的一個32位周期計數器,每過一個CPU時鐘周期就會加1,因此可以實現非常精確的微秒甚至納秒級延時。

  C

  // 在core_cmInstr.h中定義了DWT相關寄存器// 需要在主函數或初始化函數中啟用DWT// DWT_Delay_Init() 函數void DWT_Delay_Init(void){    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 使能DWT    DWT->LAR = 0xC5ACCE55;                          // 解鎖DWT    DWT->CYCCNT = 0;                                // 清零計數器    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;            // 使能計數器}// 微秒延時函數void DWT_Delay_us(uint32_t us){    uint32_t start_tick = DWT->CYCCNT;    uint32_t delay_ticks = us * (SystemCoreClock / 1000000); // 1us對應的時鐘周期數    while ((DWT->CYCCNT - start_tick) < delay_ticks);}

  注意: SystemCoreClock 變量通常由STM32CubeMX生成,表示CPU主頻。使用DWT延時需要在CubeMX中配置調試接口為Trace模式。

  方法二:基于__nop()的軟件延時(精度較差,不推薦用于精確時序)

  這種方法通過執行空指令來消耗CPU周期,但精度受編譯器優化、CPU緩存、中斷等因素影響。

  C

  // 偽代碼,實際延時需要根據CPU主頻和指令周期數進行調整// 不推薦用于DS18B20這類需要精確時序的場景void delay_us(uint32_t us){    for (volatile uint32_t i = 0; i < us * (SystemCoreClock / 1000000 / NOP_PER_US); i++)    {        __nop(); // 執行空操作    }}

  5.4 單總線基本操作實現

  基于前面定義的GPIO操作和延時函數,可以實現單總線協議中的復位、寫位和讀位。

  5.4.1 單總線初始化(復位與存在脈沖)

  C

  // DS18B20復位函數,返回1表示復位成功,0表示DS18B20不存在uint8_t DS18B20_Reset(void){    uint8_t presence = 0;    DS18B20_SetPinOutput(); // 設置為輸出模式    DS18B20_DQ_LOW();       // 拉低DQ線    DWT_Delay_us(480);      // 保持低電平至少480us (復位脈沖)    DS18B20_DQ_HIGH();      // 釋放DQ線 (上拉電阻拉高)    DWT_Delay_us(70);       // 等待DS18B20響應 (15-60us等待,這里取70us確保DS18B20開始響應)    DS18B20_SetPinInput();  // 設置為輸入模式,讀取存在脈沖    if (DS18B20_DQ_READ() == GPIO_PIN_RESET) // 檢測到低電平,表示DS18B20存在    {        presence = 1;    }    DWT_Delay_us(410);      // 等待存在脈沖結束 (DS18B20將DQ拉低60-240us,然后釋放,這里等待410us確保其完全釋放)    return presence;}

  5.4.2 寫入一個位(Write Bit)

  C

  // DS18B20寫入一個位void DS18B20_WriteBit(uint8_t bit){    DS18B20_SetPinOutput(); // 設置為輸出模式    if (bit == 1) // 寫入邏輯1    {        DS18B20_DQ_LOW();   // 拉低DQ線        DWT_Delay_us(5);    // 保持低電平1-15us (這里取5us)        DS18B20_DQ_HIGH();  // 釋放DQ線        DWT_Delay_us(65);   // 等待時隙結束 (至少60us,這里取65us)    }    else // 寫入邏輯0    {        DS18B20_DQ_LOW();   // 拉低DQ線        DWT_Delay_us(65);   // 保持低電平60-120us (這里取65us)        DS18B20_DQ_HIGH();  // 釋放DQ線        DWT_Delay_us(5);    // 等待時隙結束 (確保總線空閑)    }}

  5.4.3 讀取一個位(Read Bit)

  C

  // DS18B20讀取一個位,返回0或1uint8_t DS18B20_ReadBit(void){    uint8_t bit = 0;    DS18B20_SetPinOutput(); // 設置為輸出模式    DS18B20_DQ_LOW();       // 拉低DQ線    DWT_Delay_us(5);        // 保持低電平1-15us (這里取5us)    DS18B20_DQ_HIGH();      // 釋放DQ線 (準備采樣)    DS18B20_SetPinInput();  // 設置為輸入模式,讀取DQ線    DWT_Delay_us(10);       // 等待15us采樣窗口的中間點 (5us拉低 + 10us等待 = 15us)    if (DS18B20_DQ_READ() == GPIO_PIN_SET) // 采樣DQ線    {        bit = 1;    }    DWT_Delay_us(50);       // 等待讀取時隙結束 (總共60us,已經用了15us,再等50us)    return bit;}

  5.4.4 寫入一個字節(Write Byte)

  C

  // DS18B20寫入一個字節void DS18B20_WriteByte(uint8_t data){    for (int i = 0; i < 8; i++)    {        DS18B20_WriteBit(data & 0x01); // 從最低位開始寫入        data >>= 1;    }}

  5.4.5 讀取一個字節(Read Byte)

  C

  // DS18B20讀取一個字節uint8_t DS18B20_ReadByte(void){    uint8_t data = 0;    for (int i = 0; i < 8; i++)    {        data >>= 1; // 每次讀取一位,數據左移,低位進來        if (DS18B20_ReadBit())        {            data |= 0x80; // 將讀取到的位放到最高位(因為每次右移,最高位會被擠掉,所以需要反向操作)        }    }    return data;}

  修正: DS18B20_ReadByte 的邏輯,由于DS18B20通信是LSB優先,讀取時應該從最低位開始組裝字節。

  C

  // DS18B20讀取一個字節 (LSB優先)uint8_t DS18B20_ReadByte(void){    uint8_t data = 0;    for (int i = 0; i < 8; i++)    {        // 每次讀取一位,然后將該位放到字節的正確位置        if (DS18B20_ReadBit())        {            data |= (0x01 << i); // 將讀取到的位放到對應位置        }    }    return data;}

  5.5 DS18B20高級功能實現

  結合上述基本操作,可以實現DS18B20的溫度讀取等功能。

  5.5.1 獲取溫度函數

  C

  // 讀取DS18B20溫度函數float DS18B20_GetTemp(void){    uint8_t temp_H, temp_L;    int16_t raw_temp;    float temp_C;    if (DS18B20_Reset() == 0) // 復位失敗,DS18B20可能不存在或通信異常    {        return -200.0; // 返回一個特殊值表示錯誤    }    DS18B20_WriteByte(0xCC); // 跳過ROM命令 (適用于單DS18B20)    DS18B20_WriteByte(0x44); // 啟動溫度轉換    // 等待溫度轉換完成    // 可以通過讀取DQ線,等待其變為高電平(非寄生供電模式)    // 或者直接延時750ms(12位分辨率最長轉換時間)    // 推薦使用DWT_Delay_us(750000); 等待    // 更穩妥的方式是輪詢DQ線,直到它變為高電平    while(DS18B20_ReadBit() == 0) // 等待DQ線變為高電平 (轉換完成)    {        // 可以加入超時機制防止死循環        // HAL_Delay(1); // 每次等待1ms        // count++;        // if(count > 1000) break; // 超時    }        // 或者直接使用固定延時(簡單但可能不準確)    DWT_Delay_us(750000); // 12位分辨率最長轉換時間    if (DS18B20_Reset() == 0) // 再次復位,準備讀取數據    {        return -200.0;    }    DS18B20_WriteByte(0xCC); // 跳過ROM命令    DS18B20_WriteByte(0xBE); // 讀取暫存器命令    temp_L = DS18B20_ReadByte(); // 讀取溫度低字節    temp_H = DS18B20_ReadByte(); // 讀取溫度高字節    // 組合成16位原始溫度值    raw_temp = (temp_H << 8) | temp_L;    // 轉換為攝氏度(假設12位分辨率)    temp_C = (float)raw_temp * 0.0625f; // 12位分辨率,每位0.0625℃    // 這里可以進一步讀取CRC校驗字節,進行數據校驗,提高可靠性    // uint8_t crc = DS18B20_ReadByte();    return temp_C;}

  5.5.2 設置DS18B20分辨率(可選)

  DS18B20允許設置9-12位的分辨率。

  C

  // 設置DS18B20分辨率函數// resolution: 9, 10, 11, 12uint8_t DS18B20_SetResolution(uint8_t resolution){    uint8_t config_reg = 0; // 配置寄存器值    if (DS18B20_Reset() == 0)    {        return 0; // 失敗    }    // 讀取當前暫存器內容,保留TH和TL,只修改配置寄存器    DS18B20_WriteByte(0xCC); // SKIP ROM    DS18B20_WriteByte(0xBE); // READ SCRATCHPAD    // 丟棄前兩個字節的溫度數據 (這里我們不讀取,因為我們只關心配置寄存器)    DS18B20_ReadByte(); // temp_L    DS18B20_ReadByte(); // temp_H    uint8_t TH = DS18B20_ReadByte(); // TH    uint8_t TL = DS18B20_ReadByte(); // TL    config_reg = DS18B20_ReadByte(); // 配置寄存器    // 根據分辨率設置配置寄存器    switch (resolution)    {        case 9:            config_reg &= 0x7F; // R1=0, R0=0 -> 9位            break;        case 10:            config_reg &= 0x9F; // R1=0, R0=1 -> 10位            config_reg |= 0x20;            break;        case 11:            config_reg &= 0xBF; // R1=1, R0=0 -> 11位            config_reg |= 0x40;            break;        case 12:            config_reg |= 0x60; // R1=1, R0=1 -> 12位            break;        default:            return 0; // 無效分辨率    }    if (DS18B20_Reset() == 0)    {        return 0; // 失敗    }    DS18B20_WriteByte(0xCC); // SKIP ROM    DS18B20_WriteByte(0x4E); // WRITE SCRATCHPAD    DS18B20_WriteByte(TH);          // 寫入TH    DS18B20_WriteByte(TL);          // 寫入TL    DS18B20_WriteByte(config_reg);  // 寫入配置寄存器    if (DS18B20_Reset() == 0) // 復位,準備復制到EEPROM    {        return 0; // 失敗    }    DS18B20_WriteByte(0xCC); // SKIP ROM    DS18B20_WriteByte(0x48); // COPY SCRATCHPAD (保存到EEPROM)    HAL_Delay(10); // 等待復制完成,大約10ms    return 1; // 成功}

  5.6 CRC校驗(提高數據可靠性)

  DS18B20的暫存器讀取包含一個8位的CRC校驗碼。在讀取數據后計算CRC并與讀取到的CRC校驗碼進行比對,可以有效檢測通信過程中是否發生錯誤,提高數據可靠性。

  實現CRC校驗需要一個CRC8算法。DS18B20使用的是Dallas Semiconductor的CRC8算法。


  5.7 多點DS18B20驅動(ROM搜索)

  如果需要連接多個DS18B20,則需要實現ROM搜索算法。ROM搜索是一個迭代過程,通過發送0xF0 SEARCH ROM指令,DS18B20會返回其ROM碼中的沖突位,主機根據沖突位來遍歷所有可能的ROM碼,最終找到總線上所有DS18B20的唯一ID。這個算法相對復雜,需要維護一個搜索狀態變量和ROM地址數組。

  大致步驟:

  發送復位和存在脈沖。

  發送SEARCH ROM (0xF0) 命令。

  循環8次(每個字節)或64次(每個位): a.  讀取兩位(DS18B20返回的“0”和“1”的沖突信息)。 b.  根據沖突信息和上一次搜索路徑,決定發送“0”或“1”以解決沖突。 c.  記錄當前路徑的ROM碼。

  重復直到所有ROM碼被發現。由于篇幅限制,這里不提供完整的ROM搜索算法代碼,但這是實現多點DS18B20測量的基礎。

  6. 軟件流程圖與主程序設計

  一個典型的DS18B20溫度采集主程序流程如下:

  6.1 主程序流程圖

  代碼段

graph TD    A[系統初始化:時鐘、GPIO、DWT等] --> B{DS18B20復位成功?}    B -- 否 --> C[報錯:傳感器不存在或通信異常]    B -- 是 --> D[發送SKIP ROM命令 (0xCC)]    D --> E[發送CONVERT T命令 (0x44)]    E --> F[等待溫度轉換完成 (約750ms或輪詢DQ線)]    F --> G{DS18B20再次復位成功?}    G -- 否 --> C    G -- 是 --> H[發送SKIP ROM命令 (0xCC)]    H --> I[發送READ SCRATCHPAD命令 (0xBE)]    I --> J[讀取9字節暫存器數據 (包括溫度高低字節和CRC)]    J --> K[進行CRC校驗]    K -- 校驗失敗 --> C    K -- 校驗成功 --> L[解析溫度數據]    L --> M[將溫度數據通過串口/LCD等方式顯示/發送]    M --> N[延時一段時間 (例如1秒) ]    N --> D

  6.2 主程序代碼骨架

  

#include "main.h"

#include "stm32f1xx_hal.h" // 根據實際MCU系列選擇

#include "ds18b20.h"       // 包含DS18B20驅動頭文件

#include <stdio.h>         // 用于printf輸出


// 定義串口句柄,用于調試輸出

extern UART_HandleTypeDef huart1; // 假設使用UART1


void SystemClock_Config(void); // 系統時鐘配置函數

static void MX_GPIO_Init(void); // GPIO初始化函數

static void MX_USART1_UART_Init(void); // 串口初始化函數


int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_USART1_UART_Init();

    DWT_Delay_Init(); // 初始化DWT用于微秒延時


    float temperature = 0.0f;

    char temp_str[30];


    // 可選:設置DS18B20分辨率為12位

    // DS18B20_SetResolution(12); // 如果需要設置,請在循環外執行一次


    while (1)

    {

        temperature = DS18B20_GetTemp_WithCRC(); // 獲取溫度 (帶CRC校驗)


        if (temperature > -100.0f) // 假設-200.0或-201.0是錯誤碼

        {

            sprintf(temp_str, "Temperature: %.2f C ", temperature);

        }

        else if (temperature == -200.0f)

        {

            sprintf(temp_str, "DS18B20 Not Found or Reset Failed! ");

        }

        else if (temperature == -201.0f)

        {

            sprintf(temp_str, "DS18B20 CRC Error! Data Corrupted! ");

        }

        

        HAL_UART_Transmit(&huart1, (uint8_t*)temp_str, strlen(temp_str), 100);


        HAL_Delay(1000); // 1秒更新一次

    }

}


// 示例:SystemClock_Config, MX_GPIO_Init, MX_USART1_UART_Init 由STM32CubeMX生成

// 

  7. 調試與注意事項

  在DS18B20驅動設計與實現過程中,可能會遇到一些問題。理解并解決這些問題是確保系統穩定運行的關鍵。

  7.1 常見問題與解決方案

  DS18B20復位失敗(無存在脈沖):

  檢查硬件連接: 確保VCC、GND、DQ線連接正確,特別是4.7kΩ上拉電阻是否正確連接且阻值合適。

  檢查供電: 確保DS18B20供電電壓在3.0V-5.5V之間,且供電穩定。嘗試使用獨立供電而不是寄生電源模式。

  檢查GPIO配置: 確保STM32的GPIO設置為正確的輸出/輸入模式,并且在釋放總線時能正確變為輸入或高電平輸出。

  檢查延時函數: DS18B20時序對延時精度要求很高。確保微秒延時函數(DWT_Delay_us)工作正常且準確。示波器是調試時序的利器。

  DS18B20損壞: 少數情況下傳感器本身可能損壞。嘗試更換一個DS18B20。讀取溫度數據異常(始終為85℃或0℃):

  檢查READ SCRATCHPAD (0xBE) 命令是否正確發送。

  檢查DS18B20_ReadByte()函數,確保數據位能正確地被STM32讀取。使用示波器觀察DQ線的數據波形。

  檢查溫度數據解析算法,特別是負數的補碼轉換和浮點數轉換。檢查CONVERT T (0x44) 命令是否正確發送。

  確保在發送完CONVERT T命令后有足夠的等待時間(12位分辨率需要750ms)讓DS18B20完成轉換。85℃: DS18B20在上電或復位后的默認溫度值是85℃。如果一直讀到這個值,說明溫度轉換沒有成功啟動或者數據讀取有問題。

  0℃: 可能是在讀取數據時,接收到的都是0,或者數據解析錯誤。多點測溫時無法識別所有傳感器:

  ROM搜索算法問題: ROM搜索算法比較復雜,任何一個細節錯誤都可能導致部分或全部傳感器無法被發現。仔細對照DS18B20數據手冊中的SEARCH ROM流程。

  總線負載過大: 當連接的DS18B20數量過多或DQ線過長時,總線的容性負載會增加,導致信號上升沿變慢。此時可能需要減小上拉電阻的阻值(例如2.2kΩ),或者增加有源上拉電路(如使用一個MOSFET)。CRC校驗失敗:

  通信不穩定: 檢查電源穩定性,確保沒有大的噪聲干擾。

  時序問題: 再次檢查所有時序延時是否嚴格符合DS18B20數據手冊要求。任何微小的時序偏差都可能導致數據傳輸錯誤。

  CRC算法實現錯誤: 仔細核對CRC8算法是否嚴格按照Dallas Semiconductor的規范實現。7.2 調試工具

  示波器: 這是調試單總線通信必不可少的工具。通過示波器可以直觀地觀察DQ線的波形,判斷復位脈沖、存在脈沖、寫入時隙和讀取時隙的時序是否符合要求,以及數據位的電平是否正確。特別注意信號的上升沿和下降沿。

  邏輯分析儀: 如果沒有示波器,或者需要同時觀察多路信號,邏輯分析儀也是一個很好的選擇。它可以捕捉數字信號,并解析出協議內容,方便分析通信數據。

  串口調試助手: 用于接收STM32發送的溫度數據和調試信息,驗證程序邏輯是否正確。

  STM32在線調試器(ST-Link/J-Link): 用于程序的燒錄、單步調試、變量觀察,是定位軟件邏輯錯誤的必備工具。7.3 功耗優化(可選)

  在某些對功耗有嚴格要求的應用中,可以考慮以下優化:

  降低DS18B20的采樣頻率: DS18B20在進行溫度轉換時功耗最高。減少溫度讀取的頻率可以顯著降低系統平均功耗。

  STM32進入低功耗模式: 在等待DS18B20轉換完成的長時間延時期間,可以將STM32進入停止模式(Stop Mode)或待機模式(Standby Mode),然后通過定時器或外部中斷喚醒。

  控制DS18B20的供電: 在極端低功耗場景下,可以通過一個GPIO控制MOSFET來切換DS18B20的VCC供電,只在需要測量時上電。

  8. 總結與展望

  本設計方案詳細闡述了基于STM32微控制器驅動DS18B20溫度傳感器的全過程,從核心元器件選型、硬件連接、單總線通信協議解析到軟件驅動的詳細實現,并提供了關鍵代碼片段。通過精確的GPIO控制、嚴格的時序延時以及完善的CRC校驗,可以構建一個穩定、高精度的溫度采集系統。

  DS18B20因其獨特的單總線特性和優秀的性能,在眾多應用中仍占有一席之地。未來,在此基礎上可以進一步擴展,例如:

  多點溫度網絡: 實現復雜的ROM搜索算法,構建多達上百個DS18B20的溫度傳感器網絡。

  數據存儲與顯示: 將溫度數據存儲到EEPROM或SD卡中,并通過LCD、OLED顯示屏進行實時顯示。

  無線傳輸: 集成Wi-Fi(ESP8266/ESP32)、藍牙或LoRa模塊,將溫度數據上傳至云平臺或遠程監控。

  溫度控制: 根據采集到的溫度數據,通過PID算法或其他控制策略,控制風扇、加熱器等執行機構,實現智能溫度控制。

  更高級的軟件架構: 引入實時操作系統(RTOS),將DS18B20驅動封裝為獨立的任務,提高系統的并發性和可維護性。掌握DS18B20的驅動不僅是溫度采集的基礎,更是深入理解單總線通信協議和嵌入式系統時序控制的絕佳實踐。希望本設計方案能為您的開發工作提供全面而有價值的參考。

責任編輯:David

【免責聲明】

1、本文內容、數據、圖表等來源于網絡引用或其他公開資料,版權歸屬原作者、原發表出處。若版權所有方對本文的引用持有異議,請聯系拍明芯城(marketing@iczoom.com),本方將及時處理。

2、本文的引用僅供讀者交流學習使用,不涉及商業目的。

3、本文內容僅代表作者觀點,拍明芯城不對內容的準確性、可靠性或完整性提供明示或暗示的保證。讀者閱讀本文后做出的決定或行為,是基于自主意愿和獨立判斷做出的,請讀者明確相關結果。

4、如需轉載本方擁有版權的文章,請聯系拍明芯城(marketing@iczoom.com)注明“轉載原因”。未經允許私自轉載拍明芯城將保留追究其法律責任的權利。

拍明芯城擁有對此聲明的最終解釋權。

相關資訊

拍明芯城微信圖標

各大手機應用商城搜索“拍明芯城”

下載客戶端,隨時隨地買賣元器件!

拍明芯城公眾號
拍明芯城抖音
拍明芯城b站
拍明芯城頭條
拍明芯城微博
拍明芯城視頻號
拍明
廣告
恒捷廣告
廣告
深亞廣告
廣告
原廠直供
廣告