找回密码
 立即注册
查看: 8597|回复: 38

DHT11, 一线制温湿度传感器参考程序

[复制链接]

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-3-27 17:20:19 | 显示全部楼层 |阅读模式

DHT11, 一线制温湿度传感器,读不出数据

#include <STC32G.H>
#include <intrins.H>
#include "LED8.h"
#define uchar unsigned char
#define uint unsigned int
        
sbit DATA=P1^3;
        
uchar DHT11_Data[8],Humanity,Temperature;
        
void DHT11_Start();
uchar Receive_Byte();
void DHT11_ReadData();
void delay_us(uchar xus);
void delay_ms(uint xms);

void main()
{
        P1M0 = 0x00; P1M1 = 0x00;
        delay_ms(1000);
        while(1)
        {
                DHT11_ReadData();
                Humanity=DHT11_Data[0]*10+DHT11_Data[1];
                Temperature=DHT11_Data[4]*10+DHT11_Data[5];
        
                LED8(3,Humanity/10);
                delay_ms(1);
                LED8(4,Humanity%10);
                delay_ms(1);
                LED8(7,Temperature/10);
                delay_ms(1);
                LED8(8,Temperature%10);
                delay_ms(1);
        }
}


void delay_ms(uint xms)        //@11.0592MHz
{
        uint i,j;
        for(i=xms;i>0;i--)
                for(j=110;j>0;j--);
}

void delay_us(uchar xus)                //@11.0592MHz
{
        while (--xus);
}

void DHT11_Start()
{
        DATA=1;                        //空闲状态为高电平
        delay_us(2);
        DATA=0;                        //主机发出开始信号,将总线拉低至少18ms
        delay_ms(20);
        DATA=1;                        //拉高总线并延时等待20--40us
        delay_us(30);
}

uchar Receive_Byte()        //读取一个字节数据
{
        uchar i,dat;
        for(i=0;i<8;i++)
        {
                while(DATA==0);        //等待数据低电平部分过去
                delay_us(8);        //延时50us,若DATA还为高电平则为数据1,否则为数据0
                dat<<=1;
                if(DATA==1)
                {
                        dat|=0x01;
                }
                while(DATA==1);        //等待此帧数据高电平完全过去
        }
        return dat;
}

void DHT11_ReadData()
{
        uchar H1,H2,T1,T2,check,Humanity_H,Humanity_L,Temperature_H,Temperature_L;
        DHT11_Start();                //主机发出开始信号
        if(DATA==0)                        //DHT11响应信号
        {
                while(DATA==0);        //DHT11响应信号,80us
                delay_us(40);        //DHT11响应信号,拉高延时80us,准备输出
                H1=Receive_Byte();
                H2=Receive_Byte();
                T1=Receive_Byte();
                T2=Receive_Byte();
                check=Receive_Byte();
                delay_us(25);        //当一次数据传输完成后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
                if((H1+H2+T1+T2)==check)        //数据检验
                {
                        Humanity_H=H1;
                        Humanity_L=H2;
                        Temperature_H=T1;
                        Temperature_L=T2;
                }
                DHT11_Data[0]=Humanity_H/10;
                DHT11_Data[1]=Humanity_H%10;
                DHT11_Data[2]=Humanity_L/10;
                DHT11_Data[3]=Humanity_L%10;
                DHT11_Data[4]=Temperature_H/10;
                DHT11_Data[5]=Temperature_H%10;
                DHT11_Data[6]=Temperature_L/10;
                DHT11_Data[7]=Temperature_L%10;
        }
}

//这是主函数,从C52那里改的

回复

使用道具 举报 送花

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-3-27 17:20:55 | 显示全部楼层
#ifndef  __LED8_H__
#define __LED8_H__
#define uchar unsigned char
#define uint    unsigned int
       
void LED8(uchar i,j);

#endif
//LED8.h

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-3-27 17:21:24 | 显示全部楼层
#include <STC32G.H>
#define uchar unsigned char
#define uint    unsigned int
sbit P2_4=P2^4;
sbit P2_3=P2^3;
sbit P2_2=P2^2;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                    0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void LED8(uchar i,j)
{
        switch(i)       
        {
                case 1:P2_4=1;P2_3=1;P2_2=1;break;
                case 2:P2_4=1;P2_3=1;P2_2=0;break;
                case 3:P2_4=1;P2_3=0;P2_2=1;break;
                case 4:P2_4=1;P2_3=0;P2_2=0;break;
                case 5:P2_4=0;P2_3=1;P2_2=1;break;
                case 6:P2_4=0;P2_3=1;P2_2=0;break;
                case 7:P2_4=0;P2_3=0;P2_2=1;break;
                case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        P0=table[j];
}
//LED8.c

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-3-27 17:22:45 | 显示全部楼层
能通过编译,但是没有数据,不知道问题在哪
  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2023-3-27 20:06:02 | 显示全部楼层
延时时间不对,STC32G的速度比89c52快了几十倍,延时的时间也要相应修改。
1.png
这俩函数用ISP软件从新生成一下,先自己动手试试,要实在不会我明天写个给你好了。
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-3-27 20:20:09 | 显示全部楼层
冲哥是天山上的来客,高风亮节,路见不平,拔刀相助了:)
1.png


1.png
DHT11_百度百科 (baidu.com)
2.png
这是STC89C52RC的代码,即使是对的,软件模拟通信也要加延时



  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-3-27 20:23:41 | 显示全部楼层
1.png

2.png
3.png
4.png
5.png
6.png
  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-3-27 20:29:32 | 显示全部楼层
下面这个是网上看到的STC15的参考程序,也是要加延时啊 :
#include<STC15.H>
#include "intrins.h"//用于提供_nop_();函数
#include "OLED_Contrul_Hygrothermograph.c"//OLED控制函数

