硬件連接:
MCU通過一條數據線與DH11連接,MCU通過這條線發命令給DH11,DH11再通過這條線把數據發送給MCU。

溫濕度模塊的核心就是 MCU發給DH11的命令格式和DH11返回的數據格式。
時序:

首先MCU發送一個開始信號S,這個開始信號是一個低脈沖,然后再拉高。等待DHT11應答。
然后,DH11拉低,做出一個響應信號,再拉高,准備發送數據。
接着就是DH11返回的數據。
這些數據一共有40bit,高位先出。(8bit濕度整數數據+8bit濕度小數數據+8bi溫度整數數據+8bit溫度小數數據+8bit校驗和)
數據有40bit: 8bit濕度整數數據+8bit濕度小數數據+8bit溫度整數數據+8bit溫度小數數據+8bit校驗和
時序要求:

MCU必須先拉低至少18ms,然后再拉高20-40us,DH11再拉低80us以響應,最后再拉高80us.
接下來就是傳輸數據:

Bit0:1bit 50us開始后,DHT11拉低數據時間為30us以內

Bit1:1bit 50us開始后,DHT11拉低數據時間為超過70us
代碼實現:
實現GPIO的基本操作:
GPG5,gpio配置如下:


static void dht11_data_cfg_as_output(void) { GPGCON &= ~(3<<10); GPGCON |= (1<<10); } static void dht11_data_cfg_as_input(void) { GPGCON &= ~(3<<10); } static void dht11_data_set(int val) { if (val) GPGDAT |= (1<<5); else GPGDAT &= ~(1<<5); } static int dht11_data_get(void) { if (GPGDAT & (1<<5)) return 1; else return 0; } DHT11操作: void dht11_init(void) { dht11_data_cfg_as_output(); dht11_data_set(1); mdelay(2000); } static void dht11_start(void) { dht11_data_set(0); mdelay(20); dht11_data_cfg_as_input(); } static int dht11_wait_ack(void) { udelay(60); return dht11_data_get(); } static int dht11_recv_byte(void) { int i; int data = 0; for (i = 0; i < 8; i++) { if (dht11_wait_for_val(1, 1000)) { printf("dht11 wait for high data err!\n\r"); return -1; } udelay(40); data <<= 1; if (dht11_data_get() == 1) data |= 1; if (dht11_wait_for_val(0, 1000)) { printf("dht11 wait for low data err!\n\r"); return -1; } } return data; } static int dht11_wait_for_val(int val, int timeout_us) { while (timeout_us--) { if (dht11_data_get() == val) return 0; /* ok */ udelay(1); } return -1; /* err */ } int dht11_read(int *hum, int *temp) { unsigned char hum_m, hum_n; unsigned char temp_m, temp_n; unsigned char check; dht11_start(); if (0 != dht11_wait_ack()) { printf("dht11 not ack, err!\n\r"); return -1; } if (0 != dht11_wait_for_val(1, 1000)) /* 等待ACK變為高電平, 超時時間是1000us */ { printf("dht11 wait for ack high err!\n\r"); return -1; } if (0 != dht11_wait_for_val(0, 1000)) /* 數據階段: 等待低電平, 超時時間是1000us */ { printf("dht11 wait for data low err!\n\r"); return -1; } hum_m = dht11_recv_byte(); hum_n = dht11_recv_byte(); temp_m = dht11_recv_byte(); temp_n = dht11_recv_byte(); check = dht11_recv_byte(); dht11_data_cfg_as_output(); dht11_data_set(1); if (hum_m + hum_n + temp_m + temp_n == check) { *hum = hum_m; *temp = temp_m; mdelay(2000); /* 讀取周期是2S, 不能讀太頻繁 */ return 0; } else { printf("dht11 checksum err!\n\r"); return -1; } } void dht11_test(void) { int hum, temp; dht11_init(); while (1) { if (dht11_read(&hum, &temp) !=0 ) { printf("\n\rdht11 read err!\n\r"); dht11_init(); } else { printf("\n\rDHT11 : %d humidity, %d temperature\n\r", hum, temp); } } }
