农产品网站的品牌建设,网站建设意见建议,seo门户网站,天元建设集团有限公司鹿腾基于Freertos的ESP-IDF开发——6.使用DHT1温湿度传感器 0. 前言1. DHT11驱动原理2. 完整代码3. 演示效果4. 其他FreeRtos文章 0. 前言
开发环境#xff1a;ESP-IDF 4.3 操作系统#xff1a;Windows10 专业版 开发板#xff1a;自制的ESP32-WROOM-32E 准备一个DHT11温湿度传… 基于Freertos的ESP-IDF开发——6.使用DHT1温湿度传感器 0. 前言1. DHT11驱动原理2. 完整代码3. 演示效果4. 其他FreeRtos文章 0. 前言
开发环境ESP-IDF 4.3 操作系统Windows10 专业版 开发板自制的ESP32-WROOM-32E 准备一个DHT11温湿度传感器
DHT11是比较经典的入门级温湿度传感器这节我们学习使用它来测得周边环境的温湿度数据。
1. DHT11驱动原理 其控制时序如下
主机发送起始信号主机将总线拉低至少18ms然后拉高20-40us等待DHT11响应。DHT11响应信号DHT11在收到起始信号后会将总线拉低80us然后拉高80us表示已经准备好发送数据。DHT11发送数据DHT11会依次发送40位数据每一位数据的时间长度为50us高电平表示1低电平表示0。主机接收数据主机在接收到每一位数据后会等待50us然后再接收下一位数据。数据校验DHT11发送完40位数据后会再次将总线拉低50us然后拉高80us表示数据已经发送完毕。主机接收到数据后需要进行校验确保数据的正确性。通信结束主机在接收到数据后需要将总线拉高至少40us表示通信结束。
需要注意的是DHT11的控制时序非常严格如果时序不正确可能会导致数据传输失败。因此在使用DHT11时需要仔细按照时序进行控制。
首先我们将引脚设置为输出模式并将其拉低20毫秒然后将其拉高最后将其设置为输入模式。
然后我们等待DHT11的响应信号并开始读取数据。
我们使用FreeRTOS的计时器来计算每个位的持续时间并将其转换为0或1的位。
2. 完整代码
#include string.h
#include freertos/FreeRTOS.h
#include freertos/task.h
#include nvs_flash.h
#include driver/rmt.h
#include soc/rmt_reg.h
#include driver/gpio.h
#include esp_log.h#define DHT11_GPIO 26 // DHT11引脚定义
const static char *TAG DHT11_Demo;// 温度是10倍/10有1位小数
int temp_x10 123;
int humidity 60;
const int channel 0;uint8_t DHT11_PIN -1;
// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_item32_t *item, int item_num, int *humidity, int *temp_x10);// DHT11 初始化
void DHT11_Init(uint8_t dht11_pin)
{DHT11_PIN dht11_pin;const int RMT_CLK_DIV 80; // RMT计数器时钟分频器const int RMT_TICK_10_US (80000000 / RMT_CLK_DIV / 100000); // RMT计数器10us.(时钟源是APB时钟)const int rmt_item32_tIMEOUT_US 1000; // RMT接收超时usrmt_config_t rmt_rx {.gpio_num dht11_pin,.channel channel,.clk_div RMT_CLK_DIV,.mem_block_num 1,.rmt_mode RMT_MODE_RX, // 接收模式.rx_config.filter_en false,.rx_config.filter_ticks_thresh 100,.rx_config.idle_threshold rmt_item32_tIMEOUT_US / 10 * (RMT_TICK_10_US),};rmt_config(rmt_rx);rmt_driver_install(rmt_rx.channel, 1000, 0); // 安装驱动//rmt_driver_uninstall(rmt_rx.channel) // 卸载驱动
}// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_item32_t *item, int item_num, int *humidity, int *temp_x10)
{int i 0;unsigned rh 0, temp 0, checksum 0;if (item_num 42){ // 检查是否有足够的脉冲数ESP_LOGI(TAG, item_num 42 %d,item_num);return 0;}item; // 跳过开始信号脉冲for (i 0; i 16; i, item){ // 提取湿度数据rh (rh 1) (item-duration1 35 ? 0 : 1);}for (i 0; i 16; i, item){ // 提取温度数据temp (temp 1) (item-duration1 35 ? 0 : 1);}for (i 0; i 8; i, item){ // 提取校验数据checksum (checksum 1) (item-duration1 35 ? 0 : 1);}// 检查校验if ((((temp 8) temp (rh 8) rh) 0xFF) ! checksum){ESP_LOGI(TAG, Checksum failure %4X %4X %2X\n, temp, rh, checksum);return 0;}// 返回数据*humidity rh 8;*temp_x10 (temp 8) * 10 (temp 0xFF);return 1;
}// 使用RMT接收DHT11数据
int DHT11_StartGet(int *temp_x10, int *humidity)
{RingbufHandle_t rb NULL;size_t rx_size 0;rmt_item32_t *item;int rtn 0;//获得RMT RX环形缓冲区句柄并处理RX数据rmt_get_ringbuf_handle(channel, rb);if (!rb){return 0;}//发送20ms脉冲启动DHT11单总线gpio_set_level(DHT11_PIN, 1);gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);ets_delay_us(1000);gpio_set_level(DHT11_PIN, 0);ets_delay_us(20000);//将rmt_rx_start和rmt_rx_stop放入缓存rmt_rx_start(channel, 1);rmt_rx_stop(channel);//信号线设置为输入准备接收数据gpio_set_level(DHT11_PIN, 1);gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT);//这次启动RMT接收器以获取数据rmt_rx_start(channel, 1);//从环形缓冲区中取出数据item (rmt_item32_t *)xRingbufferReceive(rb, rx_size, 2);if (item ! NULL){int n;n rx_size / 4 - 0;// 解析来自ringbuffer的数据值.rtn parse_items(item, n, humidity, temp_x10);// 解析数据后将空格返回到ringbuffer.vRingbufferReturnItem(rb, (void *)item);}//停止RMT接收rmt_rx_stop(channel);return rtn;
}// 温度 湿度变量
int temp 0,hum 0;// 主函数
void app_main(void)
{ESP_ERROR_CHECK(nvs_flash_init());vTaskDelay(100 / portTICK_PERIOD_MS);ESP_LOGI(TAG, [APP] APP Is Start!~\r\n);ESP_LOGI(TAG, [APP] IDF Version is %d.%d.%d,ESP_IDF_VERSION_MAJOR,ESP_IDF_VERSION_MINOR,ESP_IDF_VERSION_PATCH);ESP_LOGI(TAG, [APP] Free memory: %d bytes, esp_get_free_heap_size());ESP_LOGI(TAG, [APP] IDF version: %s, esp_get_idf_version());DHT11_Init(DHT11_GPIO);while (1){if (DHT11_StartGet(temp, hum)){ESP_LOGI(TAG, [%lld] temp-%i.%i C hum-%i%%, esp_timer_get_time(), temp / 10, temp % 10, hum);}vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
3. 演示效果
如图所示这是我把它放在了我的电脑排风口附近测得的温度
4. 其他FreeRtos文章
基于Freertos的ESP-IDF开发——0.Windows下espidf的环境搭建 基于Freertos的ESP-IDF开发——1.HelloWorld 基于Freertos的ESP-IDF开发——2.点亮一颗LED 基于Freertos的ESP-IDF开发——3.使用任务上 基于Freertos的ESP-IDF开发——3.使用任务中 基于Freertos的ESP-IDF开发——3.使用任务下 基于Freertos的ESP-IDF开发——4.使用任务的方式来点亮LED灯 基于Freertos的ESP-IDF开发——5.使用按键[不带消抖、带消抖、长按短按识别]