芯查查logo
  • 数据服务
    1. 新产品
    2. 物料选型
    3. 查替代
    4. 丝印反查
    5. 查品牌
    6. PCN/PDN
    7. 查方案
    8. 查代理
    9. 数据合作
  • SaaS/方案
      SaaS产品
    1. 供应链波动监控
    2. 半导体产业链地图
    3. BOM管理
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 行业资讯
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
  • 开通会员
基于stm32f103zet6的温湿度检测
原创 发布时间:2022/11/21 21:53
版块:
单片机/MCU论坛
简介:所用传感器为DHT11

DHT11温湿度模块简介:

     DHT11 一款湿温度一体化的数字传感器。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。

        性能指标和特性如下:

      在讲解代码之前我们先看一下DHT11的数据结构:

      DHT11数字温湿度传感器采用的是单总线数据格式,这个和DS18B20是一样的,都是由单个数据引脚端口完成输入输出双向传输。其数据包由5Byte(40Bit)组成。数据分为小数部分和整数部分,具体的格式如下:

      一次完整的数据传输为40Bit,高位先出。

      数据格式:    8Bit适度整数数据+8Bit湿度小数数据

                           +8Bit适度整数数据+8Bit湿度小数数据

                           +8Bit校验和数据

     其中校验和数据为前四个字节相加。

      

      数值的计算方法:

       humi=byte4.byte3=45.0   (%RH)     湿度

       temp=byte2.byte1=28.0 (℃)          温度

       校验和即 byte0 =byte1+byte2+byte3+byte4   (如果相等则数据校验成功)

      这里还要注意一点就是,DHT11一次通讯时间最大为3ms,主机连续采样间隔建议不小于100ms

 DHT11和单片机的连接和程序的编写:

       1

        先看看ht11.h文件:

        

#define DHT11 (GPIO_Pin_11) //PG11

#define GPIO_DHT11 GPIOG


#define DHT11_DQ_IN PGin(11)   //输入

#define DHT11_DQ_OUT PGout(11)  //输出


void DHT11_IO_OUT(void);

void DHT11_IO_IN(void);

u8 DHT11_Init(void);

void DHT11_Rst(void);

u8 DHT11_Check(void);

u8 DHT11_Read_Bit(void);

u8 DHT11_Read_Byte(void);

u8 DHT11_Read_Data(u8 *temp,u8 *humi);

      程序的编写思想和DS18B20的同出一辙,首先定义了PG11为数据端口,将PG11通DHT11的输出端口相连就可以进行数据传输了。这种在头文件中利用宏定义来定义一些程序中需要更换的参数,这是有利于程序的移植的,如果需要更换数据输入的端口则只需要在头文件中更改定义的宏即可。

       u8 DHT11_Check()                                                                                              void DHT11_Rst()    

{                                                                                                                              { 

u8 retry=0;                                                                                                     DHT11_IO_OUT();  //SET OUTPUT

DHT11_IO_IN();//SET INPUT                                                                         DHT11_DQ_OUT=0;  //拉低DQ                 

    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~50us                             delay_ms(20);     //拉低至少18ms             

{                                                                                                                        DHT11_DQ_OUT=1;  //DQ=1        

retry++;                                                                                                    delay_us(30);      //主机拉高20~40us

delay_us(1);                                                                                             }

};  

if(retry>=100)return 1;

else retry=0;

    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~50us

{

retry++;

delay_us(1);

};

if(retry>=100)return 1;     

return 0;

}

        看这个检测和复位的程序是不是很熟悉,这个和DS18B20的基本相似只是高低电平持续的时间不一样。来看看DHT11的复位和响应号:

         

