一、項目需求

二、項目框圖
三、DHT11工作原理
參考于良許嵌入式手把手教你玩轉DHT11(原理+驅動) | 良許嵌入式
3.1 正常工作驗證 #??
上電后,「電源指示燈/POWER」紅燈亮,表示上電成功,正常工作。?
3.2 DHT11工作時序 #???
3.2.1 整體工作時序 #???
DHT11 整體工作時序為:主機發送開始信號、DHT11 響應輸出、主機接收 40bit 數據(濕度數據+溫度數據+校驗值),結束信號(可選)。
具體過程如下:?
1.? 總線空閑狀態為高電平,主機拉低總線等待 DHT11 響應, 主機把總線拉低必須大于 18ms,保證 DHT11 能檢測到起始信號;?
2.? 主機發送開始信號結束后,拉高總線電平并延時等待 20-40us 后,讀取 DHT11 的響應信號;??
3.? DHT11 接收到主機的開始信號后,等待微處理器開始信號結束,發送 80us 低電平響應信號;??
4.? DHT11 發送 80us 高電平準備發送數據;??
5.? DHT11 發送 40bit 數據(濕度數據+溫度數據+校驗值)。???
過程 主機 DHT11? 1 拉低>18ms?? 2 拉高20~40us?? 3?? 響應 80us 低電平? 4?? 拉高 80us? 5?? 發送 40bit 數據(濕度數據+溫度數據+校驗值)?
?
3.2.2 起始及響應信號 #???
總流程講完介紹一下細分流程: 首先主機拉低總線至少 18ms,然后再拉高總線,延時 20~40us,此時起始信號(有時也叫復位信號)發送完畢。?
DHT11 檢測到復位信號后,觸發一次采樣,并拉低總線 80us 表示響應信號,告訴主機數據已經準備好了。
DHT11 之后拉高總線 80us,然后開始傳輸數據。如果檢測到響應信號為高電平,則 DHT11 初始化失敗,請檢查線路是否連接正常。?
3.2.3 讀時序 #???
DHT11 開始傳輸數據。每 1bit 數據都以 50us 低電平開始,告訴主機開始傳輸一位數據了。DHT11 以高電平的長短定義數據位是 0 還是 1:
當 50us 低電平過后拉高總線,高電平持續 26~28us 表示 0,高電平持續 70us 表示數據 1。?
當最后 1bit 數據傳送完畢后,DHT11 拉低總線 50us,表示數據傳輸完畢,隨后總線由上拉電阻拉高進入空閑狀態。?
位數據0表示方式: 以 50us 低電平開始,高電平持續 26~28us 表示 0。
位數據1表示方式: 以 50us 低電平開始,高電平持續 70us 表示 1。?
3.3 DHT11數據格式 #??
DHT11 的 DATA 傳輸一次完整的數據為 40bit,按照高位在前,低位在后的順序傳輸。?
數據格式為:8bit 濕度整數數據 + 8bit 濕度小數數據 + 8bit 溫度整數數據 + 8bit 溫度小數數據 + 8bit 校驗位,
一共 5 字節(40bit)數據。 正常情況下,前四個字節的和剛好與校驗位相等,通過這種機制可以保證數據傳輸的準確性。
四、項目實現
復制項目文件19-串口打印
重命名59-DHT11
新建文件dht11
dht11.c
dht11.h
打開項目工程
加載文件
書寫頭文件
編譯
編程思路:
1、之前的模塊都需要init函數,而這里的dht11反倒不需要init函數,因為dht11只有一個data的IO口。DHT11的一個data口用于輸入和輸出,所以需要對DHT11的IO口做一個配置,則需要:dht11_gpio_input,dht11_gpio_output兩個函數。
2、接下來是DHT11的起始信號及響應信號需要:dht11_start
3、讀時序:dht11_read_byte
4、將讀出的數據,存儲下來,用指針(地址)承接:dht11_read
5、因為是單總線協議,所以先進行一個封裝
??????? 判斷1位數據,當IO口電平等于高電平的時候,延時50微妙,判斷當下是高電平還是低電平,如果是高電平,則傳出來的數據是1,否則就是0,
while(!DHT11_DQ_IN);
??????? delay_us(50);
??????? if(DHT11_DQ_IN == 1)
??????? {
??????????? temp = 1;
??????????? while(DHT11_DQ_IN);
??????? }
??????? else
??????????? temp = 0;
??????? 我們知道,一個字節有8位,所以這段代碼要執行八次,才是一位,定義一個UINT8_T的變量,這個變量有8位,將受到的一位字節存放在這個變量的像左移一位。
??? for(i=0; i<8; i++){
??????? while(!DHT11_DQ_IN);
??????? delay_us(50);
??????? if(DHT11_DQ_IN == 1)
??????? {
??????????? temp = 1;
??????????? while(DHT11_DQ_IN);
??????? }
??????? else
??????????? temp = 0;
??????? byte = byte << 1;
??????? byte |= temp;
??? }
上面這個函數,是用來返回發送過來的一個字節,DHT11會返回5個字節,所以上述操作,要執行5次,并且第五位是校驗位,前四位的和等于第五位時,才證明沒有發送錯數據,官方文檔要求,DH11不可以一直在返回數據,需要延長2s
??? for(i=0; i<5; i++)
??? {
??????? dht11_data[i] = dht11_read_byte();
??? }
??? if(dht11_data[0]+dht11_data[1]+dht11_data[2]+dht11_data[3] == dht11_data[4])
??? {
??????? memcpy(result,dht11_data,4);//將dht11_data中四個數據復制給result
??????? printf("濕度:%d.%dRH ,",dht11_data[0],dht11_data[1]);
??????? printf("溫度:%d.%d℃ \r\n",dht11_data[2],dht11_data[3]);
??? }
??? delay_ms(2000);
????????在esp8266中需要重寫esp8266_send_data函數,因為以前的esp8266_send_data函數是用來模仿printf,所以需要重寫函數,用來發送數據
//兩個參數分別是:要發送的數據,和要發送數據的長度
void esp8266_send_data(char *data,uint16_t len)
{
??? //清空發送緩沖區
??? esp8266_rx_clear();
??? //發送數據函數
??? HAL_UART_Transmit(&esp8266_handle,(unsigned char*)data,len,100);
}
在OneNet創建產品和設備
三元組很重要:產品id,設備id,密鑰
設備id的獲取,將設備導入出來,就會有一個表,其中有設備id
?將代碼中上面部分,按自己的東西改寫,