1、個人構想:如何爲編程愛好者設計一款好玩的智能硬件(一)——即插即用、積木化、功能重組的智能硬件模塊構想html
2、別人家的孩子:如何爲編程愛好者設計一款好玩的智能硬件(二)——別人是如何設計硬件積木的!編程
3、MCU選型:如何爲編程愛好者設計一款好玩的智能硬件(三)——該選什麼樣的MCU呢?網絡
4、溫溼度傳感器DHT11驅動封裝:ide
萬事開頭難,昨晚睡太晚!天天一篇確實有點累,不過能鞭策本身不偷懶努力向前!前三篇咱們已經將「X-積木」大體輪廓(第一篇)、同類產品(第二篇)、MCU選型及大體計劃(第三篇最後)介紹了一下。前幾篇屬於宏觀把控,本篇將實施第三篇最後的三步計劃中的第一步——「暫選CC2541做爲核心塊,先實現幾個簡單的功能塊(如溫溼度模塊、光照模塊、顯示屏模塊、超聲波模塊、繼電器模塊、人體紅外線模塊等),並分別對各個外設模塊封裝成能夠經過藍牙獲取其使用說明和通訊方式的API,而後嘗試開發一個手機demo來經過藍牙蒐集這些信息並展現。」函數
包括本篇在內的接下來幾篇都是針對各類常見外設進行和平臺無關性封裝,在每篇中會詳細介紹每一個外設的特性及封裝思路,而且在各類平臺上進行驗證。本篇介紹智能家居領域老是少不了的一款傳感器——溫溼度傳感器post
買買買:url
有些朋友建議我「你講軟件咱們可以下載找到,你講硬件咱們很難找到,若是方便給個連接吧」。所以從此我會在必要的地方插入如何購買這些元件的連接(不是廣告植入哦!)。對於該款DHT11傳感器只要在淘寶上輸入關鍵詞,即可搜到一片(我建議你們買那些銷量比較高的,若是您不想跟風的話,能夠深刻了解下所給的資料等是否齊全)。不過目前我不建議你們盲目地買過來,從此我會針對具體的小應用給你們一些採購方案~spa
傳感器資料:設計
datasheet:http://akizukidenshi.com/download/ds/aosong/DHT11.pdfcode
DHT11 ①:是一個包含溼度測量電阻、NTC溫度測量裝置和一個8-bit的微處理器的溫溼度採集模塊。②:典型應用在加溼器、空調還有部分傳感器網絡中的氣象採集等。③:特別說明其輸出的是相對溫溼度,須要校準!
Relative humidity Resolution: 16Bit Repeatability: ±1% RH Accuracy: At 25℃ ±5% RH Interchangeability: fully interchangeable Response time: 1 / e (63%) of 25℃ 6s 1m / s air 6s Hysteresis: <± 0.3% RH Long-term stability: <± 0.5% RH / yr in Temperature Resolution: 16Bit Repeatability: ±0.2℃ Range: At 25℃ ±2℃ Response time: 1 / e (63%) 10S
下面是其一個典型的小系統的電路圖,其四個引腳的典型電器特性爲:1, the VDD power supply 3.5~5.5V DC 2 DATA serial data, a single bus 3, NC, empty pin 4, GND ground, the negative power
從上面能夠看出,其和MCU進行通訊的I/O引腳只有引腳2一根,因此要想正確從其中獲取溫溼度數據就必須瞭解其單線的通訊協議了!咱們的任務就是根據其通訊協議,編寫一個平臺無關的底層驅動!
通訊協議:
數據在DHT11和MCU之間採用單總線傳輸,一次傳輸40個bit,高位先出。
數據格式:
8bit溼度數據整數部分+8bit溼度數據小數部分+8bit溫度數據整數部分+8bit溫度數據小數部分+8bit奇偶校驗
@這裏的8bit奇偶校驗=8bit溼度數據整數部分+8bit溼度數據小數部分+8bit溫度數據整數部分+8bit溫度數據小數部分
數據時序圖:
上面咱們知道DHT11經過單總線將溫溼度數據和奇偶校驗總共40bit發送給主設備(通常是MCU),那麼MCU如何發起、讀取、並結束讀數據這一過程的呢?要想知道這一過程最簡單的方式即是看數據時序圖(不少人討厭看、膽怯看,是由於不瞭解它,其實它展現了整個通訊的詳細過程,很美!)下面咱們就根據一個寫好的DHT11的驅動程序,來反推這個時序圖的精巧與美!
Step 1:系統上電啓動後一秒DHT11趨於穩定,能夠進行數據讀取操做(因此係統剛啓動時最好不要馬上調用DHT11驅動函數讀取數據
Step 2:初看該時序圖,能夠看出host設備置單總線一個凹槽型電平,造成開始讀的初始信號!對於細節——置低必定要大於18ms。
Step 3:在主設備發起開始信號後便進入等待從設備應答模式,接下來當從設備將數據總線拉低持續80us而後又拉高80us後就準備發送40bit的數據了。
Step 4:接下來40bit的數據均是採用下面的格式發送過來,那麼這40bit如何區分是1仍是0呢?以下:根據高電平持續的時間——當高電平持續30us如下表示該bit爲0,若維持50-70us代表爲1.這樣就能準確得到這40bit的數據狀況了,再加上最後8bit的奇偶校驗,便更加加強了其可靠性!
Step 5:結束通訊,在40bit數據輸出完畢低電平持續50us後置主設備爲輸出模式,置總線爲高電平,結束本次通訊。
數據時序圖對應的DHT11的驅動程序(只是從網上找的針對CC2541的):
從下面代碼容易看出:step2階段的代碼和上面的時序圖凹槽型幾乎同樣;step3階段用while循環統計低電平和高電平持續時間(不過這裏的驅動並無用這個持續時間);讀8bit數據函數下面講;step5階段在52行端口屬性設置爲輸出時真正生效,雖然上面27行已經將DATA_PIN置高,可是到52行纔會生效,因此也知足40bit數據傳輸結束後50us後拉高電平結束本次數據傳輸。
1 void DHT11(void) //溫溼傳感啓動 2 { 3 DATA_PIN=0; //啓動階段step2 4 Delay_ms(19); //>18MS 5 DATA_PIN=1; 6 P0DIR &= ~0x01; //從新配置IO口方向 7 Delay_10us(); 8 Delay_10us(); 9 Delay_10us(); 10 Delay_10us(); 11 if(!DATA_PIN) 12 { 13 ucharFLAG=2; //從設備應答階段step3 14 while((!DATA_PIN)&&ucharFLAG++); 15 ucharFLAG=2; 16 while((DATA_PIN)&&ucharFLAG++); 17 COM(); //讀取40bit階段step4 18 ucharRH_data_H_temp=ucharcomdata; 19 COM(); 20 ucharRH_data_L_temp=ucharcomdata; 21 COM(); 22 ucharT_data_H_temp=ucharcomdata; 23 COM(); 24 ucharT_data_L_temp=ucharcomdata; 25 COM(); 26 ucharcheckdata_temp=ucharcomdata; 27 DATA_PIN=1; //和最後的52行組成end階段step5 28 uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);//奇偶校驗 29 if(uchartemp==ucharcheckdata_temp) 30 { 31 ucharRH_data_H=ucharRH_data_H_temp; 32 ucharRH_data_L=ucharRH_data_L_temp; 33 ucharT_data_H=ucharT_data_H_temp; 34 ucharT_data_L=ucharT_data_L_temp; 35 ucharcheckdata=ucharcheckdata_temp; 36 } 37 wendu_shi=ucharT_data_H/10; 38 wendu_ge=ucharT_data_H%10; 39 40 shidu_shi=ucharRH_data_H/10; 41 shidu_ge=ucharRH_data_H%10; 42 } 43 else //沒用成功讀取,返回0 44 { 45 wendu_shi=0; 46 wendu_ge=0; 47 48 shidu_shi=0; 49 shidu_ge=0; 50 } 51 52 P0DIR |= 0x01; //IO口須要從新配置 53 }
對於COM函數連續讀8bit數據的細節以下:參照step4兩種表示當前bit位爲1仍是0的方法——第7行是用while循環過掉低電平狀態(一樣這裏ucharFLAG做爲統計低電平持續的時間並無用,這也體現了該驅動的不嚴謹性!),以後故意延時30us並檢測當前是低電平仍是高電平,這裏用的很機智!由於step4中兩個時序圖能夠看出表示當前bit位爲0的時序圖高電平持續時間沒有超過30us,表示1的時序圖高電平持續了近70us,因此延時30us後再檢測當前電平就能判斷該bit位是0仍是1了!很機智吧!
1 void COM(void) // 溫溼寫入 2 { 3 uchar i; 4 for(i=0;i<8;i++) 5 { 6 ucharFLAG=2; 7 while((!DATA_PIN)&&ucharFLAG++); 8 Delay_10us(); 9 Delay_10us(); 10 Delay_10us(); 11 uchartemp=0; 12 if(DATA_PIN)uchartemp=1; 13 ucharFLAG=2; 14 while((DATA_PIN)&&ucharFLAG++); 15 if(ucharFLAG==1)break; 16 ucharcomdata<<=1; 17 ucharcomdata|=uchartemp; 18 } 19 }
小結&接下來計劃:
本節將一款經常使用的DHT11溫溼度傳感器的購買、資料查找、datasheet閱讀、時序圖的理解和驅動代碼的之因此這樣寫的緣由給你們展現出來。雖然是一款簡單的單總線傳感器,可是這種分析流程和方法和比較複雜的模塊基本都是類似的。今天時間也有點晚了,我準備將該傳感器和平臺無關的驅動封裝放在下一篇介紹,今天得早點休息啦~晚安,各位!明天同一時間、同一地點ヾ( ̄▽ ̄)再見~
@beautifulzzzz
2015-9-8 持續更新中~