本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949
配套资料获取:https://renesas-docs.100ask.net
瑞萨MCU零基础入门系列教程汇总: https://blog.csdn.net/qq_35181236/article/details/132779862
DHT11是一款可测量温度和湿度的传感器。比如市面上一些空气加湿器,会测量空气中湿度,再根据测量结果决定是否继续加湿。
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,具有超小体积、极低功耗的特点,使用单根总线与主机进行双向的串行数据传输。DHT11测量温度的精度为±2℃,检测范围为-20℃-60℃。湿度的精度为±5%RH,检测范围为5%RH-95%RH,常用于对精度和实时性要求不高的温湿度测量场合。
主机通过一条数据线与DH11连接,主机通过这条线发命令给DHT11,DHT11再通过这条线把数据发送给主机。
主控发出开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,并送出40bit的数据,完成一次信号采集。DHT11接收到开始信号后触发一次温湿度采集,如果没有开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。
通讯过程如图所示:
主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
和DS18B20非常相似,DHT11也是一个单总线设备。对于时延函数的精度也达到微秒级,因而配置和DS18B20基本一致。DHT11使用的GPIO是P503。
和DS18B20的IO驱动一模一样,参考《32.4.1 IO驱动》。
和DS18B20的GPT驱动一模一样,参考《32.4.2 定时器驱动》。
要操作DHT11,只需要对它进行初始化、然后读取数值。抽象出如下结构体:
typedef struct DHT11Dev{
unsigned int tempture;
unsigned int humidity;
int (*Init)(struct DHT11Dev *ptdev);
int (*Read)(struct DHT11Dev *ptdev);
}DHT11Device;
在drv_dht11.c中实现了一个DTH11Dev结构体,代码如下:
static struct DHT11Dev gDevice = {
.tempture = 0,
.humidity = 0,
.Init = DHT11DevInit,
.Read = DHT11DevRead
};
最后需要向上层应用提供获取DHT11设备的接口:
struct DHT11Dev *DHT11GetDevice(void)
{
return &gDevice;
}
初始化DHT11即初始化IO:
static int DHT11DevInit(struct DHT11Dev *ptdev)
{
if(NULL == ptdev) return -EINVAL;
gDataDevice = IODeviceFind("DHT11 IO");
if(NULL == gDataDevice)
{
printf("Failed to find DHT11 IO!\r\n");
return -ENXIO;
}
if(ESUCCESS != gDataDevice->Init(gDataDevice))
{
printf("Failed to init GPIO!\r\n");
return -EIO;
}
return ESUCCESS;
}
DHT11的数据读取不像DS18B20那样需要发送指令,它完全依靠总线的时延特征来区分信号和数据:
static int DHT11DevRead(struct DHT11Dev *ptdev)
{
if(NULL == ptdev) return -EINVAL;
unsigned int timeout = 100;
static long long tmp = 0;
unsigned int tempture_data_inter = 0, tempture_data_dec = 0;
unsigned int humidity_data_inter = 0, humidity_data_dec = 0;
unsigned char crc_data = 0;
tmp = 0;
// 主机拉低最少18ms
gDataDevice->Write(gDataDevice, 0);
mdelay(20);
// 拉高等待DHT11响应,20-40us
gDataDevice->Write(gDataDevice, 1);
udelay(30);
gDataDevice->Read(gDataDevice);
while((gDataDevice->value==1) && (timeout!=0))
{
gDataDevice->Read(gDataDevice);
udelay(1);
timeout--;
}
……………..(省略,读者自行阅读配套代码原文)
// 响应DHT11拉低总线80us后再拉高总线80us
if(crc_data==(tempture_data_inter + humidity_data_inter + tempture_data_dec + humidity_data_dec))
{
ptdev->tempture = tempture_data_inter;
ptdev->humidity = humidity_data_inter;
return ESUCCESS;
}
return -EIO;
}
获取到DHT11设备且初始化后,即可开始读取数据。本次实验每隔1s读取一次,并将结果打印出来:
void DeviceTest(void)
{
UartDevicesRegister();
TimerDevicesRegister();
IODevicesRegister();
DHT11Device *pDevice = DHT11GetDevice();
if(NULL == pDevice)
{
printf("Error. There is no DHT11 device!\r\n");
return;
}
pDevice->Init(pDevice);
printf("\r\n");
while(1)
{
if(pDevice->Read(pDevice) == ESUCCESS)
{
printf("环境温度:%d℃ \t 环境湿度:%d℃ \r", pDevice->tempture, pDevice->humidity);
}
delay(1);
}
}
将程序烧录到开发板运行,可以观察到如下结果: