孵化環(huán)境溫濕度監(jiān)控系統(tǒng)設(shè)計(jì)與DHT11驅(qū)動(dòng)實(shí)現(xiàn))
簡(jiǎn)介這款基于51單片機(jī)的孵化環(huán)境溫濕度監(jiān)控系統(tǒng)設(shè)計(jì)壓縮包面向單片機(jī)初學(xué)者、電子設(shè)計(jì)課程項(xiàng)目開(kāi)發(fā)者提供一套從硬件原理到軟件調(diào)試的完整參考方案可服務(wù)于課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或小型環(huán)境監(jiān)控項(xiàng)目開(kāi)發(fā)。資源共17個(gè)文件壓縮包僅100KB涵蓋Keil工程文件.uvproj/.uvopt、C語(yǔ)言源碼.c、編譯生成的HEX與LIST/M51中間文件以及原理圖截圖和必看說(shuō)明可滿足仿真、燒錄與二次修改需求也配套了工程備份文件供對(duì)照恢復(fù)。已有436人學(xué)習(xí)/下載。內(nèi)容包含傳感器數(shù)據(jù)采集、閾值判斷與加熱器/加濕器控制邏輯并對(duì)LCD1602顯示、串行通信等要點(diǎn)給出可運(yùn)行代碼HEX文件方便直接燒錄驗(yàn)證代碼注釋配合原理圖可快速理解初始化、采集、控制、顯示主流程適合結(jié)合DHT11/DHT22實(shí)際調(diào)試。建議讀者先瀏覽必看說(shuō)明和原理圖再按照模塊閱讀C代碼能夠較快掌握51單片機(jī)在環(huán)境監(jiān)控類(lèi)項(xiàng)目中的典型用法。1. 孵化環(huán)境溫濕度監(jiān)控51單片機(jī)課程設(shè)計(jì)的完整閉環(huán)禽蛋孵化對(duì)溫濕度極其敏感溫度長(zhǎng)期低于37℃會(huì)導(dǎo)致胚胎發(fā)育遲緩超過(guò)39℃則可能直接致死濕度低于45%時(shí)蛋內(nèi)水分蒸發(fā)過(guò)快影響氣室正常形成。這套基于51單片機(jī)的孵化環(huán)境溫濕度監(jiān)控系統(tǒng)正是圍繞這兩個(gè)核心參數(shù)做的閉環(huán)控制方案DHT11采集溫度和濕度STC89C52或AT89S52讀取數(shù)據(jù)后送到LCD1602顯示并通過(guò)繼電器控制加熱器和加濕器。對(duì)于電子信息工程和嵌入式方向的課設(shè)來(lái)說(shuō)這個(gè)題目幾乎把所有基礎(chǔ)外設(shè)都串起來(lái)了。如果你手里正好有這個(gè)源碼包下面從DHT11時(shí)序、LCD驅(qū)動(dòng)、繼電器控制到Proteus仿真和燒錄排錯(cuò)一條線講完。2. DHT11時(shí)序解析與51單片機(jī)單總線讀取實(shí)現(xiàn)2.1 DHT11的測(cè)量原理與40位數(shù)據(jù)幀DHT11使用單總線協(xié)議一條數(shù)據(jù)線負(fù)責(zé)命令和數(shù)據(jù)的雙向傳輸。傳感器上電后單片機(jī)必須先發(fā)送開(kāi)始信號(hào)將數(shù)據(jù)線拉低至少18ms然后釋放。DHT11會(huì)回復(fù)80us低電平和80us高電平隨后連續(xù)輸出40位數(shù)據(jù)。這40位按順序是濕度整數(shù)、濕度小數(shù)、溫度整數(shù)、溫度小數(shù)、校驗(yàn)和每項(xiàng)8位。DHT11的小數(shù)部分恒為0所以很多程序直接忽略小數(shù)DHT22則能讀出0.1℃分辨率的真實(shí)小數(shù)但成本更高。單總線每一位的編解碼依賴(lài)高電平持續(xù)時(shí)間。數(shù)據(jù)線先被拉低一段固定時(shí)間隨后釋放如果高電平持續(xù)26~28us表示邏輯0持續(xù)70us左右表示邏輯1。51單片機(jī)沒(méi)有硬件單總線控制器必須用sbit模擬這個(gè)時(shí)序因此代碼質(zhì)量取決于延時(shí)函數(shù)的精度。DHT11和DHT22的差異主要在精度和成本DHT11精度±2℃、±5%RH采樣周期1s價(jià)格只有幾塊錢(qián)課設(shè)和常規(guī)孵化監(jiān)控完全夠用。DHT11硬件接線很簡(jiǎn)單但數(shù)據(jù)腳必須接上拉電阻否則空閑狀態(tài)無(wú)法穩(wěn)定保持高電平。下表是標(biāo)準(zhǔn)接法。DHT11引腳51單片機(jī)說(shuō)明VCC5V供電工作范圍3.3V~5.5VDATAP2.0單總線數(shù)據(jù)10kΩ上拉到VCCGNDGND共地連接我一般建議數(shù)據(jù)引腳固定接P2.0因?yàn)楹罄m(xù)LCD1602和繼電器會(huì)占用大量P0、P1、P2口P2.0離繼電器輸出遠(yuǎn)不容易受吸合時(shí)的電磁干擾。在Proteus仿真時(shí)上拉電阻可以直接用RESPACK-8排阻其中一個(gè)引腳接VCC。2.2 開(kāi)始信號(hào)、讀取字節(jié)與校驗(yàn)下面是一份在Keil C51中可直接編譯的DHT11讀取代碼。它只用到寄存器和sbit位定義不依賴(lài)特殊擴(kuò)展庫(kù)。#include reg51.h #include intrins.h sbit DHT11 P2^0; void delay_us(unsigned int t) { while (t--) { _nop_(); } } void delay_ms(unsigned int t) { unsigned int i, j; for (i 0; i t; i) for (j 0; j 123; j); } void DHT11_Start(void) { DHT11 1; delay_us(2); DHT11 0; delay_ms(20); // 拉低20ms滿足開(kāi)始信號(hào)至少18ms要求 DHT11 1; // 釋放總線等待DHT11響應(yīng) delay_us(30); } unsigned char DHT11_ReadByte(void) { unsigned char i, dat 0; for (i 0; i 8; i) { while (DHT11 0); // 等待低電平結(jié)束即數(shù)據(jù)位起始 delay_us(40); // 延時(shí)40us后采樣 if (DHT11 1) dat | (0x80 i); // 高電平時(shí)間長(zhǎng)判為1 while (DHT11 1); // 等待高電平結(jié)束進(jìn)入下一位 } return dat; }這段代碼的核心是delay_us(40)。邏輯1的高電平寬度約70us邏輯0約28us所以在高電平開(kāi)始后40us處采樣只有邏輯1還維持在高這樣就區(qū)分了兩種電平。dat | (0x80 i)把當(dāng)前位放進(jìn)字節(jié)的對(duì)應(yīng)位置。等待DHT11 1結(jié)束再進(jìn)入下一位保證每位時(shí)序?qū)R。完整的讀取函數(shù)需要先調(diào)用DHT11_Start()然后檢測(cè)傳感器的響應(yīng)電平。如果傳感器沒(méi)有拉低響應(yīng)說(shuō)明接線或開(kāi)始信號(hào)有問(wèn)題需要返回錯(cuò)誤標(biāo)志。unsigned char DHT11_ReadData(unsigned char *dat) { unsigned char i, buf[5] {0, 0, 0, 0, 0}; DHT11_Start(); if (DHT11 1) return 0; // 未檢測(cè)到DHT11拉低響應(yīng) while (DHT11 0); // 等待80us低電平結(jié)束 while (DHT11 1); // 等待80us高電平結(jié)束 for (i 0; i 5; i) buf[i] DHT11_ReadByte(); if ((buf[0] buf[1] buf[2] buf[3]) buf[4]) { dat[0] buf[0]; dat[1] buf[1]; dat[2] buf[2]; dat[3] buf[3]; dat[4] buf[4]; return 1; // 校驗(yàn)通過(guò) } return 0; // 校驗(yàn)失敗 }調(diào)用后dat[0]是濕度整數(shù)dat[1]濕度小數(shù)dat[2]溫度整數(shù)dat[3]溫度小數(shù)dat[4]校驗(yàn)和。DHT11的小數(shù)位沒(méi)有實(shí)際參考價(jià)值所以后面顯示和控制邏輯可以只取dat[0]和dat[2]。校驗(yàn)失敗時(shí)不要直接丟棄數(shù)據(jù)常見(jiàn)做法是連續(xù)讀取三次取出現(xiàn)次數(shù)最多的那一組能明顯降低偶發(fā)誤碼的影響。2.3 延時(shí)函數(shù)在不同晶振下的誤差處理Keil C51的_nop_()在12MHz晶振下約等于1us但整個(gè)delay_us循環(huán)還有函數(shù)調(diào)用和while判斷的額外開(kāi)銷(xiāo)所以實(shí)際延時(shí)比名義值偏長(zhǎng)。如果單片機(jī)換成了11.0592MHz晶振用同一份代碼40us的實(shí)際等待可能會(huì)變成45us以上。這不會(huì)導(dǎo)致DHT11完全失效但會(huì)增加邊界位誤判概率尤其是邏輯0容易被人為拉長(zhǎng)到40us以上。更穩(wěn)妥的做法是使用定時(shí)器延時(shí)但課設(shè)里大多數(shù)代碼都用普通循環(huán)。我判斷代碼是否正常的經(jīng)驗(yàn)是連續(xù)讀取兩次溫度差不超過(guò)1℃、濕度差不超過(guò)1%就說(shuō)明時(shí)序基本正確。如果數(shù)值跳變劇烈優(yōu)先把delay_us(40)改成兩個(gè)_nop_()或加一個(gè)空語(yǔ)句而不是直接懷疑傳感器損壞。另外DHT11兩次采樣間隔不能小于1s內(nèi)部傳感器完成一次測(cè)量需要一定時(shí)間主循環(huán)里連續(xù)讀會(huì)讀到舊值這個(gè)放到第4章結(jié)合主循環(huán)結(jié)構(gòu)再展開(kāi)。3. LCD1602顯示與繼電器控制從原理圖到Keil C51工程3.1 原理圖接線與P0口上拉問(wèn)題資源包里的“原理圖截圖.png”是標(biāo)準(zhǔn)課設(shè)接法。LCD1602的控制線RS、RW、E接在P2口高位數(shù)據(jù)線D0-D7接P0口。繼電器控制端接在P1口DHT11數(shù)據(jù)腳接P2.0整體布局很清晰。有一個(gè)細(xì)節(jié)必須單獨(dú)提P0口內(nèi)部沒(méi)有上拉電阻是開(kāi)漏輸出。直接接LCD1602數(shù)據(jù)端時(shí)輸出高電平能力很弱顯示屏容易出現(xiàn)“沒(méi)有字符、亂碼、一個(gè)亮行”等表象。原理圖上通常給P0口加10kΩ排阻到VCC。如果你的板子沒(méi)有排阻至少要把P0口所有引腳在初始化時(shí)置1再外接上拉電阻提供高電平。下面是一份和原理圖對(duì)應(yīng)的引腳分配表方便抄板和改程序時(shí)核對(duì)。模塊信號(hào)51引腳說(shuō)明DHT11DATAP2.010kΩ上拉LCD1602RSP2.50指令 1數(shù)據(jù)LCD1602RWP2.60寫(xiě) 1讀LCD1602EP2.7高電平使能下降沿鎖存LCD1602D0-D7P0.0-P0.7并聯(lián)10kΩ排阻上拉繼電器IN1P1.0控制加熱器繼電器IN2P1.1控制加濕器繼電器模塊如果是低電平觸發(fā)控制邏輯要反過(guò)來(lái)。實(shí)物用PNP三極管驅(qū)動(dòng)時(shí)基極低電平導(dǎo)通繼電器線圈通電NPN三極管則相反。看原理圖時(shí)重點(diǎn)看三極管型號(hào)不要讓程序和硬件電平反著來(lái)。3.2 LCD1602驅(qū)動(dòng)8線并行讀寫(xiě)LCD1602大多用8線并行方式因?yàn)?1的P0口正好8位。驅(qū)動(dòng)時(shí)序不復(fù)雜E拉高期間RS指定命令還是數(shù)據(jù)RW固定為寫(xiě)0數(shù)據(jù)線準(zhǔn)備好后E的下降沿把數(shù)據(jù)鎖存進(jìn)LCD控制器。初始化要先等上電穩(wěn)定再發(fā)功能設(shè)置、顯示開(kāi)關(guān)、清屏。下面是一份精簡(jiǎn)的8線驅(qū)動(dòng)代碼接口與上一節(jié)表格一致。#include reg51.h #define LCD_DB P0 sbit LCD_RS P2^5; sbit LCD_RW P2^6; sbit LCD_E P2^7; void LcdDelay(unsigned char t) { unsigned char i; while (t--) for (i 0; i 120; i); } void LcdWriteCmd(unsigned char cmd) { LCD_E 0; LCD_RS 0; // 命令模式 LCD_RW 0; // 寫(xiě)模式 LCD_DB cmd; LcdDelay(2); LCD_E 1; LcdDelay(2); LCD_E 0; // 下降沿鎖存 } void LcdWriteData(unsigned char dat) { LCD_E 0; LCD_RS 1; // 數(shù)據(jù)模式 LCD_RW 0; LCD_DB dat; LcdDelay(2); LCD_E 1; LcdDelay(2); LCD_E 0; } void LcdInit(void) { LcdDelay(20); // 上電等待 LcdWriteCmd(0x38); // 8位模式雙行5x8點(diǎn)陣 LcdWriteCmd(0x0C); // 開(kāi)顯示不顯示光標(biāo) LcdWriteCmd(0x06); // 輸入模式寫(xiě)一個(gè)字符后地址加1 LcdWriteCmd(0x01); // 清屏 LcdDelay(5); }這些指令里0x38是LCD1602的核心配置漏掉它屏幕可能只能顯示一排方塊。0x01清屏需要時(shí)間所以后面加了延時(shí)。每次寫(xiě)之前把E拉低是為了避免初始化過(guò)程中GPIO電平抖動(dòng)導(dǎo)致誤寫(xiě)入。顯示字符串時(shí)先設(shè)置DDRAM地址再逐字符寫(xiě)入數(shù)據(jù)。首行地址從0x00開(kāi)始第二行從0x40開(kāi)始因?yàn)镈DRAM基地址是0x80所以第二行首地址是0x800x400xC0。void LcdShowString(unsigned char addr, unsigned char *str) { LcdWriteCmd(0x80 | addr); // 設(shè)置DDRAM地址0x00為第一行 while (*str) { LcdWriteData(*str); } }調(diào)用時(shí)LcdShowString(0x00, Temp:)會(huì)在左上角顯示標(biāo)題LcdShowString(0x40, Hum:)會(huì)在第二行顯示。如果要顯示動(dòng)態(tài)溫度值可以用sprintf把數(shù)字轉(zhuǎn)成字符串但keil C51的sprintf比較占代碼空間課設(shè)里更常見(jiàn)的是像第5章那樣用0x30加上數(shù)字位直接轉(zhuǎn)ASCII字符。3.3 繼電器驅(qū)動(dòng)與加熱、加濕輸出繼電器部分的關(guān)鍵不是代碼而是驅(qū)動(dòng)電路。51單片機(jī)IO口不能直接驅(qū)動(dòng)5V繼電器線圈常規(guī)做法是使用PNP三極管作為開(kāi)關(guān)基極接IO口發(fā)射極接VCC集電極接繼電器線圈線圈兩端并聯(lián)續(xù)流二極管。PNP三極管高電平截止、低電平導(dǎo)通所以程序里控制加熱器時(shí)通常置0有效。如果使用成品低電平觸發(fā)繼電器模塊模塊內(nèi)部已經(jīng)完成三極管和續(xù)流二極管照著手冊(cè)接線即可??刂拼a可以封裝為獨(dú)立函數(shù)傳入溫度和濕度輸出加熱與加濕兩個(gè)IO狀態(tài)。sbit HEATER P1^0; sbit HUMIDIFIER P1^1; void ControlOutput(unsigned char temp, unsigned char hum) { if (temp 37) HEATER 0; // 低電平導(dǎo)通PNP加熱器啟動(dòng) else if (temp 39) HEATER 1; // 高電平截止加熱器停止 if (hum 50) HUMIDIFIER 0; // 加濕器啟動(dòng) else if (hum 60) HUMIDIFIER 1; }這種寫(xiě)法在中間區(qū)間不修改IO繼電器能保持上一狀態(tài)但如果是簡(jiǎn)單閾值判斷溫度在37℃附近波動(dòng)時(shí)仍可能頻繁通斷。更平滑的做法是加回差這個(gè)放到第4章結(jié)合仿真講。實(shí)物調(diào)試時(shí)要注意一個(gè)現(xiàn)象繼電器吸合瞬間LCD數(shù)值可能跳一個(gè)字這通常是繼電器線圈干擾DHT11數(shù)據(jù)線。解決方法是繼電器供電和單片機(jī)供電分開(kāi)數(shù)據(jù)線用雙絞線縮短長(zhǎng)度。3.4 Keil工程文件識(shí)別與編譯輸出源碼包里看到的1.uvproj、1.uvopt、1.c、1.hex是一套完整的Keil工程。1.uvproj是工程文件用Keil uVision5打開(kāi)1.uvopt是窗口布局配置刪掉不影響編譯1.c是主程序源文件1.hex是編譯生成的燒錄文件。1.OBJ、1.LST、1.M51都是編譯中間產(chǎn)物不是人看的源碼。打開(kāi)工程后按F7編譯出現(xiàn)“0 Error(s)”就說(shuō)明編譯通過(guò)。如果只拿到源碼沒(méi)有工程文件也可以新建一個(gè)工程把1.c添加進(jìn)去然后設(shè)置Atmel AT89C52或STC89C52RC芯片型號(hào)。編譯前務(wù)必在Options for Target的Output選項(xiàng)卡勾選Create HEX File否則不會(huì)生成新的hex。4. 閾值控制與Proteus仿真聯(lián)調(diào)4.1 孵化溫濕度閾值設(shè)置與回差邏輯孵化過(guò)程中溫度和濕度不能只做單點(diǎn)控制。常見(jiàn)禽蛋孵化參考條件是溫度設(shè)定37.8℃允許波動(dòng)范圍37℃~39℃濕度設(shè)定55%允許波動(dòng)范圍50%~60%。如果代碼采用“低于下限開(kāi)啟、高于上限關(guān)閉”的雙閾值中間區(qū)間保持現(xiàn)狀繼電器就不會(huì)在臨界點(diǎn)瘋狂翻轉(zhuǎn)。這就是回差控制的思路也叫滯回控制。下面代碼把閾值寫(xiě)在宏定義里調(diào)整方便也方便答辯時(shí)演示參數(shù)變化。#define TEMP_LOW 37 #define TEMP_HIGH 39 #define HUM_LOW 50 #define HUM_HIGH 60 void SmartControl(unsigned char temp, unsigned char hum) { if (temp TEMP_LOW) { HEATER 0; // 低電平導(dǎo)通繼電器 } else if (temp TEMP_HIGH) { HEATER 1; } if (hum HUM_LOW) { HUMIDIFIER 0; } else if (hum HUM_HIGH) { HUMIDIFIER 1; } }有人會(huì)問(wèn)溫度在37℃到39℃之間時(shí)這段代碼沒(méi)有對(duì)HEATER賦值繼電器會(huì)怎樣答案是保持原狀態(tài)因?yàn)镠EATER對(duì)應(yīng)的是IO鎖存器函數(shù)返回后引腳電平不變。所以“低于下限開(kāi)、高于上限關(guān)、中間保持”已經(jīng)天然形成回差。如果采用普通單閾值比如低于37℃開(kāi)、高于37℃關(guān)溫度在臨界抖動(dòng)時(shí)繼電器就會(huì)快速通斷觸點(diǎn)和加熱器壽命都會(huì)受影響。如果你想讓控制更精細(xì)可以用溫度小數(shù)位參與判斷。DHT11的小數(shù)位恒為0實(shí)際需要DHT22或者放大10倍的虛擬溫度值。課設(shè)答辯時(shí)能說(shuō)清這個(gè)局限反而比強(qiáng)行顯示小數(shù)位更專(zhuān)業(yè)。4.2 Proteus仿真元件查找與hex加載資源包沒(méi)有附帶Proteus工程文件但按原理圖可以很快搭出仿真。Proteus 8以上版本在元件庫(kù)搜索AT89C51、LM016L、DHT11、RELAY即可。注意DHT11在Proteus里的模型名稱(chēng)可能因版本不同有差異有些版本叫DHT11有些版本用AM2301模型代替。仿真元件Proteus關(guān)鍵詞用途單片機(jī)AT89C51與STC89C52引腳兼容溫濕度傳感器DHT11讀取溫濕度顯示屏LM016L對(duì)應(yīng)LCD1602繼電器RELAY模擬加熱/加濕開(kāi)關(guān)排阻RESPACK-8P0口上拉在Proteus中雙擊AT89C51在Program File一欄選擇Keil生成的1.hex然后運(yùn)行仿真。正常情況LCD會(huì)顯示當(dāng)前溫濕度當(dāng)溫度低于37℃時(shí)加熱燈亮高于39℃時(shí)加熱燈滅。仿真環(huán)境里DHT11模型默認(rèn)輸出固定數(shù)值所以多數(shù)人驗(yàn)證的是顯示和控制邏輯而不是真實(shí)讀取協(xié)議。想驗(yàn)證DHT11讀取代碼本身可以用示波器觀察數(shù)據(jù)腳波形或者用信號(hào)發(fā)生器模擬單總線數(shù)據(jù)。我一般會(huì)先在Proteus里把閾值調(diào)低一點(diǎn)用虛擬溫度變量模擬比如讓溫度從35℃緩慢升到41℃觀察繼電器吸合和釋放的邊界是否在37℃和39℃附近。這樣能快速確認(rèn)回差邏輯是否生效再燒到實(shí)物上。4.3 主循環(huán)中的采樣節(jié)拍與狀態(tài)刷新DHT11兩次采樣之間必須間隔至少1s否則傳感器內(nèi)部測(cè)量未完成讀出的數(shù)據(jù)不會(huì)更新。如果主循環(huán)寫(xiě)成下面這樣讀取頻率會(huì)遠(yuǎn)高于1s實(shí)際溫度會(huì)卡在固定值或者偶爾讀到舊數(shù)據(jù)。// 錯(cuò)誤示例主循環(huán)里連續(xù)讀 while (1) { DHT11_ReadData(dat); LcdShowString(0x00, T:); // ... }正確做法是用定時(shí)器產(chǎn)生時(shí)間片。定時(shí)器0中斷每10ms進(jìn)入一次累積到100次就是1s主循環(huán)只在標(biāo)志位置位時(shí)做一次完整采集、顯示和控制。下面是基礎(chǔ)框架。volatile unsigned int tick_10ms 0; bit flag_1s 0; void Timer0_ISR(void) interrupt 1 { TH0 0xDC; // 10ms重裝載12MHz晶振 TL0 0x00; tick_10ms; if (tick_10ms 100) { tick_10ms 0; flag_1s 1; // 1秒定時(shí)到 } } void main(void) { unsigned char dat[5] {0, 0, 0, 0, 0}; LcdInit(); TMOD 0x01; TH0 0xDC; TL0 0x00; ET0 1; EA 1; TR0 1; while (1) { if (flag_1s) { flag_1s 0; if (DHT11_ReadData(dat)) { SmartControl(dat[2], dat[0]); // 更新LCD顯示 } } } }定時(shí)器初值0xDC00是12MHz晶振下10ms溢出的標(biāo)準(zhǔn)值。如果晶振是11.0592MHzTH0和TL0要重算否則1s標(biāo)志會(huì)提前或延后導(dǎo)致DHT11讀取頻率超出限制。主循環(huán)中while(1)不阻塞1s之內(nèi)還能做按鍵掃描、蜂鳴器報(bào)警等其他任務(wù)這是嵌入式系統(tǒng)最基礎(chǔ)的“時(shí)間片輪轉(zhuǎn)”結(jié)構(gòu)也是這個(gè)課設(shè)從“能跑”到“結(jié)構(gòu)合理”的分水嶺。5. 燒錄hex與現(xiàn)場(chǎng)排錯(cuò)解決傳感器誤讀和控制混亂5.1 STC單片機(jī)的串口下載流程資源包里的1.hex就是最終燒錄文件。以STC89C52RC為例使用USB轉(zhuǎn)TTL模塊連接單片機(jī)P3.0和P3.1注意交叉USB轉(zhuǎn)TTL的TXD接單片機(jī)P3.0RXD接P3.1GND共地。打開(kāi)STC-ISP軟件選擇STC89C52RC加載1.hex波特率可以先選2400點(diǎn)擊下載后再給單片機(jī)板上電。如果提示握手失敗先檢查串口號(hào)是否被占用再確認(rèn)USB轉(zhuǎn)TTL模塊是否插緊。5.2 三種現(xiàn)場(chǎng)故障的排查順序現(xiàn)象優(yōu)先排查點(diǎn)常見(jiàn)原因LCD有背光無(wú)字符對(duì)比度電位器、P0上拉對(duì)比度電壓異?;騊0口沒(méi)有上拉電阻溫濕度顯示0或255DHT11供電、上拉電阻、Data線Data線接錯(cuò)或延時(shí)函數(shù)與晶振不匹配繼電器不動(dòng)作三極管基極電阻、模塊電平觸發(fā)邏輯與三極管類(lèi)型不匹配DHT11誤讀是最難定位的。如果溫度一直顯示0先測(cè)量Data引腳電壓空閑狀態(tài)應(yīng)該在3.3V以上。如果只有0.5V說(shuō)明上拉電阻焊接有問(wèn)題如果始終為高說(shuō)明DHT11沒(méi)有響應(yīng)可能是數(shù)據(jù)引腳定義和原理圖不一致。用LED閃爍判斷程序是否卡在while(DHT110)是在沒(méi)有示波器時(shí)最直接的辦法。在讀取函數(shù)里加入超時(shí)計(jì)數(shù)也能防止傳感器損壞后程序死鎖。5.3 串口輸出調(diào)試把現(xiàn)場(chǎng)數(shù)據(jù)送出來(lái)當(dāng)LCD顯示和控制邏輯同時(shí)出問(wèn)題時(shí)我一般會(huì)屏蔽LCD代碼用串口把DHT11原始讀到的數(shù)據(jù)發(fā)到上位機(jī)先確認(rèn)傳感器本身是否工作。這樣能把問(wèn)題范圍縮小一半。void Uart_Init(void) { SCON 0x50; // 模式18位UART允許接收 TMOD | 0x20; // 定時(shí)器1作為波特率發(fā)生器 TH1 0xFD; // 9600bps 11.0592MHz TL1 0xFD; TR1 1; } void Uart_SendChar(unsigned char c) { SBUF c; while (TI 0); TI 0; } void Uart_SendString(unsigned char *s) { while (*s) { Uart_SendChar(*s); } }調(diào)用時(shí)把讀到的數(shù)據(jù)轉(zhuǎn)換成可見(jiàn)ASCII字符發(fā)送串口助手連續(xù)收到“T:37 H:54”這樣的數(shù)據(jù)說(shuō)明傳感器和單片機(jī)通信正常問(wèn)題在顯示或控制環(huán)節(jié)如果收不到或全是FF則問(wèn)題在傳感器或單總線時(shí)序。這個(gè)串口調(diào)試技巧同樣適用于其他51單片機(jī)課設(shè)比反復(fù)看LCD定位快得多。本文還有配套的精品資源點(diǎn)擊獲取