DHT11, 一线制温湿度传感器参考程序
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,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*10+DHT11_Data;
Temperature=DHT11_Data*10+DHT11_Data;
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=Humanity_H/10;
DHT11_Data=Humanity_H%10;
DHT11_Data=Humanity_L/10;
DHT11_Data=Humanity_L%10;
DHT11_Data=Temperature_H/10;
DHT11_Data=Temperature_H%10;
DHT11_Data=Temperature_L/10;
DHT11_Data=Temperature_L%10;
}
}
//这是主函数,从C52那里改的
#ifndef__LED8_H__
#define __LED8_H__
#define uchar unsigned char
#define uint unsigned int
void LED8(uchar i,j);
#endif
//LED8.h #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;
}
//LED8.c 能通过编译,但是没有数据,不知道问题在哪 延时时间不对,STC32G的速度比89c52快了几十倍,延时的时间也要相应修改。
这俩函数用ISP软件从新生成一下,先自己动手试试,要实在不会我明天写个给你好了。
冲哥是天山上的来客,高风亮节,路见不平,拔刀相助了:)
DHT11_百度百科 (baidu.com)
这是STC89C52RC的代码,即使是对的,软件模拟通信也要加延时
下面这个是网上看到的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={1,1,1};//前两位为整数部分,后一位为小数部分
unsigned int Humidity={1,1};//传回的湿度数据只有整数部分
unsigned char Data_Receive;
/*##############################################################################################
设计名称:基于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=dat8;
}
Delay30us();//等待DHT11拉低50us
Delay30us();
DHT=1;
for(i=0;i<4;i++)
{
CheckValue+=Data_Receive;//计算校验值
}
if((unsigned char)CheckValue==Data_Receive)//比对
{
Temperature=Data_Receive/10;
Temperature=Data_Receive%10;
Temperature=Data_Receive%10;
Humidity=Data_Receive/10;
Humidity=Data_Receive%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
}
} 电子DIY小家 发表于 2023-3-27 20:06
延时时间不对,STC32G的速度比89c52快了几十倍,延时的时间也要相应修改。
这俩函数用ISP软件从新生成一下 ...
感谢回复,已经写出来了 帮忙将 【DHT11 + STC32G12K128】 调试通过的程序上传上来,方便后续新人学习:)