【1】DHT11傳感器
DHT11是一種數(shù)字溫濕度傳感器,能夠通過數(shù)字信號(hào)輸出當(dāng)前環(huán)境的溫度和濕度值。DHT11可以通過一條數(shù)據(jù)信號(hào)線連接到微控制器或其他外設(shè),從而實(shí)現(xiàn)溫濕度的實(shí)時(shí)測(cè)量和數(shù)據(jù)讀取。
DHT11采用單總線通信協(xié)議,只需要連接一個(gè)數(shù)字信號(hào)線和兩個(gè)電源線,即可實(shí)現(xiàn)傳感器的數(shù)據(jù)讀取。傳感器本身具有一定的溫度和濕度校準(zhǔn)能力,因此輸出的數(shù)據(jù)比較可靠。
DHT11傳感器的測(cè)量范圍為0~50°C的溫度和20%~90%的相對(duì)濕度,測(cè)量精度為±2°C和±5%RH。
【2】通信協(xié)議
DHT11采用單總線通信協(xié)議,使用一條數(shù)據(jù)信號(hào)線來傳輸數(shù)據(jù),其中包括起始信號(hào)、數(shù)據(jù)位和校驗(yàn)位。通信協(xié)議如下:
- 主機(jī)發(fā)送一個(gè)開始信號(hào)給DHT11,即將數(shù)據(jù)信號(hào)線拉低至少18ms以上。
- 主機(jī)發(fā)出啟動(dòng)信號(hào)之后,拉低數(shù)據(jù)線至少80us,在這個(gè)過程中,DHT11將會(huì)檢測(cè)到主機(jī)發(fā)送的啟動(dòng)信號(hào),并做出回應(yīng)。
- DHT11響應(yīng)主機(jī)發(fā)出的啟動(dòng)信號(hào)后,會(huì)拉高數(shù)據(jù)信號(hào)線至少80us,表示傳輸數(shù)據(jù)前的“準(zhǔn)備工作”已經(jīng)完成。
-
DHT11開始向主機(jī)發(fā)送數(shù)據(jù),每個(gè)數(shù)據(jù)包包含40個(gè)位,高位先傳輸。在數(shù)據(jù)傳輸?shù)倪^程中,DHT11會(huì)將數(shù)據(jù)信號(hào)線從低電平轉(zhuǎn)換為高電平,表示1的開始,持續(xù)時(shí)間26
28us,然后將數(shù)據(jù)線拉低,表示0的開始,持續(xù)時(shí)間70us。 - 在發(fā)送完40位數(shù)據(jù)后,DHT11會(huì)發(fā)送一個(gè)校驗(yàn)位。校驗(yàn)位的計(jì)算方法是將前四個(gè)字節(jié)數(shù)據(jù)相加,求出一個(gè)8位校驗(yàn)碼,將此校驗(yàn)碼與第五個(gè)字節(jié)進(jìn)行比較,如果相等,則數(shù)據(jù)傳輸成功,否則需要重傳數(shù)據(jù)。
- 主機(jī)接收到數(shù)據(jù)后,需要將數(shù)據(jù)信號(hào)線拉高,以結(jié)束傳輸。
【3】讀取DHT11溫濕度數(shù)據(jù)
以下是一個(gè)讀取DHT11傳感器的溫度和濕度示例代碼:
Copy Code#include "stm32f10x.h"
#include "dht11.h"
?
#define DHT11_GPIO_PORT GPIOB
#define DHT11_GPIO_PIN GPIO_Pin_12
?
void delay_us(uint32_t us)
{
us *= (SystemCoreClock / 1000000) / 5;
while (--us);
}
?
void dht11_start(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
?
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
?
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
?
/* 發(fā)送開始信號(hào) */
GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);
delay_us(18000);
?
GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);
delay_us(40);
?
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
?
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
?
uint16_t dht11_read_bit(void)
{
uint16_t retry = 0;
?
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) {
retry++;
if (retry > 1000) {
return 0;
}
delay_us(1);
}
?
retry = 0;
?
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET) {
retry++;
if (retry > 1000) {
return 0;
}
delay_us(1);
}
?
if (retry < 30) {
? ? ? ? ?return 0;
? ? } else {
? ? ? ? ?return 1;
? ? }
?}
??
?uint8_t dht11_read_byte(void)
?{
? ? ?uint8_t i;
? ? ?uint8_t data = 0;
??
? ? ?for (i = 0; i < 8; i++) {
? ? ? ? ?data <<= 1;
? ? ? ? ?if (dht11_read_bit()) {
? ? ? ? ? ? ?data |= 0x01;
? ? ? ? }
? ? }
??
? ? ?return data;
?}
??
?uint8_t dht11_read_data(dht11_data_t *data)
?{
? ? ?uint8_t i;
? ? ?uint8_t buf[5];
? ? ?uint8_t checksum = 0;
??
? ? ?dht11_start();
??
? ? ?if (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) {
? ? ? ? ?/* 等待DHT11響應(yīng) */
? ? ? ? ?while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET);
??
? ? ? ? ?/* 等待DHT11發(fā)射數(shù)據(jù) */
? ? ? ? ?while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET);
??
? ? ? ? ?/* 接收數(shù)據(jù) */
? ? ? ? ?for (i = 0; i < 5; i++) {
? ? ? ? ? ? ?buf[i] = dht11_read_byte();
? ? ? ? }
??
? ? ? ? ?/* 校驗(yàn)和 */
? ? ? ? ?checksum = buf[0] + buf[1] + buf[2] + buf[3];
??
? ? ? ? ?if (checksum == buf[4]) {
? ? ? ? ? ? ?data->humidity = buf[0];
data->temperature = buf[2];
return 1;
}
}
?
return 0;
}
?
int main(void)
{
dht11_data_t data;
?
GPIO_InitTypeDef GPIO_InitStruct;
?
/* 使能GPIOB時(shí)鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
?
/* 配置DHT11引腳為輸入模式 */
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
?
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
?
while (1) {
if (dht11_read_data(&data)) {
printf("Temperature: %d°C Humidity: %d%%n", data.temperature, data.humidity);
} else {
printf("Error reading data from DHT11.n");
}
delay_us(2000000);
}
}
在這個(gè)示例代碼中,首先定義了一個(gè)dht11_data_t結(jié)構(gòu)體,用于保存讀取的溫度和濕度數(shù)據(jù)。然后,編寫了一些函數(shù)來執(zhí)行DHT11讀取操作。
delay_us()函數(shù)是一個(gè)簡(jiǎn)單的延遲函數(shù),用于等待一定量的時(shí)間。需要精確地計(jì)算一個(gè)微秒的延遲,并在循環(huán)中使用該延遲來等待一段時(shí)間。
dht11_start()函數(shù)用于發(fā)送DHT11的開始信號(hào)。將DHT11引腳配置為輸出模式,并發(fā)送18毫秒的低電平信號(hào),然后再發(fā)送40微秒的高電平信號(hào)。
dht11_read_bit()函數(shù)用于讀取DHT11傳輸?shù)臄?shù)據(jù)位。等待DHT11輸出信號(hào)的變化,并根據(jù)變化的時(shí)間來判斷數(shù)據(jù)位的值。如果一個(gè)數(shù)據(jù)位的響應(yīng)時(shí)間小于30微秒,則被判定為0,否則為1。
dht11_read_byte()函數(shù)用于讀取一個(gè)字節(jié)的數(shù)據(jù)(8個(gè)數(shù)據(jù)位)。通過調(diào)用dht11_read_bit()函數(shù)8次來讀取每個(gè)數(shù)據(jù)位,并將結(jié)果組合成一個(gè)字節(jié)。
dht11_read_data()函數(shù)用于讀取整個(gè)DHT11數(shù)據(jù)包,包括溫度、濕度和校驗(yàn)和。首先調(diào)用dht11_start()函數(shù)發(fā)送開始信號(hào),然后等待DHT11發(fā)送數(shù)據(jù)。使用dht11_read_byte()函數(shù)讀取5個(gè)字節(jié)的數(shù)據(jù),并驗(yàn)證校驗(yàn)和以確保數(shù)據(jù)完整和正確。
最后,在main()函數(shù)中,初始化GPIO口和DHT11傳感器,并執(zhí)行一個(gè)循環(huán)來讀取數(shù)據(jù)。如果讀取成功,則將溫度和濕度打印到串口終端上,否則輸出錯(cuò)誤信息。
審核編輯:湯梓紅
-
傳感器
+關(guān)注
關(guān)注
2576文章
54837瀏覽量
789436 -
單片機(jī)
+關(guān)注
關(guān)注
6074文章
45464瀏覽量
667442 -
通信協(xié)議
+關(guān)注
關(guān)注
28文章
1084瀏覽量
41961 -
STM32
+關(guān)注
關(guān)注
2308文章
11153瀏覽量
372560 -
DHT11
+關(guān)注
關(guān)注
19文章
277瀏覽量
59545
發(fā)布評(píng)論請(qǐng)先 登錄
數(shù)據(jù)安全優(yōu)先:以太網(wǎng)溫濕度監(jiān)測(cè)與追溯合規(guī)方案
【瑞薩RA6E2地奇星開發(fā)板試用】DHT11 測(cè)量溫濕度
宏集案例 | COMET無線溫濕度監(jiān)測(cè)系統(tǒng)助力文物展陳與長(zhǎng)期保存
溫濕度傳感器HTU31D在溫濕度控器中的應(yīng)用優(yōu)勢(shì)
如何對(duì)電能質(zhì)量在線監(jiān)測(cè)裝置進(jìn)行溫濕度環(huán)境適應(yīng)性測(cè)試?
基于LORA無線通訊的祥控多點(diǎn)式煙葉溫濕度監(jiān)測(cè)系統(tǒng)
基于物聯(lián)網(wǎng)的溫濕度監(jiān)測(cè)系統(tǒng)方案:構(gòu)建全域感知的智能環(huán)境網(wǎng)絡(luò)
一款適用于粉塵、易結(jié)露等惡劣環(huán)境溫濕度監(jiān)控中的溫濕度傳感芯片
基于物聯(lián)網(wǎng)的溫濕度監(jiān)測(cè)系統(tǒng)
常見的溫濕度傳感器類型?
溫濕度變送器功能有哪些?一文詳細(xì)解析
智能倉儲(chǔ):溫濕度監(jiān)控方案應(yīng)用
用樹莓派RP2350 DIY 桌面動(dòng)態(tài)溫濕度計(jì)
LoRa無線技術(shù)的溫濕度監(jiān)測(cè)預(yù)警系統(tǒng)
STM32+DHT11監(jiān)測(cè)環(huán)境的溫濕度
評(píng)論