基于STM32單片機(jī)對(duì)DS18B20溫度傳感器的驅(qū)動(dòng)設(shè)計(jì)方案


原標(biāo)題:基于STM32單片機(jī)對(duì)DS18B20溫度傳感器的驅(qū)動(dòng)設(shè)計(jì)方案
基于STM32單片機(jī)對(duì)DS18B20溫度傳感器的驅(qū)動(dòng)設(shè)計(jì)方案
在當(dāng)今物聯(lián)網(wǎng)與智能控制系統(tǒng)飛速發(fā)展的時(shí)代,溫度數(shù)據(jù)采集作為環(huán)境感知的重要組成部分,其精度與穩(wěn)定性直接影響到整個(gè)系統(tǒng)的性能。DS18B20作為一款經(jīng)典的數(shù)字溫度傳感器,以其獨(dú)特的單總線(One-Wire)通信方式、寬廣的測(cè)量范圍、高精度以及優(yōu)秀的環(huán)境適應(yīng)性,在工業(yè)控制、消費(fèi)電子、醫(yī)療設(shè)備、智能家居等諸多領(lǐng)域得到了廣泛應(yīng)用。本設(shè)計(jì)方案將深入探討如何基于功能強(qiáng)大的STM32系列微控制器,實(shí)現(xiàn)對(duì)DS18B20溫度傳感器的穩(wěn)定、高效驅(qū)動(dòng),涵蓋硬件選型、軟件設(shè)計(jì)、通信協(xié)議解析、數(shù)據(jù)處理以及常見(jiàn)問(wèn)題解決方案等多個(gè)方面。
1. 系統(tǒng)概述與設(shè)計(jì)目標(biāo)
本系統(tǒng)旨在構(gòu)建一個(gè)基于STM32微控制器驅(qū)動(dòng)DS18B20溫度傳感器的高精度溫度采集模塊。其核心目標(biāo)包括:
高精度溫度采集: 利用DS18B20傳感器本身的高精度(可配置9-12位分辨率)確保測(cè)量結(jié)果的準(zhǔn)確性。
穩(wěn)定可靠的通信: 實(shí)現(xiàn)STM32與DS18B20之間基于單總線協(xié)議的穩(wěn)定數(shù)據(jù)傳輸,抵抗干擾。
靈活的硬件接口: 設(shè)計(jì)合理的硬件連接方案,便于集成與擴(kuò)展。
高效的軟件驅(qū)動(dòng): 編寫模塊化、可移植的軟件代碼,實(shí)現(xiàn)DS18B20的初始化、溫度讀取、配置等功能。
友好的數(shù)據(jù)輸出: 將采集到的溫度數(shù)據(jù)通過(guò)串口或其他接口輸出,便于上位機(jī)顯示或進(jìn)一步處理。
低功耗設(shè)計(jì)(可選): 考慮在特定應(yīng)用場(chǎng)景下,如何通過(guò)軟件和硬件協(xié)同實(shí)現(xiàn)低功耗運(yùn)行。
2. 核心元器件選型與功能分析
成功的嵌入式系統(tǒng)設(shè)計(jì)離不開(kāi)對(duì)核心元器件的精確選擇與深刻理解。本章節(jié)將詳細(xì)闡述STM32微控制器與DS18B20溫度傳感器的選型依據(jù)、功能特性以及其在整個(gè)系統(tǒng)中的關(guān)鍵作用,并介紹其他必要的輔助元器件。
2.1 微控制器單元(MCU):STM32系列
2.1.1 選型推薦
對(duì)于DS18B20的驅(qū)動(dòng),由于其單總線協(xié)議對(duì)時(shí)序的嚴(yán)格要求,以及未來(lái)可能的功能擴(kuò)展(如LCD顯示、網(wǎng)絡(luò)通信等),推薦選用STM32F103C8T6或STM32F401RCT6。
STM32F103C8T6: 這是一款基于ARM Cortex-M3內(nèi)核的微控制器,屬于STM32F1系列的主流產(chǎn)品。
CPU內(nèi)核(Cortex-M3): 提供強(qiáng)大的處理能力,可以高效執(zhí)行DS18B20的單總線時(shí)序操作和數(shù)據(jù)解析算法。
GPIO(通用輸入輸出): 用于與DS18B20的DQ線直接連接,并通過(guò)軟件控制其輸出高低電平,或配置為輸入模式讀取數(shù)據(jù)。F103C8T6的GPIO可以配置為推挽輸出、開(kāi)漏輸出、浮空輸入、上拉/下拉輸入等多種模式,這對(duì)于單總線協(xié)議中DQ線的控制至關(guān)重要。
定時(shí)器(Timers): DS18B20的單總線協(xié)議對(duì)時(shí)序有嚴(yán)格要求,例如復(fù)位脈沖的持續(xù)時(shí)間、數(shù)據(jù)位的采樣點(diǎn)等。STM32的定時(shí)器可以提供精確的微秒級(jí)延時(shí),確保通信的準(zhǔn)確性。
NVIC(嵌套向量中斷控制器): 可以管理外部中斷,雖然DS18B20通常不需要中斷來(lái)驅(qū)動(dòng),但在多任務(wù)系統(tǒng)中,或需要對(duì)通信錯(cuò)誤進(jìn)行實(shí)時(shí)響應(yīng)時(shí),中斷功能會(huì)非常有用。
Flash存儲(chǔ)器和SRAM: 用于存儲(chǔ)程序代碼和運(yùn)行時(shí)數(shù)據(jù),包括DS18B20的驅(qū)動(dòng)代碼、溫度數(shù)據(jù)、以及其他應(yīng)用邏輯。
高性價(jià)比: F103系列是STM32家族中性價(jià)比較高的入門級(jí)芯片,非常適合學(xué)習(xí)和中小型項(xiàng)目開(kāi)發(fā)。它的成本效益使其成為許多原型設(shè)計(jì)和量產(chǎn)應(yīng)用的首選。
豐富的資源: 擁有72MHz的主頻,64KB的Flash存儲(chǔ)器和20KB的SRAM,以及多個(gè)通用GPIO、定時(shí)器、USART、SPI、I2C等外設(shè)。這些資源足以滿足DS18B20的時(shí)序要求,并為未來(lái)擴(kuò)展其他傳感器、通信模塊(如藍(lán)牙、Wi-Fi)或顯示設(shè)備預(yù)留了足夠的硬件基礎(chǔ)。
成熟的生態(tài)系統(tǒng): ST公司為STM32F1系列提供了非常完善的開(kāi)發(fā)工具鏈(如Keil MDK, STM32CubeIDE)和豐富的例程、庫(kù)函數(shù)(如HAL庫(kù)、LL庫(kù)),社區(qū)支持廣泛,方便開(kāi)發(fā)者快速上手和調(diào)試。
管腳兼容性: TSSOP48封裝,引腳數(shù)量適中,便于PCB設(shè)計(jì)和手工焊接。
選擇理由:
功能:
STM32F401RCT6: 這是一款基于ARM Cortex-M4內(nèi)核的微控制器,屬于STM32F4系列的入門級(jí)產(chǎn)品。
FPU(浮點(diǎn)單元): 大幅提升浮點(diǎn)運(yùn)算速度,對(duì)于需要精確溫度計(jì)算和顯示的應(yīng)用非常有利。
更高效的DMA(直接存儲(chǔ)器訪問(wèn)): 可以實(shí)現(xiàn)數(shù)據(jù)在內(nèi)存和外設(shè)之間的高速傳輸,減輕CPU負(fù)擔(dān),提高系統(tǒng)整體效率。雖然DS18B20的通信量不大,但DMA在多任務(wù)系統(tǒng)中依然能發(fā)揮作用。
更寬的工作溫度范圍和更高可靠性: 部分F4系列芯片設(shè)計(jì)用于更嚴(yán)苛的工業(yè)環(huán)境,這可能是一個(gè)額外優(yōu)勢(shì)。
更高性能: F401系列擁有84MHz的主頻,配備浮點(diǎn)單元(FPU),使其在進(jìn)行復(fù)雜數(shù)學(xué)運(yùn)算(如溫度數(shù)據(jù)的浮點(diǎn)轉(zhuǎn)換、濾波算法等)時(shí)效率更高。如果未來(lái)的應(yīng)用需要更復(fù)雜的信號(hào)處理或圖形顯示,F(xiàn)401會(huì)提供更好的性能儲(chǔ)備。
更大的存儲(chǔ)空間: 256KB的Flash和64KB的SRAM,為更大型的應(yīng)用程序和數(shù)據(jù)存儲(chǔ)提供了充足的空間。
更多高級(jí)外設(shè): 比如更多的定時(shí)器、DMA控制器、以及更快的ADC等。雖然DS18B20本身不直接使用ADC,但如果系統(tǒng)中還有其他模擬傳感器,這些高級(jí)外設(shè)會(huì)很有用。
適用于更復(fù)雜的系統(tǒng): 如果考慮到未來(lái)項(xiàng)目可能擴(kuò)展到更復(fù)雜的系統(tǒng),例如需要運(yùn)行RTOS(實(shí)時(shí)操作系統(tǒng))、進(jìn)行大量數(shù)據(jù)處理或與更高速外設(shè)通信,F(xiàn)401提供了更強(qiáng)的處理能力和更豐富的外設(shè)接口。
選擇理由:
功能: 除了F103的所有功能外,F(xiàn)401還具備:總結(jié): 對(duì)于初學(xué)者和大多數(shù)基本溫度采集應(yīng)用,STM32F103C8T6是更具性價(jià)比和易用性的選擇。如果項(xiàng)目對(duì)性能有更高要求,或者有未來(lái)擴(kuò)展至更復(fù)雜系統(tǒng)的考慮,STM32F401RCT6將是更好的選擇。
2.2 溫度傳感器:DS18B20
2.2.1 選型推薦
DS18B20是Maxim Integrated公司(現(xiàn)已被Analog Devices收購(gòu))生產(chǎn)的一款單總線數(shù)字溫度傳感器。
選擇理由:
單總線接口: 這是DS18B20最顯著的特點(diǎn),只需一根數(shù)據(jù)線(DQ)即可與微控制器進(jìn)行通信,大大簡(jiǎn)化了硬件連接。DQ線同時(shí)用于供電(寄生電源模式)和數(shù)據(jù)傳輸,減少了布線復(fù)雜性。
寬測(cè)量范圍: -55°C 至 +125°C,覆蓋了大多數(shù)日常及工業(yè)應(yīng)用場(chǎng)景。
高精度: 在-10°C至+85°C范圍內(nèi),精度可達(dá)±0.5°C。用戶可配置9位、10位、11位或12位的測(cè)量分辨率,對(duì)應(yīng)的轉(zhuǎn)換時(shí)間分別為93.75ms、187.5ms、375ms、750ms,精度越高,轉(zhuǎn)換時(shí)間越長(zhǎng)。
數(shù)字輸出: 直接輸出數(shù)字溫度值,避免了傳統(tǒng)模擬溫度傳感器(如熱敏電阻、PT100)需要進(jìn)行AD轉(zhuǎn)換的環(huán)節(jié),簡(jiǎn)化了硬件設(shè)計(jì),提高了抗干擾能力,且無(wú)需校準(zhǔn)。
獨(dú)特ID: 每個(gè)DS18B20都有一個(gè)獨(dú)一無(wú)二的64位ROM序列碼,允許多個(gè)DS18B20并聯(lián)在同一根單總線上,并通過(guò)ROM匹配指令進(jìn)行尋址,實(shí)現(xiàn)多點(diǎn)溫度測(cè)量。
寄生電源模式: 在某些應(yīng)用中,可以通過(guò)數(shù)據(jù)線(DQ)直接供電,無(wú)需額外電源線,進(jìn)一步簡(jiǎn)化了布線。但通常建議使用外部電源供電,以保證通信的穩(wěn)定性和轉(zhuǎn)換的準(zhǔn)確性,尤其是在長(zhǎng)距離傳輸或多點(diǎn)測(cè)量時(shí)。
封裝多樣性: 提供TO-92、SOP8、防水探頭(如不銹鋼封裝)等多種封裝形式,滿足不同應(yīng)用環(huán)境的需求。TO-92封裝適合板載或短距離測(cè)溫,防水探頭則適合液體或潮濕環(huán)境。
功能:
溫度測(cè)量: 將測(cè)得的溫度值轉(zhuǎn)換為數(shù)字信號(hào),存儲(chǔ)在其內(nèi)部的2字節(jié)溫度寄存器中。
用戶可編程分辨率: 用戶可以通過(guò)寫入配置寄存器來(lái)設(shè)置溫度轉(zhuǎn)換的分辨率。
報(bào)警功能: 具有可編程的高低溫度報(bào)警觸發(fā)點(diǎn)(TH和TL寄存器),當(dāng)測(cè)得的溫度超出設(shè)定范圍時(shí),DS18B20會(huì)設(shè)置一個(gè)報(bào)警標(biāo)志,并通過(guò)報(bào)警搜索命令被識(shí)別出來(lái)。
暫存器(Scratchpad): 包含溫度寄存器、高/低報(bào)警觸發(fā)寄存器(TH/TL)、配置寄存器等。
EEPROM: 用于存儲(chǔ)配置數(shù)據(jù)(TH/TL和分辨率設(shè)置),即使斷電也能保存。
64位ROM序列碼: 唯一的硬件地址,用于區(qū)分總線上的多個(gè)DS18B20。2.3 輔助元器件
2.3.1 上拉電阻
選型推薦: 4.7kΩ ~ 10kΩ 精密電阻。 通常選擇4.7kΩ。
作用: DS18B20的單總線協(xié)議是一個(gè)開(kāi)漏(Open-Drain)總線結(jié)構(gòu)。這意味著DS18B20或微控制器只能將DQ線拉低(輸出邏輯0),而不能主動(dòng)拉高(輸出邏輯1)。當(dāng)DQ線空閑時(shí),或者需要傳輸邏輯1時(shí),必須依靠外部的上拉電阻將總線拉高到VCC電平。
選擇理由:
協(xié)議要求: DS18B20數(shù)據(jù)手冊(cè)明確指出需要一個(gè)上拉電阻。
保證邏輯高電平: 沒(méi)有上拉電阻,DQ線將無(wú)法達(dá)到VCC電平,導(dǎo)致通信錯(cuò)誤。
平衡上升/下降時(shí)間: 電阻值過(guò)大會(huì)導(dǎo)致上升時(shí)間過(guò)長(zhǎng),影響通信速度和可靠性;電阻值過(guò)小會(huì)增加功耗,并可能對(duì)DS18B20的開(kāi)漏輸出電流能力造成過(guò)大負(fù)擔(dān)。4.7kΩ是經(jīng)過(guò)驗(yàn)證的典型值,能在確??煽客ㄐ诺耐瑫r(shí)保持較低功耗。對(duì)于長(zhǎng)距離傳輸或多點(diǎn)連接,可能需要適當(dāng)減小電阻值或增加有源上拉電路。
功能:
當(dāng)總線空閑時(shí),通過(guò)電阻將DQ線拉高至邏輯高電平。
當(dāng)DS18B20或STM32釋放總線(停止拉低)時(shí),迅速將DQ線拉高。
為DS18B20提供寄生電源模式下的充電電流。2.3.2 濾波電容
選型推薦: 100nF(0.1μF)陶瓷電容,并聯(lián)在DS18B20的VCC和GND之間。對(duì)于更長(zhǎng)的引線或噪聲較大的環(huán)境,可以在電源入口增加一個(gè)10μF或47μF的電解電容。
作用: 濾波電容用于濾除電源線上的高頻噪聲,提供穩(wěn)定的電源,以及在DS18B20進(jìn)行內(nèi)部操作(如溫度轉(zhuǎn)換)時(shí)提供瞬時(shí)電流。
選擇理由:
去耦: 微控制器和傳感器在工作時(shí)會(huì)產(chǎn)生瞬態(tài)電流需求,導(dǎo)致電源線上的電壓波動(dòng)。100nF陶瓷電容具有低ESR(等效串聯(lián)電阻)和良好的高頻特性,能有效地進(jìn)行高頻去耦,保證VCC的穩(wěn)定性。
抗干擾: 減少外部電磁干擾(EMI)對(duì)DS18B20電源的沖擊,提高測(cè)量的準(zhǔn)確性和通信的穩(wěn)定性。
寄生電源模式下的儲(chǔ)能: 在寄生電源模式下,DS18B20在溫度轉(zhuǎn)換期間會(huì)消耗較大的電流。這個(gè)電容可以作為能量?jī)?chǔ)存器,在DQ線被拉低時(shí),為DS18B20提供所需的瞬時(shí)能量。
功能:
旁路高頻噪聲。
提供穩(wěn)定的電源,確保DS18B20內(nèi)部電路的正常工作。
在電流高峰時(shí)為DS18B20提供瞬時(shí)能量,防止電源跌落。2.3.3 排針/排母
選型推薦: 2.54mm間距的直插或彎角排針/排母。
作用: 提供便捷的硬件連接接口,便于DS18B20模塊與STM32開(kāi)發(fā)板之間的插拔連接,也方便進(jìn)行調(diào)試和測(cè)試。
選擇理由:
標(biāo)準(zhǔn)化: 2.54mm(0.1英寸)是電子元器件的常用間距,兼容性好。
易于連接: 方便使用杜邦線進(jìn)行連接,或者直接插在面包板、洞洞板上進(jìn)行原型開(kāi)發(fā)。
靈活性: 方便更換DS18B20傳感器或?qū)⒛K集成到更大的系統(tǒng)中。
功能:
提供機(jī)械連接和電氣連接。
方便調(diào)試和維護(hù)。
3. 硬件連接方案
DS18B20與STM32的硬件連接相對(duì)簡(jiǎn)單,主要涉及供電、地線和數(shù)據(jù)線(DQ)。
3.1 基本連接
VCC (電源): 連接到STM32開(kāi)發(fā)板的3.3V或5V電源(DS18B20支持3.0V至5.5V供電)。為確保穩(wěn)定,通常建議連接到5V,因?yàn)镈S18B20手冊(cè)規(guī)定在溫度轉(zhuǎn)換時(shí)需要較大的瞬間電流,5V電源可以提供更穩(wěn)定的供電能力。
GND (地線): 連接到STM32開(kāi)發(fā)板的GND。
DQ (數(shù)據(jù)線): 連接到STM32的任意一個(gè)通用GPIO口。例如,可以連接到PA1。
上拉電阻: 一個(gè)4.7kΩ的上拉電阻(Rpu)必須連接在DQ線和VCC之間。這是單總線協(xié)議的強(qiáng)制要求。
濾波電容: 一個(gè)100nF(0.1μF)的陶瓷電容并聯(lián)在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
說(shuō)明:
圖中DS18B20的VCC引腳接STM32的電源,GND接STM32的地。
DS18B20的DQ引腳通過(guò)一個(gè)4.7kΩ上拉電阻接到VCC,然后直接連接到STM32的某個(gè)GPIO引腳(例如PA1)。
100nF的濾波電容并聯(lián)在DS18B20的VCC和GND引腳之間。3.3 多點(diǎn)連接
DS18B20的單總線特性允許在同一根DQ線上連接多個(gè)傳感器。此時(shí),每個(gè)DS18B20仍然需要自己的上拉電阻和濾波電容(雖然通常情況下,一個(gè)總線上的多個(gè)DS18B20可以共用一個(gè)主上拉電阻,但為每個(gè)傳感器提供局部濾波電容仍然是好的實(shí)踐)。STM32通過(guò)發(fā)送ROM指令(如跳過(guò)ROM、匹配ROM、搜索ROM)來(lái)與特定的DS18B20通信。
4. 單總線(One-Wire)通信協(xié)議解析
DS18B20的驅(qū)動(dòng)核心在于理解并精確實(shí)現(xiàn)其單總線通信協(xié)議。該協(xié)議定義了一系列嚴(yán)格的時(shí)序要求,包括初始化、ROM指令和功能指令。所有通信都以最低有效位(LSB)優(yōu)先傳輸。
4.1 單總線時(shí)序基礎(chǔ)
單總線協(xié)議是主從協(xié)議,STM32作為主設(shè)備,DS18B20作為從設(shè)備。所有通信都由主設(shè)備發(fā)起。
4.1.1 協(xié)議信號(hào)概述
復(fù)位(Reset)和存在(Presence)脈沖: 這是每次通信開(kāi)始的第一個(gè)時(shí)序。
主設(shè)備將DQ線拉低至少480微秒(us),然后釋放(上拉電阻將其拉高)。
DS18B20檢測(cè)到總線被拉低后,會(huì)等待15-60us,然后將DQ線拉低60-240us作為存在脈沖,表示其已準(zhǔn)備好通信。
主設(shè)備在DS18B20釋放總線后(即DQ線再次被上拉電阻拉高)15-60us內(nèi)讀取DQ線的狀態(tài)。如果檢測(cè)到低電平,則表示存在DS18B20。
寫入時(shí)隙(Write Time Slot): 主設(shè)備向從設(shè)備發(fā)送數(shù)據(jù)。每個(gè)寫入時(shí)隙至少需要60us,并在120us內(nèi)完成。
寫入邏輯1: 主設(shè)備將DQ線拉低1-15us,然后釋放總線(拉高)。
寫入邏輯0: 主設(shè)備將DQ線拉低60-120us,然后釋放總線(拉高)。
在每次寫入時(shí)隙結(jié)束后,總線必須保持空閑至少1us。
讀取時(shí)隙(Read Time Slot): 主設(shè)備從從設(shè)備讀取數(shù)據(jù)。每個(gè)讀取時(shí)隙至少需要60us,并在120us內(nèi)完成。
主設(shè)備將DQ線拉低1-15us,然后立即釋放總線(拉高)。
主設(shè)備在拉低總線后15us內(nèi)采樣DQ線的狀態(tài)。如果從設(shè)備要發(fā)送0,則DQ線將保持低電平;如果發(fā)送1,則DQ線將保持高電平。
在每次讀取時(shí)隙結(jié)束后,總線必須保持空閑至少1us。4.2 ROM指令
ROM指令用于選擇或識(shí)別總線上的DS18B20設(shè)備。
0x33 - READ ROM: (讀取ROM碼) 主機(jī)發(fā)出此命令后,DS18B20將自己的64位ROM碼傳輸給主機(jī)。此命令只適用于總線上只有一個(gè)DS18B20的情況。
0xCC - SKIP ROM: (跳過(guò)ROM碼) 主機(jī)發(fā)出此命令后,DS18B20直接執(zhí)行后續(xù)的功能命令,不再等待ROM碼匹配。適用于總線上只有一個(gè)DS18B20,或者你確定要與所有DS18B20通信。
0x55 - MATCH ROM: (匹配ROM碼) 主機(jī)發(fā)出此命令后,需要接著發(fā)送一個(gè)64位的ROM碼??偩€上只有與該ROM碼匹配的DS18B20才會(huì)響應(yīng)后續(xù)的功能命令。用于多點(diǎn)測(cè)溫時(shí)精確選擇目標(biāo)DS18B20。
0xF0 - SEARCH ROM: (搜索ROM碼) 用于在多點(diǎn)測(cè)溫系統(tǒng)中查找所有DS18B20的64位ROM碼。這是一個(gè)復(fù)雜的過(guò)程,通常通過(guò)專門的算法實(shí)現(xiàn)。4.3 功能指令
功能指令用于控制DS18B20進(jìn)行溫度轉(zhuǎn)換、讀寫暫存器等操作。在發(fā)送功能指令前,必須先發(fā)送ROM指令(通常是SKIP ROM或MATCH ROM)。
0x44 - CONVERT T: (啟動(dòng)溫度轉(zhuǎn)換) DS18B20開(kāi)始進(jìn)行溫度轉(zhuǎn)換。轉(zhuǎn)換過(guò)程需要一定時(shí)間(取決于分辨率設(shè)置,最長(zhǎng)750ms)。在轉(zhuǎn)換期間,DQ線會(huì)保持低電平,轉(zhuǎn)換完成后會(huì)拉高。
0xBE - READ SCRATCHPAD: (讀取暫存器) 主機(jī)發(fā)出此命令后,DS18B20將其內(nèi)部9字節(jié)的暫存器內(nèi)容傳輸給主機(jī)。暫存器內(nèi)容包括:
字節(jié)0和字節(jié)1:溫度數(shù)據(jù)(LSB和MSB)。
字節(jié)2和字節(jié)3:TH(高溫報(bào)警閾值)和TL(低溫報(bào)警閾值)。
字節(jié)4:配置寄存器(分辨率設(shè)置)。
字節(jié)5、字節(jié)6、字節(jié)7:保留。
字節(jié)8:CRC校驗(yàn)碼(對(duì)前8個(gè)字節(jié)的CRC校驗(yàn))。
0x4E - WRITE SCRATCHPAD: (寫入暫存器) 主機(jī)發(fā)出此命令后,需要接著發(fā)送TH、TL和配置寄存器三個(gè)字節(jié)的數(shù)據(jù)。
0x48 - COPY SCRATCHPAD: (復(fù)制暫存器) 將暫存器中的TH、TL和配置寄存器數(shù)據(jù)復(fù)制到EEPROM中,斷電后仍然保存。
0xB8 - RECALL E2: (召回EEPROM數(shù)據(jù)) 將EEPROM中存儲(chǔ)的TH、TL和配置寄存器數(shù)據(jù)召回到暫存器中。通常在DS18B20上電后自動(dòng)執(zhí)行,但也可以手動(dòng)觸發(fā)。
0xEC - READ POWER SUPPLY: (讀取電源供電模式) DS18B20會(huì)返回其當(dāng)前的供電模式(外部供電或寄生供電)。4.4 溫度數(shù)據(jù)解析
DS18B20輸出的溫度數(shù)據(jù)是2字節(jié)(16位)補(bǔ)碼形式。其中,低字節(jié)包含溫度的低8位,高字節(jié)包含溫度的高8位。
數(shù)據(jù)格式:
S Sign (符號(hào)位,1為負(fù),0為正)
MSB (最高有效位)
LSB (最低有效位)例如,當(dāng)分辨率為12位時(shí),數(shù)據(jù)格式如下:
Bit 15Bit 14Bit 13Bit 12Bit 11Bit 10Bit 9Bit 8Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
SSSSSSSST7T6T5T4T3T2T1T0
導(dǎo)出到 Google 表格
其中,Bit 0 到 Bit 7 是溫度的低8位,Bit 8 到 Bit 10 是溫度的高3位(12位分辨率),Bit 11 到 Bit 15 是符號(hào)位。
轉(zhuǎn)換為攝氏度:讀取到16位數(shù)據(jù)后,需要進(jìn)行符號(hào)擴(kuò)展和除以對(duì)應(yīng)的權(quán)重。
對(duì)于正溫度:直接將16位數(shù)據(jù)乘以對(duì)應(yīng)分辨率的權(quán)重。
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)
對(duì)于負(fù)溫度:先取反加1(補(bǔ)碼轉(zhuǎn)換),然后乘以權(quán)重,結(jié)果為負(fù)值。示例(12位分辨率):假設(shè)讀取到數(shù)據(jù)為0x0191 (二進(jìn)制 0000 0001 1001 0001) 這是正數(shù),直接換算:0x0191=401 (十進(jìn)制) 溫度 = 401times0.0625=25.0625 (circtextC)
假設(shè)讀取到數(shù)據(jù)為0xFE6F (二進(jìn)制 1111 1110 0110 1111) 這是一個(gè)負(fù)數(shù)(最高位為1)。 取反:0000 0001 1001 0000加1:0000 0001 1001 0001 (十進(jìn)制 401) 溫度 = ?401times0.0625=?25.0625 (circtextC)
5. 軟件驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
軟件驅(qū)動(dòng)是實(shí)現(xiàn)DS18B20功能的關(guān)鍵。本節(jié)將詳細(xì)介紹基于STM32HAL庫(kù)的軟件驅(qū)動(dòng)設(shè)計(jì),包括GPIO配置、延時(shí)函數(shù)、單總線基本操作(復(fù)位、讀寫位/字節(jié))以及DS18B20高級(jí)功能實(shí)現(xiàn)。
5.1 開(kāi)發(fā)環(huán)境與庫(kù)選擇
開(kāi)發(fā)環(huán)境: Keil MDK-ARM或STM32CubeIDE。推薦使用STM32CubeIDE,它集成了STM32CubeMX,方便進(jìn)行圖形化配置。
庫(kù)選擇: STM32HAL庫(kù)。 HAL庫(kù)是ST官方推薦的高級(jí)抽象層庫(kù),提供了簡(jiǎn)單易用的API,可以快速開(kāi)發(fā)。雖然LL庫(kù)(Low-Layer)能提供更精細(xì)的控制和更高的效率,但對(duì)于DS18B20這種對(duì)時(shí)序精度要求高,但數(shù)據(jù)量不大的應(yīng)用,HAL庫(kù)的性能也足夠。5.2 GPIO配置
DS18B20的DQ線是雙向的,既可以作為輸出(主設(shè)備拉低DQ線),也可以作為輸入(主設(shè)備讀取DQ線)。因此,STM32的GPIO需要頻繁地在輸出和輸入模式之間切換。
C
// 定義DS18B20連接的GPIO端口和引腳#define DS18B20_PORT GPIOA#define DS18B20_PIN GPIO_PIN_1// 設(shè)置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; // 無(wú)上拉/下拉,依靠外部4.7kΩ上拉電阻 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速模式 HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);}// 設(shè)置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; // 無(wú)上拉/下拉,外部已有上拉 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線 (實(shí)際上是釋放,依靠上拉電阻拉高)#define DS18B20_DQ_HIGH() HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET)// 讀取DQ線狀態(tài)#define DS18B20_DQ_READ() HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)
GPIO模式選擇的說(shuō)明:
輸出模式: 必須配置為推挽輸出(GPIO_MODE_OUTPUT_PP)。雖然DS18B20是開(kāi)漏設(shè)備,但STM32的GPIO在推挽模式下既可以輸出高電平也可以輸出低電平。當(dāng)需要拉低總線時(shí),輸出低電平;當(dāng)需要釋放總線時(shí),輸出高電平,但實(shí)際上DQ線是通過(guò)外部上拉電阻拉高的,所以即使STM32的輸出高電平能力與DS18B20的開(kāi)漏特性不完全匹配,只要我們配合外部上拉電阻,并確保在需要DS18B20響應(yīng)時(shí)STM32釋放DQ線(即配置為輸入或輸出高電平),就能正常工作。
輸入模式: 必須配置為浮空輸入(GPIO_MODE_INPUT)。這是因?yàn)镈Q線需要由DS18B20或外部上拉電阻來(lái)控制高低電平,STM32只需被動(dòng)讀取其狀態(tài)。如果配置為上拉/下拉輸入,可能會(huì)干擾總線上的電平。
速度: 配置為高速(GPIO_SPEED_FREQ_HIGH),以確保GPIO電平切換足夠快,滿足DS18B20的嚴(yán)格時(shí)序要求。5.3 精確延時(shí)函數(shù)
DS18B20通信對(duì)延時(shí)精度要求很高,HAL庫(kù)的HAL_Delay()函數(shù)基于系統(tǒng)時(shí)鐘節(jié)拍(毫秒級(jí)),不適合微秒級(jí)延時(shí)。需要編寫一個(gè)基于CPU空轉(zhuǎn)或DWT(Data Watchpoint and Trace Unit)的微秒級(jí)延時(shí)函數(shù)。
方法一:基于DWT_CYCCNT寄存器的微秒延時(shí)(推薦,精度高)
DWT_CYCCNT是ARM Cortex-M內(nèi)核自帶的一個(gè)32位周期計(jì)數(shù)器,每過(guò)一個(gè)CPU時(shí)鐘周期就會(huì)加1,因此可以實(shí)現(xiàn)非常精確的微秒甚至納秒級(jí)延時(shí)。
C
// 在core_cmInstr.h中定義了DWT相關(guān)寄存器// 需要在主函數(shù)或初始化函數(shù)中啟用DWT// DWT_Delay_Init() 函數(shù)void DWT_Delay_Init(void){ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 使能DWT DWT->LAR = 0xC5ACCE55; // 解鎖DWT DWT->CYCCNT = 0; // 清零計(jì)數(shù)器 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // 使能計(jì)數(shù)器}// 微秒延時(shí)函數(shù)void DWT_Delay_us(uint32_t us){ uint32_t start_tick = DWT->CYCCNT; uint32_t delay_ticks = us * (SystemCoreClock / 1000000); // 1us對(duì)應(yīng)的時(shí)鐘周期數(shù) while ((DWT->CYCCNT - start_tick) < delay_ticks);}
注意: SystemCoreClock 變量通常由STM32CubeMX生成,表示CPU主頻。使用DWT延時(shí)需要在CubeMX中配置調(diào)試接口為Trace模式。
方法二:基于__nop()的軟件延時(shí)(精度較差,不推薦用于精確時(shí)序)
這種方法通過(guò)執(zhí)行空指令來(lái)消耗CPU周期,但精度受編譯器優(yōu)化、CPU緩存、中斷等因素影響。
C
// 偽代碼,實(shí)際延時(shí)需要根據(jù)CPU主頻和指令周期數(shù)進(jìn)行調(diào)整// 不推薦用于DS18B20這類需要精確時(shí)序的場(chǎng)景void delay_us(uint32_t us){ for (volatile uint32_t i = 0; i < us * (SystemCoreClock / 1000000 / NOP_PER_US); i++) { __nop(); // 執(zhí)行空操作 }}
5.4 單總線基本操作實(shí)現(xiàn)
基于前面定義的GPIO操作和延時(shí)函數(shù),可以實(shí)現(xiàn)單總線協(xié)議中的復(fù)位、寫位和讀位。
5.4.1 單總線初始化(復(fù)位與存在脈沖)
C
// DS18B20復(fù)位函數(shù),返回1表示復(fù)位成功,0表示DS18B20不存在uint8_t DS18B20_Reset(void){ uint8_t presence = 0; DS18B20_SetPinOutput(); // 設(shè)置為輸出模式 DS18B20_DQ_LOW(); // 拉低DQ線 DWT_Delay_us(480); // 保持低電平至少480us (復(fù)位脈沖) DS18B20_DQ_HIGH(); // 釋放DQ線 (上拉電阻拉高) DWT_Delay_us(70); // 等待DS18B20響應(yīng) (15-60us等待,這里取70us確保DS18B20開(kāi)始響應(yīng)) DS18B20_SetPinInput(); // 設(shè)置為輸入模式,讀取存在脈沖 if (DS18B20_DQ_READ() == GPIO_PIN_RESET) // 檢測(cè)到低電平,表示DS18B20存在 { presence = 1; } DWT_Delay_us(410); // 等待存在脈沖結(jié)束 (DS18B20將DQ拉低60-240us,然后釋放,這里等待410us確保其完全釋放) return presence;}
5.4.2 寫入一個(gè)位(Write Bit)
C
// DS18B20寫入一個(gè)位void DS18B20_WriteBit(uint8_t bit){ DS18B20_SetPinOutput(); // 設(shè)置為輸出模式 if (bit == 1) // 寫入邏輯1 { DS18B20_DQ_LOW(); // 拉低DQ線 DWT_Delay_us(5); // 保持低電平1-15us (這里取5us) DS18B20_DQ_HIGH(); // 釋放DQ線 DWT_Delay_us(65); // 等待時(shí)隙結(jié)束 (至少60us,這里取65us) } else // 寫入邏輯0 { DS18B20_DQ_LOW(); // 拉低DQ線 DWT_Delay_us(65); // 保持低電平60-120us (這里取65us) DS18B20_DQ_HIGH(); // 釋放DQ線 DWT_Delay_us(5); // 等待時(shí)隙結(jié)束 (確??偩€空閑) }}
5.4.3 讀取一個(gè)位(Read Bit)
C
// DS18B20讀取一個(gè)位,返回0或1uint8_t DS18B20_ReadBit(void){ uint8_t bit = 0; DS18B20_SetPinOutput(); // 設(shè)置為輸出模式 DS18B20_DQ_LOW(); // 拉低DQ線 DWT_Delay_us(5); // 保持低電平1-15us (這里取5us) DS18B20_DQ_HIGH(); // 釋放DQ線 (準(zhǔn)備采樣) DS18B20_SetPinInput(); // 設(shè)置為輸入模式,讀取DQ線 DWT_Delay_us(10); // 等待15us采樣窗口的中間點(diǎn) (5us拉低 + 10us等待 = 15us) if (DS18B20_DQ_READ() == GPIO_PIN_SET) // 采樣DQ線 { bit = 1; } DWT_Delay_us(50); // 等待讀取時(shí)隙結(jié)束 (總共60us,已經(jīng)用了15us,再等50us) return bit;}
5.4.4 寫入一個(gè)字節(jié)(Write Byte)
C
// DS18B20寫入一個(gè)字節(jié)void DS18B20_WriteByte(uint8_t data){ for (int i = 0; i < 8; i++) { DS18B20_WriteBit(data & 0x01); // 從最低位開(kāi)始寫入 data >>= 1; }}
5.4.5 讀取一個(gè)字節(jié)(Read Byte)
C
// DS18B20讀取一個(gè)字節(jié)uint8_t DS18B20_ReadByte(void){ uint8_t data = 0; for (int i = 0; i < 8; i++) { data >>= 1; // 每次讀取一位,數(shù)據(jù)左移,低位進(jìn)來(lái) if (DS18B20_ReadBit()) { data |= 0x80; // 將讀取到的位放到最高位(因?yàn)槊看斡乙?,最高位?huì)被擠掉,所以需要反向操作) } } return data;}
修正: DS18B20_ReadByte 的邏輯,由于DS18B20通信是LSB優(yōu)先,讀取時(shí)應(yīng)該從最低位開(kāi)始組裝字節(jié)。
C
// DS18B20讀取一個(gè)字節(jié) (LSB優(yōu)先)uint8_t DS18B20_ReadByte(void){ uint8_t data = 0; for (int i = 0; i < 8; i++) { // 每次讀取一位,然后將該位放到字節(jié)的正確位置 if (DS18B20_ReadBit()) { data |= (0x01 << i); // 將讀取到的位放到對(duì)應(yīng)位置 } } return data;}
5.5 DS18B20高級(jí)功能實(shí)現(xiàn)
結(jié)合上述基本操作,可以實(shí)現(xiàn)DS18B20的溫度讀取等功能。
5.5.1 獲取溫度函數(shù)
C
// 讀取DS18B20溫度函數(shù)float DS18B20_GetTemp(void){ uint8_t temp_H, temp_L; int16_t raw_temp; float temp_C; if (DS18B20_Reset() == 0) // 復(fù)位失敗,DS18B20可能不存在或通信異常 { return -200.0; // 返回一個(gè)特殊值表示錯(cuò)誤 } DS18B20_WriteByte(0xCC); // 跳過(guò)ROM命令 (適用于單DS18B20) DS18B20_WriteByte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換 // 等待溫度轉(zhuǎn)換完成 // 可以通過(guò)讀取DQ線,等待其變?yōu)楦唠娖剑ǚ羌纳╇娔J剑? // 或者直接延時(shí)750ms(12位分辨率最長(zhǎng)轉(zhuǎn)換時(shí)間) // 推薦使用DWT_Delay_us(750000); 等待 // 更穩(wěn)妥的方式是輪詢DQ線,直到它變?yōu)楦唠娖? while(DS18B20_ReadBit() == 0) // 等待DQ線變?yōu)楦唠娖?(轉(zhuǎn)換完成) { // 可以加入超時(shí)機(jī)制防止死循環(huán) // HAL_Delay(1); // 每次等待1ms // count++; // if(count > 1000) break; // 超時(shí) } // 或者直接使用固定延時(shí)(簡(jiǎn)單但可能不準(zhǔn)確) DWT_Delay_us(750000); // 12位分辨率最長(zhǎng)轉(zhuǎn)換時(shí)間 if (DS18B20_Reset() == 0) // 再次復(fù)位,準(zhǔn)備讀取數(shù)據(jù) { return -200.0; } DS18B20_WriteByte(0xCC); // 跳過(guò)ROM命令 DS18B20_WriteByte(0xBE); // 讀取暫存器命令 temp_L = DS18B20_ReadByte(); // 讀取溫度低字節(jié) temp_H = DS18B20_ReadByte(); // 讀取溫度高字節(jié) // 組合成16位原始溫度值 raw_temp = (temp_H << 8) | temp_L; // 轉(zhuǎn)換為攝氏度(假設(shè)12位分辨率) temp_C = (float)raw_temp * 0.0625f; // 12位分辨率,每位0.0625℃ // 這里可以進(jìn)一步讀取CRC校驗(yàn)字節(jié),進(jìn)行數(shù)據(jù)校驗(yàn),提高可靠性 // uint8_t crc = DS18B20_ReadByte(); return temp_C;}
5.5.2 設(shè)置DS18B20分辨率(可選)
DS18B20允許設(shè)置9-12位的分辨率。
C
// 設(shè)置DS18B20分辨率函數(shù)// resolution: 9, 10, 11, 12uint8_t DS18B20_SetResolution(uint8_t resolution){ uint8_t config_reg = 0; // 配置寄存器值 if (DS18B20_Reset() == 0) { return 0; // 失敗 } // 讀取當(dāng)前暫存器內(nèi)容,保留TH和TL,只修改配置寄存器 DS18B20_WriteByte(0xCC); // SKIP ROM DS18B20_WriteByte(0xBE); // READ SCRATCHPAD // 丟棄前兩個(gè)字節(jié)的溫度數(shù)據(jù) (這里我們不讀取,因?yàn)槲覀冎魂P(guān)心配置寄存器) DS18B20_ReadByte(); // temp_L DS18B20_ReadByte(); // temp_H uint8_t TH = DS18B20_ReadByte(); // TH uint8_t TL = DS18B20_ReadByte(); // TL config_reg = DS18B20_ReadByte(); // 配置寄存器 // 根據(jù)分辨率設(shè)置配置寄存器 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; // 無(wú)效分辨率 } 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) // 復(fù)位,準(zhǔn)備復(fù)制到EEPROM { return 0; // 失敗 } DS18B20_WriteByte(0xCC); // SKIP ROM DS18B20_WriteByte(0x48); // COPY SCRATCHPAD (保存到EEPROM) HAL_Delay(10); // 等待復(fù)制完成,大約10ms return 1; // 成功}
5.6 CRC校驗(yàn)(提高數(shù)據(jù)可靠性)
DS18B20的暫存器讀取包含一個(gè)8位的CRC校驗(yàn)碼。在讀取數(shù)據(jù)后計(jì)算CRC并與讀取到的CRC校驗(yàn)碼進(jìn)行比對(duì),可以有效檢測(cè)通信過(guò)程中是否發(fā)生錯(cuò)誤,提高數(shù)據(jù)可靠性。
實(shí)現(xiàn)CRC校驗(yàn)需要一個(gè)CRC8算法。DS18B20使用的是Dallas Semiconductor的CRC8算法。
5.7 多點(diǎn)DS18B20驅(qū)動(dòng)(ROM搜索)
如果需要連接多個(gè)DS18B20,則需要實(shí)現(xiàn)ROM搜索算法。ROM搜索是一個(gè)迭代過(guò)程,通過(guò)發(fā)送0xF0 SEARCH ROM指令,DS18B20會(huì)返回其ROM碼中的沖突位,主機(jī)根據(jù)沖突位來(lái)遍歷所有可能的ROM碼,最終找到總線上所有DS18B20的唯一ID。這個(gè)算法相對(duì)復(fù)雜,需要維護(hù)一個(gè)搜索狀態(tài)變量和ROM地址數(shù)組。
大致步驟:
發(fā)送復(fù)位和存在脈沖。
發(fā)送SEARCH ROM (0xF0) 命令。
循環(huán)8次(每個(gè)字節(jié))或64次(每個(gè)位): a. 讀取兩位(DS18B20返回的“0”和“1”的沖突信息)。 b. 根據(jù)沖突信息和上一次搜索路徑,決定發(fā)送“0”或“1”以解決沖突。 c. 記錄當(dāng)前路徑的ROM碼。
重復(fù)直到所有ROM碼被發(fā)現(xiàn)。由于篇幅限制,這里不提供完整的ROM搜索算法代碼,但這是實(shí)現(xiàn)多點(diǎn)DS18B20測(cè)量的基礎(chǔ)。
6. 軟件流程圖與主程序設(shè)計(jì)
一個(gè)典型的DS18B20溫度采集主程序流程如下:
6.1 主程序流程圖
代碼段
graph TD A[系統(tǒng)初始化:時(shí)鐘、GPIO、DWT等] --> B{DS18B20復(fù)位成功?} B -- 否 --> C[報(bào)錯(cuò):傳感器不存在或通信異常] B -- 是 --> D[發(fā)送SKIP ROM命令 (0xCC)] D --> E[發(fā)送CONVERT T命令 (0x44)] E --> F[等待溫度轉(zhuǎn)換完成 (約750ms或輪詢DQ線)] F --> G{DS18B20再次復(fù)位成功?} G -- 否 --> C G -- 是 --> H[發(fā)送SKIP ROM命令 (0xCC)] H --> I[發(fā)送READ SCRATCHPAD命令 (0xBE)] I --> J[讀取9字節(jié)暫存器數(shù)據(jù) (包括溫度高低字節(jié)和CRC)] J --> K[進(jìn)行CRC校驗(yàn)] K -- 校驗(yàn)失敗 --> C K -- 校驗(yàn)成功 --> L[解析溫度數(shù)據(jù)] L --> M[將溫度數(shù)據(jù)通過(guò)串口/LCD等方式顯示/發(fā)送] M --> N[延時(shí)一段時(shí)間 (例如1秒) ] N --> D
6.2 主程序代碼骨架
#include "main.h"
#include "stm32f1xx_hal.h" // 根據(jù)實(shí)際MCU系列選擇
#include "ds18b20.h" // 包含DS18B20驅(qū)動(dòng)頭文件
#include <stdio.h> // 用于printf輸出
// 定義串口句柄,用于調(diào)試輸出
extern UART_HandleTypeDef huart1; // 假設(shè)使用UART1
void SystemClock_Config(void); // 系統(tǒng)時(shí)鐘配置函數(shù)
static void MX_GPIO_Init(void); // GPIO初始化函數(shù)
static void MX_USART1_UART_Init(void); // 串口初始化函數(shù)
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
DWT_Delay_Init(); // 初始化DWT用于微秒延時(shí)
float temperature = 0.0f;
char temp_str[30];
// 可選:設(shè)置DS18B20分辨率為12位
// DS18B20_SetResolution(12); // 如果需要設(shè)置,請(qǐng)?jiān)谘h(huán)外執(zhí)行一次
while (1)
{
temperature = DS18B20_GetTemp_WithCRC(); // 獲取溫度 (帶CRC校驗(yàn))
if (temperature > -100.0f) // 假設(shè)-200.0或-201.0是錯(cuò)誤碼
{
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. 調(diào)試與注意事項(xiàng)
在DS18B20驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)過(guò)程中,可能會(huì)遇到一些問(wèn)題。理解并解決這些問(wèn)題是確保系統(tǒng)穩(wěn)定運(yùn)行的關(guān)鍵。
7.1 常見(jiàn)問(wèn)題與解決方案
DS18B20復(fù)位失?。o(wú)存在脈沖):
檢查硬件連接: 確保VCC、GND、DQ線連接正確,特別是4.7kΩ上拉電阻是否正確連接且阻值合適。
檢查供電: 確保DS18B20供電電壓在3.0V-5.5V之間,且供電穩(wěn)定。嘗試使用獨(dú)立供電而不是寄生電源模式。
檢查GPIO配置: 確保STM32的GPIO設(shè)置為正確的輸出/輸入模式,并且在釋放總線時(shí)能正確變?yōu)檩斎牖蚋唠娖捷敵觥?/span>
檢查延時(shí)函數(shù): DS18B20時(shí)序?qū)ρ訒r(shí)精度要求很高。確保微秒延時(shí)函數(shù)(DWT_Delay_us)工作正常且準(zhǔn)確。示波器是調(diào)試時(shí)序的利器。
DS18B20損壞: 少數(shù)情況下傳感器本身可能損壞。嘗試更換一個(gè)DS18B20。讀取溫度數(shù)據(jù)異常(始終為85℃或0℃):
檢查READ SCRATCHPAD (0xBE) 命令是否正確發(fā)送。
檢查DS18B20_ReadByte()函數(shù),確保數(shù)據(jù)位能正確地被STM32讀取。使用示波器觀察DQ線的數(shù)據(jù)波形。
檢查溫度數(shù)據(jù)解析算法,特別是負(fù)數(shù)的補(bǔ)碼轉(zhuǎn)換和浮點(diǎn)數(shù)轉(zhuǎn)換。檢查CONVERT T (0x44) 命令是否正確發(fā)送。
確保在發(fā)送完CONVERT T命令后有足夠的等待時(shí)間(12位分辨率需要750ms)讓DS18B20完成轉(zhuǎn)換。85℃: DS18B20在上電或復(fù)位后的默認(rèn)溫度值是85℃。如果一直讀到這個(gè)值,說(shuō)明溫度轉(zhuǎn)換沒(méi)有成功啟動(dòng)或者數(shù)據(jù)讀取有問(wèn)題。
0℃: 可能是在讀取數(shù)據(jù)時(shí),接收到的都是0,或者數(shù)據(jù)解析錯(cuò)誤。多點(diǎn)測(cè)溫時(shí)無(wú)法識(shí)別所有傳感器:
ROM搜索算法問(wèn)題: ROM搜索算法比較復(fù)雜,任何一個(gè)細(xì)節(jié)錯(cuò)誤都可能導(dǎo)致部分或全部傳感器無(wú)法被發(fā)現(xiàn)。仔細(xì)對(duì)照DS18B20數(shù)據(jù)手冊(cè)中的SEARCH ROM流程。
總線負(fù)載過(guò)大: 當(dāng)連接的DS18B20數(shù)量過(guò)多或DQ線過(guò)長(zhǎng)時(shí),總線的容性負(fù)載會(huì)增加,導(dǎo)致信號(hào)上升沿變慢。此時(shí)可能需要減小上拉電阻的阻值(例如2.2kΩ),或者增加有源上拉電路(如使用一個(gè)MOSFET)。CRC校驗(yàn)失敗:
通信不穩(wěn)定: 檢查電源穩(wěn)定性,確保沒(méi)有大的噪聲干擾。
時(shí)序問(wèn)題: 再次檢查所有時(shí)序延時(shí)是否嚴(yán)格符合DS18B20數(shù)據(jù)手冊(cè)要求。任何微小的時(shí)序偏差都可能導(dǎo)致數(shù)據(jù)傳輸錯(cuò)誤。
CRC算法實(shí)現(xiàn)錯(cuò)誤: 仔細(xì)核對(duì)CRC8算法是否嚴(yán)格按照Dallas Semiconductor的規(guī)范實(shí)現(xiàn)。7.2 調(diào)試工具
示波器: 這是調(diào)試單總線通信必不可少的工具。通過(guò)示波器可以直觀地觀察DQ線的波形,判斷復(fù)位脈沖、存在脈沖、寫入時(shí)隙和讀取時(shí)隙的時(shí)序是否符合要求,以及數(shù)據(jù)位的電平是否正確。特別注意信號(hào)的上升沿和下降沿。
邏輯分析儀: 如果沒(méi)有示波器,或者需要同時(shí)觀察多路信號(hào),邏輯分析儀也是一個(gè)很好的選擇。它可以捕捉數(shù)字信號(hào),并解析出協(xié)議內(nèi)容,方便分析通信數(shù)據(jù)。
串口調(diào)試助手: 用于接收STM32發(fā)送的溫度數(shù)據(jù)和調(diào)試信息,驗(yàn)證程序邏輯是否正確。
STM32在線調(diào)試器(ST-Link/J-Link): 用于程序的燒錄、單步調(diào)試、變量觀察,是定位軟件邏輯錯(cuò)誤的必備工具。7.3 功耗優(yōu)化(可選)
在某些對(duì)功耗有嚴(yán)格要求的應(yīng)用中,可以考慮以下優(yōu)化:
降低DS18B20的采樣頻率: DS18B20在進(jìn)行溫度轉(zhuǎn)換時(shí)功耗最高。減少溫度讀取的頻率可以顯著降低系統(tǒng)平均功耗。
STM32進(jìn)入低功耗模式: 在等待DS18B20轉(zhuǎn)換完成的長(zhǎng)時(shí)間延時(shí)期間,可以將STM32進(jìn)入停止模式(Stop Mode)或待機(jī)模式(Standby Mode),然后通過(guò)定時(shí)器或外部中斷喚醒。
控制DS18B20的供電: 在極端低功耗場(chǎng)景下,可以通過(guò)一個(gè)GPIO控制MOSFET來(lái)切換DS18B20的VCC供電,只在需要測(cè)量時(shí)上電。
8. 總結(jié)與展望
本設(shè)計(jì)方案詳細(xì)闡述了基于STM32微控制器驅(qū)動(dòng)DS18B20溫度傳感器的全過(guò)程,從核心元器件選型、硬件連接、單總線通信協(xié)議解析到軟件驅(qū)動(dòng)的詳細(xì)實(shí)現(xiàn),并提供了關(guān)鍵代碼片段。通過(guò)精確的GPIO控制、嚴(yán)格的時(shí)序延時(shí)以及完善的CRC校驗(yàn),可以構(gòu)建一個(gè)穩(wěn)定、高精度的溫度采集系統(tǒng)。
DS18B20因其獨(dú)特的單總線特性和優(yōu)秀的性能,在眾多應(yīng)用中仍占有一席之地。未來(lái),在此基礎(chǔ)上可以進(jìn)一步擴(kuò)展,例如:
多點(diǎn)溫度網(wǎng)絡(luò): 實(shí)現(xiàn)復(fù)雜的ROM搜索算法,構(gòu)建多達(dá)上百個(gè)DS18B20的溫度傳感器網(wǎng)絡(luò)。
數(shù)據(jù)存儲(chǔ)與顯示: 將溫度數(shù)據(jù)存儲(chǔ)到EEPROM或SD卡中,并通過(guò)LCD、OLED顯示屏進(jìn)行實(shí)時(shí)顯示。
無(wú)線傳輸: 集成Wi-Fi(ESP8266/ESP32)、藍(lán)牙或LoRa模塊,將溫度數(shù)據(jù)上傳至云平臺(tái)或遠(yuǎn)程監(jiān)控。
溫度控制: 根據(jù)采集到的溫度數(shù)據(jù),通過(guò)PID算法或其他控制策略,控制風(fēng)扇、加熱器等執(zhí)行機(jī)構(gòu),實(shí)現(xiàn)智能溫度控制。
更高級(jí)的軟件架構(gòu): 引入實(shí)時(shí)操作系統(tǒng)(RTOS),將DS18B20驅(qū)動(dòng)封裝為獨(dú)立的任務(wù),提高系統(tǒng)的并發(fā)性和可維護(hù)性。掌握DS18B20的驅(qū)動(dòng)不僅是溫度采集的基礎(chǔ),更是深入理解單總線通信協(xié)議和嵌入式系統(tǒng)時(shí)序控制的絕佳實(shí)踐。希望本設(shè)計(jì)方案能為您的開(kāi)發(fā)工作提供全面而有價(jià)值的參考。
責(zé)任編輯:David
【免責(zé)聲明】
1、本文內(nèi)容、數(shù)據(jù)、圖表等來(lái)源于網(wǎng)絡(luò)引用或其他公開(kāi)資料,版權(quán)歸屬原作者、原發(fā)表出處。若版權(quán)所有方對(duì)本文的引用持有異議,請(qǐng)聯(lián)系拍明芯城(marketing@iczoom.com),本方將及時(shí)處理。
2、本文的引用僅供讀者交流學(xué)習(xí)使用,不涉及商業(yè)目的。
3、本文內(nèi)容僅代表作者觀點(diǎn),拍明芯城不對(duì)內(nèi)容的準(zhǔn)確性、可靠性或完整性提供明示或暗示的保證。讀者閱讀本文后做出的決定或行為,是基于自主意愿和獨(dú)立判斷做出的,請(qǐng)讀者明確相關(guān)結(jié)果。
4、如需轉(zhuǎn)載本方擁有版權(quán)的文章,請(qǐng)聯(lián)系拍明芯城(marketing@iczoom.com)注明“轉(zhuǎn)載原因”。未經(jīng)允許私自轉(zhuǎn)載拍明芯城將保留追究其法律責(zé)任的權(quán)利。
拍明芯城擁有對(duì)此聲明的最終解釋權(quán)。