sbit YLED=P3^1;
sbit RLED=P3^0;
sbit DHT=P3^5;//DHT11模块

unsigned int Temperature[3]={1,1,1};//前两位为整数部分,后一位为小数部分
unsigned int Humidity[2]={1,1};//传回的湿度数据只有整数部分

unsigned char Data_Receive[5];
/*##############################################################################################
设计名称:基于DHT11的温湿度计(Hygrothermograph)
设计者:清河

平台:STC15F104W
硬件部分
显示:采用OLED12864显示温度和湿度
测量,采用DHT11模块,模块信息如下:
ASATR
-----
NA:DHT11
OC:3.3-5.5V
U1:5-95%RH
U2:-20-60℃
U3:±5%RH±2℃
SN:A1712882A

为保证延时准确,晶振设置为12MHz

##############################################################################################*/

void Delay30us()//@12.000MHz
{
        unsigned char i;
        i=87;
        while(--i);
}

void Delay20ms()//@12.000MHz
{
        unsigned char i,j,k;
        i=1;
        j=234;
        k=113;
        do
        {
                do
                {
                        while(--k);
                }while(--j);
        }while(--i);
}

void Delay1s()//@12.000MHz
{
        unsigned char i,j,k;
        i=46;
        j=153;
        k=245;
        do
        {
                do
                {
                        while(--k);
                }while(--j);
        }while(--i);
}

void OLED_Display()//OLED显示驱动函数
{
        OLED_DataDisplay_T(56,4,Temperature);//在指定位置显示温度
        OLED_DataDisplay_H(56,6,Humidity);//在指定位置显示湿度
}

void DHT_Collect()//温度采集函数
{
        unsigned char i,j;//for循环变量
        unsigned char t;//超时判断
        unsigned char dat8=0;//一次读取的8位数据,需要读5次
        unsigned int CheckValue=0;//校验和
        
        DHT=0;//主机发起始信号
        Delay20ms();//主机拉低总线至少18ms
        DHT=1;//主机拉高总线20~40us
        Delay30us();
        
        t=80;//设置超时等待时间
        while(DHT&&t--);//等待DHT11拉低总线
        if(t==0)//超时
        {
                DHT=1;
        }
        t=250;//设置超时等待时间
        while(!DHT&&t--);//等待DHT11拉高总线
        if(t==0)//超时
        {
                DHT=1;
        }
        t=250;//设置超时等待时间
        while(DHT&&t--);//等待DHT11拉低总线
        if(t==0)//超时
        {
                DHT=1;
        }

        for(j=0;j<5;j++)//5次读取
        {
                for(i=0;i<8;i++)//1次8个位
                {
        //等待50us开始时隙
                        t=150;//设置超时等待时间
                        while(!DHT&&t--);//等待DHT11拉高总线
                        if(t==0)//超时
                        {
                                DHT=1;
                        }
                        t=0;//记录时间清零
                        while(DHT&&++t);//等待并记录高电平持续时间
                        dat8<<=1;
                        if(t>30)//高电平持续时间较长(70us)
                        dat8+=1;//传输值为1
                }
                Data_Receive[j]=dat8;
        }
        
        Delay30us();//等待DHT11拉低50us
        Delay30us();
        DHT=1;

        for(i=0;i<4;i++)
        {
                CheckValue+=Data_Receive;//计算校验值
        }
        if((unsigned char)CheckValue==Data_Receive[4])//比对
        {
                Temperature[0]=Data_Receive[2]/10;
                Temperature[1]=Data_Receive[2]%10;
                Temperature[2]=Data_Receive[3]%10;
                Humidity[0]=Data_Receive[0]/10;
                Humidity[1]=Data_Receive[0]%10;
        }
}

void sys_init()//系统初始化函数
{
        YLED=1;
        RLED=1;
        OLED_Init(); //OLED初始化
        OLED_CLS();//清屏
        
        OLED_FormTitle(0,0);//显示标题文字Linyar Lab.
        OLED_FormName(0,2);//显示Hygrothermograph名称
        OLED_FormLine(0,3);//显示一条横线
        OLED_FormTemp(8,4);//显示温度文字
        OLED_FormHumi(16,6);//显示湿度文字
        OLED_AnyChar_16X16(96,4,TempChar);//在行4(每行高16像素),列96像素位置显示摄氏度℃字符
        OLED_AnyChar_8X16(88,6,HumiChar);//在行6(每行高16像素),列88像素位置显示百分号%字符
        OLED_AnyChar_8X16(72,4,PointChar);//在行4(每行高16像素),列72像素位置显示冒号:字符
}

void main()
{
        P3M0=0X00;
        P3M1=0X00;
        sys_init();
        
        while(1)
        {
                DHT_Collect();//DHT11数据采集
                YLED=1;RLED=0;//灯状态转换
                OLED_Display();//OLED显示函数
                RLED=1;YLED=0;//灯状态转换
                Delay1s();
                Delay1s();//注意:长时间的延时必须要有,不然会读出0
        }
}
回复 支持 1 反对 0

使用道具 举报 送花

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-3-28 10:33:40 | 显示全部楼层
电子DI*** 发表于 2023-3-27 20:06
延时时间不对,STC32G的速度比89c52快了几十倍,延时的时间也要相应修改。

这俩函数用ISP软件从新生成一下 ...

感谢回复,已经写出来了

点评

那就是调通了  详情 回复 发表于 2023-3-28 15:42
  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-3-28 10:49:16 | 显示全部楼层
帮忙将 【DHT11 + STC32G12K128】 调试通过的程序上传上来,方便后续新人学习:)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 20:03 , Processed in 0.182682 second(s), 109 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表