一、我的構想:如何為編程愛好者設計一款好玩的智能硬件(一)——即插即用、積木化、功能重組的智能硬件模塊構想
二、別人家的孩子:如何為編程愛好者設計一款好玩的智能硬件(二)——別人是如何設計硬件積木的!
三、MCU選型:如何為編程愛好者設計一款好玩的智能硬件(三)——該選什么樣的MCU呢?
四、溫濕度傳感器DHT11驅動封裝:
萬事開頭難,昨晚睡太晚!每天一篇確實有點累,不過能鞭策自己不偷懶努力向前!前三篇我們已經將“X-積木”大致輪廓(第一篇)、同類產品(第二篇)、MCU選型及大致計划(第三篇最后)介紹了一下。前幾篇屬於宏觀把控,本篇將實施第三篇最后的三步計划中的第一步——“暫選CC2541作為核心塊,先實現幾個簡單的功能塊(如溫濕度模塊、光照模塊、顯示屏模塊、超聲波模塊、繼電器模塊、人體紅外線模塊等),並分別對各個外設模塊封裝成可以通過藍牙獲取其使用說明和通信方式的API,然后嘗試開發一個手機demo來通過藍牙搜集這些信息並展示。”
包括本篇在內的接下來幾篇都是針對各種常見外設進行和平台無關性封裝,在每篇中會詳細介紹每個外設的特性及封裝思路,並且在各種平台上進行驗證。本篇介紹智能家居領域總是少不了的一款傳感器——溫濕度傳感器

買買買:
有些朋友建議我“你講軟件我們能夠下載找到,你講硬件我們很難找到,如果方便給個鏈接吧”。因此今后我會在必要的地方插入如何購買這些元件的鏈接(不是廣告植入哦!)。對於該款DHT11傳感器只要在淘寶上輸入關鍵詞,便可搜到一片(我建議大家買那些銷量比較高的,如果您不想跟風的話,可以深入了解下所給的資料等是否齊全)。不過目前我不建議大家盲目地買過來,今后我會針對具體的小應用給大家一些采購方案~
傳感器資料:
datasheet:http://akizukidenshi.com/download/ds/aosong/DHT11.pdf
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 持續更新中~
