|
前言:手里有个DHT11的温湿度传感器,三根脚,GND、VCC和DATA。DATA脚接一个IO即可按照芯片输出数据格式进行取数操作,接下来参考万能的网络参考一下大师兄的代码适配咱的ESP32-C3。
开发环境:VSCode+IDF+OLED+SSD1306+DHT11
在工程中的component目录下新增DHT11.c文件,同目录下include下增加DHT11.h文件,具体DHT11.c如下所示。
#include "esp_log.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "DHT11.h"
static void InputInitial(void)//设置端口为输入
{
gpio_pad_select_gpio(DHT11_PIN);
gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT);
}
static void OutputHigh(void)//输出1
{
gpio_pad_select_gpio(DHT11_PIN);
gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DHT11_PIN, 1);
}
static void OutputLow(void)//输出0
{
gpio_pad_select_gpio(DHT11_PIN);
gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DHT11_PIN, 0);
}
static uint8 getData()//读取状态
{
return gpio_get_level(DHT11_PIN);
}
//读取一个字节数据
static void COM(void) // 温湿写入
{
uchar i;
for(i=0;i<8;i++)
{
ucharFLAG=2;
//等待IO口变低,变低后,通过延时去判断是0还是1
while((getData()==0)&&ucharFLAG++) ets_delay_us(10);
ets_delay_us(35);//延时35us
uchartemp=0;
//如果这个位是1,35us后,还是1,否则为0
if(getData()==1)
uchartemp=1;
ucharFLAG=2;
//等待IO口变高,变高后,表示可以读取下一位
while((getData()==1)&&ucharFLAG++)
ets_delay_us(10);
if(ucharFLAG==1)
break;
ucharcomdata<<=1;
ucharcomdata|=uchartemp;
}
}
void Delay_ms(uint16 ms)
{
int i=0;
for(i=0; i<ms; i++){
ets_delay_us(1000);
}
}
void DHT11_get(void) //温湿传感启动
{
OutputLow();
Delay_ms(19); //>18MS
OutputHigh();
InputInitial(); //输入
ets_delay_us(30);
if(!getData())//表示传感器拉低总线
{
ucharFLAG=2;
//等待总线被传感器拉高
while((!getData())&&ucharFLAG++)
ets_delay_us(10);
ucharFLAG=2;
//等待总线被传感器拉低
while((getData())&&ucharFLAG++)
ets_delay_us(10);
COM();//读取第1字节,
ucharRH_data_H_temp=ucharcomdata;
COM();//读取第2字节,
ucharRH_data_L_temp=ucharcomdata;
COM();//读取第3字节,
ucharT_data_H_temp=ucharcomdata;
COM();//读取第4字节,
ucharT_data_L_temp=ucharcomdata;
COM();//读取第5字节,
ucharcheckdata_temp=ucharcomdata;
OutputHigh();
//判断校验和是否一致
uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);
if(uchartemp==ucharcheckdata_temp)
{
//校验和一致,
ucharRH_data_H=ucharRH_data_H_temp;
ucharRH_data_L=ucharRH_data_L_temp;
ucharT_data_H=ucharT_data_H_temp;
ucharT_data_L=ucharT_data_L_temp;
ucharcheckdata=ucharcheckdata_temp;
//保存温度和湿度
Humi=ucharRH_data_H;
Humi_small=ucharRH_data_L;
Temp=ucharT_data_H;
Temp_small=ucharT_data_L;
}
else
{
Humi=100;
Temp=100;
}
}
else //没用成功读取,返回0
{
Humi=0,
Temp=0;
}
OutputHigh(); //输出
}
DHT11.h文件代码如下所示:
#ifndef DHT11_h
#define DHT11_h
#include <sys/types.h>
#include "driver/gpio.h"
#include "string.h"
#define DHT11_PIN 4//定义DHT11的引脚
#define uchar unsigned char
#define uint8 unsigned char
#define uint16 unsigned short
//温湿度定义
uchar ucharFLAG,uchartemp;
uchar Humi,Humi_small,Temp,Temp_small;
uchar ucharT_data_H,ucharT_data_L,ucharRH_data_H,ucharRH_data_L,ucharcheckdata;
uchar ucharT_data_H_temp,ucharT_data_L_temp,ucharRH_data_H_temp,ucharRH_data_L_temp,ucharcheckdata_temp;
uchar ucharcomdata;
void DHT11_get(void); //温湿传感启动
#endif
i2c_example_main.c文件最终代码如下所示:
/* SSD1306 Example
See README.md file to get detailed usage of this example.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "sdkconfig.h"
#include "OLEDDisplay.h"
#include "DHT11.h"
static const char *TAG = "oled-example";
#define _I2C_NUMBER(num) I2C_NUM_##num
#define I2C_NUMBER(num) _I2C_NUMBER(num)
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< gpio number for I2C master data */
#define I2C_MASTER_NUM I2C_NUMBER(CONFIG_I2C_MASTER_PORT_NUM) /*!< I2C port number for master dev */
SemaphoreHandle_t print_mux = NULL;
static void i2c_test_task(void *arg)
{
char temp[16]={0};
char humi[16]={0};
OLEDDisplay_t *oled = OLEDDisplay_init(I2C_MASTER_NUM,0x78,I2C_MASTER_SDA_IO,I2C_MASTER_SCL_IO);
// OLEDDisplay_fillRect(oled,7,7,18,18);
// OLEDDisplay_drawRect(oled,6,32,20,20);
// OLEDDisplay_display(oled);
// vTaskDelay(500 / portTICK_PERIOD_MS);
while(1) {
DHT11_get(); //读取温湿度
printf("Temp=%d.%d℃--Humi=%d.%d%%RH \r\n", Temp,Temp_small,Humi,Humi_small);
sprintf(temp,"%d.%d",Temp,Temp_small);
sprintf(humi,"%d.%d",Humi,Humi_small);
OLEDDisplay_clear(oled);
OLEDDisplay_setFont(oled,ArialMT_Plain_16);
OLEDDisplay_drawString(oled,16, 00, "DHT11 TEST");
OLEDDisplay_display(oled);
// vTaskDelay(500 / portTICK_PERIOD_MS);
OLEDDisplay_setFont(oled,ArialMT_Plain_10);
OLEDDisplay_drawString(oled,16, 25, "Temp:");
OLEDDisplay_display(oled);
// vTaskDelay(500 / portTICK_PERIOD_MS);
OLEDDisplay_setFont(oled,ArialMT_Plain_10);
OLEDDisplay_drawString(oled,16,36, "Humi:");
OLEDDisplay_display(oled);
OLEDDisplay_setFont(oled,ArialMT_Plain_10);
OLEDDisplay_drawString(oled,60, 25, temp);
OLEDDisplay_display(oled);
// vTaskDelay(500 / portTICK_PERIOD_MS);
OLEDDisplay_setFont(oled,ArialMT_Plain_10);
OLEDDisplay_drawString(oled,60,36, humi);
OLEDDisplay_display(oled);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vSemaphoreDelete(print_mux);
vTaskDelete(NULL);
}
void app_main(void)
{
print_mux = xSemaphoreCreateMutex();
ESP_LOGI(TAG,"Running");
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void *)0, 10, NULL);
}
具体代码路径如图所示。
修改component目录下的CMakeLists.txt文件,增加DHT11.c的编译项,如图所示。
编译下载就可以了,不会编译的看上一篇或者上上篇啊。
开始想只刷新数据变更位置,其实这样最好。目前是全屏清除,重新显示,对OLED的刷新原理也不太深入,是一直保存好,还是定时刷界面好,有兴趣的可以尝试只刷新数据变化的位置。