文章目录[隐藏]
目的:
通过温湿度的代码编写,熟悉树莓派中的单总线操作流程。
目录
1、基础知识
1.1、DHT11数字温湿度传感器简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。
温湿度传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。
DHT11采用单线制串行接口,信号传输距离可达20米以上,可以用于空调、汽车、气象站等领域。
型号 |
测量范围 |
测湿精度 |
测温精度 |
分辨力 |
封装 |
DHT11 |
20-90%RH 0-50℃ |
±5%RH |
±2℃ |
1 |
4 针单排直插 |
1.2、DHT11单总线通信协议定义
DHT11中的DATA引脚用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零。操作流程如下:
- 一次完整的数据传输为40bit,高位先出。
- 数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和。
- 数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。
图 1-2-1 时序图
读取温湿度步骤如下所示:
步骤一:
DHT11上电后(DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时DHT11的DATA引脚处于输入状态,时刻检测外部信号。
步骤二:
微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的DATA数据线也随之变高,等待DHT11作出回答信号。发送信号如图1-2-2所示:
图1-2-2 主机发送起始信号
步骤三:
DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)后,等待87微秒的高电平后的数据接收,发送信号如图1-2-3所示:
图1-2-3 从机响应信号
步骤四:
由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据“0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低电平加68-74微秒的高电平。位数据“0”、“1”格式信号如图1-2-4所示:
图1-2-4 数据位
结束信号:
DHT11的DATA引脚输出40位数据后,继续输出低电平54微秒后转为输入状态,由于上拉电阻随之变为高电平。但DHT11内部重测环境温湿度数据,并记录数据,等待外部信号的到来。
2、功能实现
通过阅读DHT11数据手册,编写温湿度单总线程序,并在终端上打印出当前的温湿度数据。
2.1、原理图
图2-1-1 温湿度原理图
通过接线,接在GPIO28引脚上。
2.2、代码实现
2.2.1、头文件
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2.2.2、宏定义
#define GPIOPIN 28 //
//设置继电器引脚为输出引脚
#define DHT11_OUT pinMode(GPIOPIN, OUTPUT)
#define DHT11_IN pinMode(GPIOPIN, INPUT)
#define u8 unsigned char
2.2.3、DHT11初始化函数
int dht11_init(void)
{
unsigned int t=0;
//第一步:拉低20ms
DHT11_OUT;
digitalWrite(GPIOPIN, LOW);
delay(20); //延时20毫秒
digitalWrite(GPIOPIN, HIGH);
delayMicroseconds(30); //延时30微妙
DHT11_IN;
//第二步:等待拉低
while ((digitalRead(GPIOPIN) == HIGH)&&(t<1000))
{
t++;
delayMicroseconds(1);
}
if(t == 1000)
{
printf("1.拉低错误了\r\n");
return -1;
}
t = 0;
//第三步:等待拉高
while ((digitalRead(GPIOPIN) == LOW)&&(t<1000))
{
t++;
delayMicroseconds(1);
}
if(t == 1000)
{
printf("2.拉高错误了\r\n");
return -1;
}
t = 0;
//第四步:等待拉低,开始读数据
while ((digitalRead(GPIOPIN) == HIGH)&&(t<1000))
{
t++;
delayMicroseconds(1);
}
if(t == 1000)
{
printf("3.拉低错误了\r\n");
return -1;
}
t = 0;
dht11_read();
return 0;
}
2.2.4、DHT11读取一个字节数据
u8 dht11_read_byte(void)
{
u8 reader,j,t;
t=0;
reader = 0;
DHT11_IN;
for(j=0;j<8;j++)
{
reader = reader <<1;
//第四步:等待拉高
while ((digitalRead(GPIOPIN) == LOW)&&(t<1000))
{
t++;
delayMicroseconds(1);
}
if(t == 1000)
{
printf("4.拉高错误了\r\n");
return -1;
}
t = 0;
delayMicroseconds(50);
if(digitalRead(GPIOPIN) == HIGH)
reader |= 0x01;
//第五步:等待拉高
while ((digitalRead(GPIOPIN) == HIGH)&&(t<1000))
{
t++;
delayMicroseconds(1);
}
if(t == 1000)
{
printf("5.等待拉低错误\r\n");
return -1;
}
t = 0;
}
return reader;
}
2.2.5、读DHT11取温湿度
void dht11_read(void)
{
u8 data[5];
u8 j=0;
memset(data,0,4);
for(j=0;j<5;j++)
{
data[j] = dht11_read_byte();
}
if(data[4] == (data[0]+data[1]+data[2]+data[3]))
{
printf("H:%d.%d,T:%d.%d\n",data[0],data[1],data[2],data[3]);
}
else
{
printf("read error\r\n");
}
return;
}
2.2.6、主程序
int main(void)
{
int ret;
//第一步: 初始化wiringPi
ret = wiringPiSetup(); //编号为0 ,需要在root权限下才能执行
if(ret == -1)
{
printf("wiringPiSetup is error\r\n");
return ret;
}
while(1)
{
dht11_init();
delay(4000); //读取间隔至少2S中
}
return 0;
}
2.3、生成执行程序
编译的时候需要添加wiringPi库,编译步骤如下所示:
gcc -Wall -o dht11 dht11.c -lwiringPi
图2-3-1 编译过程
2.4、功能实现
执行程序
./dht11
图2-4-1 温湿度数据
版权声明:本文为CSDN博主「冷静的领头狼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZOROE123/article/details/122607893
暂无评论