一、DHT22简介
1、DHT22介绍说明
DHT22数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、响应、抗干扰能力强、性价比极高寺优尽。才出12在1RTD伪E中,传感器内湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用区些T任系效。p给叫I可达20米以下,使成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
2、应用场景
暖通空调
测试及检测设备
汽车
数据记录器
消费品
自动控制
气象站
家电
湿度调节器
医疗
除湿器
3、精度
湿度范围:0~99%RH(精度为± 2),温度范围:-40 ~ 80度(± 0.5)。这个测量范围可以满足中国所有地域的环境温湿度检测了,DHT22相比DHT11测量范围更广,精度更高。值得推荐,但这东西就是贵了点。
4、引脚连接
采用的是单总线连接,MCU的引脚需要做输出也需要做输入,要根据情况而定。
二、时序分析
1、数据分析说明
上面的温度最高位表示温度是否低于0度,在代码中需要自己去判断,判断最高位是否为1
是0000 0010+1000 1100 = 652,小数点再往前一位所得到的值。
是0000 0001+0101 1111 = 351,小数点再往前一位所得到的值。
2、启动与响应
3、据位表示
DHT22的一位数据的表示均由高电平与低电平共同组成的,但是高电平的持续时间不同决定了是位1还是位0,如果高电平持续时间为26 ~ 28us表示位数据为0,如果高电平持续时间为70us表示位数据为1.
三、程序及验证
1、程序
dht22.c
#include "dht22.h"
/**********************************
引脚说明:
PB10 -- DQ
***********************************/
void Dht22_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //第9号引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增强驱动能力,引脚的输出电流更大
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //引脚的速度最大为100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使用内部上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
//温湿度模块还没有工作,那么它的触发引脚是高电平
PBout(10) = 1;
}
//引脚模式变更
void Dht22_Pin_Mode(GPIOMode_TypeDef mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //第9号引脚
GPIO_InitStructure.GPIO_Mode = mode; //输入/输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增强驱动能力,引脚的输出电流更大
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //引脚的速度最大为100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使用内部上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//启动DHT22正常返回0
int Dht22_Start(void)
{
u16 t = 0;
Dht22_Pin_Mode(GPIO_Mode_OUT);
//启动信号
PBout(10) = 1;
delay_ms(1);
PBout(10) = 0;
delay_ms(1);
PBout(10) = 1;
delay_us(30);
Dht22_Pin_Mode(GPIO_Mode_IN);
//等待低电平到来
while( PBin(10) == 1)
{
t++;
delay_us(10);
//等待2ms,如果未等待低电平,则返回
if(t >= 200)
return -1;
}
//延时一段时间
delay_us(40);
t = 0;
//等待高电平到来,过滤低电平
while( PBin(10) == 0)
{
t++;
delay_us(10);
//等待2ms,如果未等待高电平,则返回
if(t >= 200)
return -1;
}
//延时一段时间
delay_us(40);
t = 0;
//等待低电平到来 过滤高电平
while( PBin(10) == 1)
{
t++;
delay_us(10);
//等待2ms,如果未等待低电平,则返回
if(t >= 200)
return -1;
}
return 0;
}
//一次性读取八位数据合成一个字节
//高低先出, 数据:0x87 1(先出) 0 0 0 0 1 1 1
uint8_t Dht22_Read_Byte(void)
{
u8 i, t,data = 0x00; //0000 0000
for(i=0; i<8; i++)
{
t = 0;
//等待高电平到来,过滤低电平
while( PBin(10) == 0)
{
t++;
delay_us(2);
//等待100us,如果未等待高电平,则返回
if(t >= 40)
return 0;
//printf("here1\r\n");
}
//延时40us
delay_us(35);
//判断引脚电平
if(PBin(10) == 1)
{
//如果数据位为1,将数据存储到对应的位
data |= (1<<(7-i));
t = 0;
//等待低电平到来 过滤高电平
while( PBin(10) == 1)
{
t++;
delay_us(2);
//等待100us,如果未等待低电平,则返回
if(t >= 40)
return 0;
//printf("here2\r\n");
}
}
}
return data;
}
int Dht22_Read(u8 *data)
{
u8 i;
//连续获取数据
for(i=0; i<5; i++)
{
data[i] = Dht22_Read_Byte();
}
if(data[4] == (data[0]+data[1]+data[2]+data[3]))
{
return 0;
}
else
{
return -1;
}
}
main.c
int main(void)
{
u16 ret = 0;
u8 data[5] = {0};
u16 T_value = 0, H_value = 0;
float fT_value = 0, fH_value = 0;
//NVIC分组一个工程只能设置一次
//设置NVIC分组为第二分组; 抢占优先级取值范围:0~3, 响应优先级取值范围:0~3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
Usart1_Init(115200);
Dht22_Init();
delay_s(3);
while(1)
{
ret = Dht22_Start();
if(ret == 0)
{
//printf("ret = %d\r\n",ret);
ret = Dht22_Read(data);
if(ret == 0)
{
//printf("value:%d,%d,%d,%d\r\n", data[0], data[1],data[2], data[3]);
//计算温度与湿度
H_value = data[0]<<8|data[1];
T_value = data[2]<<8|data[3];
//判断最高位是否为1,由于我这边是南方,无法测量到低于0度,但我自信这个代码是对的
if(T_value & (0x01<<16))
{
//将湿度最高位变为0,其它位不变,因为最高位为温度的正负,没必须参与计算
T_value = T_value & 0x7FFF;
//之前计算的值是没有小数点,现在取余,补上小数点
fH_value = H_value/10.0;
fT_value = T_value/10.0;
printf("湿度:%0.1f\r\n", fH_value);
printf("温度:-%0.1f\r\n", fT_value);
}
else
{
//之前计算的值是没有小数点,现在取余,补上小数点
fH_value = H_value/10.0;
fT_value = T_value/10.0;
printf("湿度:%0.1f\r\n", fH_value);
printf("温度:%0.1f\r\n", fT_value);
}
}
}
//采集周期必须大于或等于2S
delay_s(2);
}
return 0;
}
验证
数据出来了,nice,小伙伴们,点点关注。
源码下载:https://download.csdn.net/download/wwwqqq2014/73811606
版权声明:本文为CSDN博主「C是最好的编程语言」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wwwqqq2014/article/details/122301787
一、DHT22简介
1、DHT22介绍说明
DHT22数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、响应、抗干扰能力强、性价比极高寺优尽。才出12在1RTD伪E中,传感器内湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用区些T任系效。p给叫I可达20米以下,使成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
2、应用场景
暖通空调
测试及检测设备
汽车
数据记录器
消费品
自动控制
气象站
家电
湿度调节器
医疗
除湿器
3、精度
湿度范围:0~99%RH(精度为± 2),温度范围:-40 ~ 80度(± 0.5)。这个测量范围可以满足中国所有地域的环境温湿度检测了,DHT22相比DHT11测量范围更广,精度更高。值得推荐,但这东西就是贵了点。
4、引脚连接
采用的是单总线连接,MCU的引脚需要做输出也需要做输入,要根据情况而定。
二、时序分析
1、数据分析说明
上面的温度最高位表示温度是否低于0度,在代码中需要自己去判断,判断最高位是否为1
是0000 0010+1000 1100 = 652,小数点再往前一位所得到的值。
是0000 0001+0101 1111 = 351,小数点再往前一位所得到的值。
2、启动与响应
3、据位表示
DHT22的一位数据的表示均由高电平与低电平共同组成的,但是高电平的持续时间不同决定了是位1还是位0,如果高电平持续时间为26 ~ 28us表示位数据为0,如果高电平持续时间为70us表示位数据为1.
三、程序及验证
1、程序
dht22.c
#include "dht22.h"
/**********************************
引脚说明:
PB10 -- DQ
***********************************/
void Dht22_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //第9号引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增强驱动能力,引脚的输出电流更大
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //引脚的速度最大为100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使用内部上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
//温湿度模块还没有工作,那么它的触发引脚是高电平
PBout(10) = 1;
}
//引脚模式变更
void Dht22_Pin_Mode(GPIOMode_TypeDef mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //第9号引脚
GPIO_InitStructure.GPIO_Mode = mode; //输入/输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增强驱动能力,引脚的输出电流更大
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //引脚的速度最大为100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使用内部上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//启动DHT22正常返回0
int Dht22_Start(void)
{
u16 t = 0;
Dht22_Pin_Mode(GPIO_Mode_OUT);
//启动信号
PBout(10) = 1;
delay_ms(1);
PBout(10) = 0;
delay_ms(1);
PBout(10) = 1;
delay_us(30);
Dht22_Pin_Mode(GPIO_Mode_IN);
//等待低电平到来
while( PBin(10) == 1)
{
t++;
delay_us(10);
//等待2ms,如果未等待低电平,则返回
if(t >= 200)
return -1;
}
//延时一段时间
delay_us(40);
t = 0;
//等待高电平到来,过滤低电平
while( PBin(10) == 0)
{
t++;
delay_us(10);
//等待2ms,如果未等待高电平,则返回
if(t >= 200)
return -1;
}
//延时一段时间
delay_us(40);
t = 0;
//等待低电平到来 过滤高电平
while( PBin(10) == 1)
{
t++;
delay_us(10);
//等待2ms,如果未等待低电平,则返回
if(t >= 200)
return -1;
}
return 0;
}
//一次性读取八位数据合成一个字节
//高低先出, 数据:0x87 1(先出) 0 0 0 0 1 1 1
uint8_t Dht22_Read_Byte(void)
{
u8 i, t,data = 0x00; //0000 0000
for(i=0; i<8; i++)
{
t = 0;
//等待高电平到来,过滤低电平
while( PBin(10) == 0)
{
t++;
delay_us(2);
//等待100us,如果未等待高电平,则返回
if(t >= 40)
return 0;
//printf("here1\r\n");
}
//延时40us
delay_us(35);
//判断引脚电平
if(PBin(10) == 1)
{
//如果数据位为1,将数据存储到对应的位
data |= (1<<(7-i));
t = 0;
//等待低电平到来 过滤高电平
while( PBin(10) == 1)
{
t++;
delay_us(2);
//等待100us,如果未等待低电平,则返回
if(t >= 40)
return 0;
//printf("here2\r\n");
}
}
}
return data;
}
int Dht22_Read(u8 *data)
{
u8 i;
//连续获取数据
for(i=0; i<5; i++)
{
data[i] = Dht22_Read_Byte();
}
if(data[4] == (data[0]+data[1]+data[2]+data[3]))
{
return 0;
}
else
{
return -1;
}
}
main.c
int main(void)
{
u16 ret = 0;
u8 data[5] = {0};
u16 T_value = 0, H_value = 0;
float fT_value = 0, fH_value = 0;
//NVIC分组一个工程只能设置一次
//设置NVIC分组为第二分组; 抢占优先级取值范围:0~3, 响应优先级取值范围:0~3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
Usart1_Init(115200);
Dht22_Init();
delay_s(3);
while(1)
{
ret = Dht22_Start();
if(ret == 0)
{
//printf("ret = %d\r\n",ret);
ret = Dht22_Read(data);
if(ret == 0)
{
//printf("value:%d,%d,%d,%d\r\n", data[0], data[1],data[2], data[3]);
//计算温度与湿度
H_value = data[0]<<8|data[1];
T_value = data[2]<<8|data[3];
//判断最高位是否为1,由于我这边是南方,无法测量到低于0度,但我自信这个代码是对的
if(T_value & (0x01<<16))
{
//将湿度最高位变为0,其它位不变,因为最高位为温度的正负,没必须参与计算
T_value = T_value & 0x7FFF;
//之前计算的值是没有小数点,现在取余,补上小数点
fH_value = H_value/10.0;
fT_value = T_value/10.0;
printf("湿度:%0.1f\r\n", fH_value);
printf("温度:-%0.1f\r\n", fT_value);
}
else
{
//之前计算的值是没有小数点,现在取余,补上小数点
fH_value = H_value/10.0;
fT_value = T_value/10.0;
printf("湿度:%0.1f\r\n", fH_value);
printf("温度:%0.1f\r\n", fT_value);
}
}
}
//采集周期必须大于或等于2S
delay_s(2);
}
return 0;
}
验证
数据出来了,nice,小伙伴们,点点关注。
源码下载:https://download.csdn.net/download/wwwqqq2014/73811606
版权声明:本文为CSDN博主「C是最好的编程语言」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wwwqqq2014/article/details/122301787
暂无评论