(这里不做过多解释,有疑问参考 https://www.xcc.com/planet/open-source/463 )

   DHT11数据“0”的表示方法:

    DHT11数据“1”的表示方法:

    这里看到数据“0”和数据“1”的主要区别就是数据线在12-14us的低电平之后高点平的持续时间不一样,数据“0”高点平持续的时间为26-28us而数据“1”高点平持续时间则为116--118us,我们则可以利用这一点来判断DHT11发送的是数据“0”还是数据“1”,即在低电平结束后的30us--118us之间检测数据端口输出的电压值,如果为高电平则为数据“1”反之则为数据“0”。那这时候就有小伙伴会问:我们怎们知道DHT11什么时候发送数据呢?我们再来看看DHT11开始发送数据的流程:

       我们可以看到,要想得到DHT11检测到的数据我们首先得向DHT11发送一段开始信号并且再得到DHT11的相应之后才能开始接收数据流,单片机发送开始信号之后,延时等待20-40us后读取DHT11的回应信号,读取总线为低电平,说明DHT11发送相应信号,DHT11发送响应信号之后,再把数据线拉高,准备发送数据,每一bit数据都是以低电平开始,如果读取响应信号为高点平,则DHT11没有响应。具体的程序如下:

u8 DHT11_Read_Bit(void)                                            

{

  u8 retry=0;

while(DHT11_DQ_IN&&retry<100)//等待变为低电平 12-14us 开始

{

retry++;

delay_us(1);

}

retry=0;

while(!DHT11_DQ_IN&&retry<100)//等待变高电平  26-28us表示0,116-118us表示1

{

retry++;

delay_us(1);

}

delay_us(40);//等待40us

if(DHT11_DQ_IN)return 1;

else return 0;    

}


u8 DHT11_Read_Byte(void)    

{        

    u8 i,dat;

    dat=0;

for (i=0;i<8;i++) 

{

    dat<<=1; 

    dat|=DHT11_Read_Bit();

    }     

    return dat;

}


u8 DHT11_Read_Data(u8 *temp,u8 *humi)    

{        

  u8 buf[5];

u8 i;

DHT11_Rst();

if(DHT11_Check()==0)

{

for(i=0;i<5;i++)//读取40位数据

{

buf[i]=DHT11_Read_Byte();

}

if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])       \\因为数据传输从高位开始,则这里的buff[0]其实是byte4

{                                                                           \\buff[2]为byte2

*humi=buf[0];                                            \\因为DHT11的分辨率为1,所以这里只输出整数位

*temp=buf[2];

}

}else return 1;

return 0;     

}

     主函数就比较简单了:

void data_pros() //数据处理函数

{

u8 temp;       

u8 humi;

DHT11_Read_Data(&temp,&humi);

printf("温度=%d°C  湿度=%d%%RH\r\n",temp,humi);

}


int main()

{

u8 i=0;

SysTick_Init(72);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组

LED_Init();

USART1_Init(115200);

while(DHT11_Init()) //检测dht11是否存在

{

printf("DHT11 Check Error!\r\n");

delay_ms(500);

}

printf("DHT11 Check OK!\r\n");

while(1)

{

i++;

if(i%20==0)

{

led1=!led1;

data_pros();    //读取一次DHT11数据最少要大于100ms

}

delay_ms(100);

}

}

   在主函数之前定义了一个数据处理函数,用于将得到的DHT11的数据通过串口在上位机串口助手上显示,如果小伙伴们用到其他显示屏幕则可以在这个数据处理函数当中直接修改数据的输出就可以了。这样定义之后在主函数中直接调用这个数据处理函数就可以完成数据的读写了。主函数中是每2秒读取一次DHT11的数值,如果需要修改时间,直接修改delay_ms()函数的延迟或者if(i%20==0)中取余的数值即可,这个也是常用的延迟较长时间的延长方式(因为 delay_ms()函数每次延时的时间是不能超过一定界限的)。

总结:

    有了之前DS18B20的基础理解DHT11会更加容易一些,两种传感器的数据传输是比较类似的。

工程附件
DHT11温湿度传感器.zip
STM32 单片机/MCU论坛 STM单片机 DIY设计 传感器模块 温度检测 DHT11
2022/11/21 21:53
  • 举报
😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷😸😹😺😻😼😽😾😿🙀🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏✂✅✈✉✊✋✌✏✒✔✖✨✳✴❄❇❌❎❓❔❕❗❤➕➖➗➡➰🚀🚃🚄🚅🚇🚉🚌🚏🚑🚒🚓🚕🚗🚙🚚🚢🚤🚥🚧🚨🚩🚪🚫🚬🚭🚲🚶🚹🚺🚻🚼🚽🚾🛀Ⓜ🅰🅱🅾🅿🆎🆑🆒🆓🆔🆕
@好友

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
发布者
搞机佬
创作者认证
最新帖子
树莓派pico 2测评 - 初体验【工程师经验】+ 飞线【开源】zvs142857 2.1A,3A快充 充电宝迷你UC3842 开关电源优化全解析:攻克常见难题,提升性能飞腾CPU × DeepSeek大模型,双芯加持全系列稳跑
热门版块
查看更多
电子DIY
电子元器件
维修技术
抄图联盟
汽车电子工程师论坛
工业电子专区
新手入门指南
单片机/MCU论坛
PCB设计
开源项目

106

收藏

分享

微信扫码
分享给好友

评论