请教各位大神,51单片机通过DHT11获取温湿度时,只能显示偶数值的温湿度,时序什么的都没发现问题
程序如下:
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DAT=P3^7; //温度传感器信号线
sbit LED0=P2^0; //湿度十位控制位
sbit LED1=P2^1; //湿度个位控制位
sbit LED2=P2^2; //温度十位控制位
sbit LED3=P2^3; //温度个位
sbit LED4=P2^4; //温度时分位
uchar code dula[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数码管显示0~9数组
uchar RH0=0;
uchar Rh=0; //用于存放上一次的湿度值,当获得的数据不满足校验要求时,显示上一次的温度值
uint tmp0=0,tmp1=0; //tmp0用于存储温度值整数部分,tmp1用于存储温度值小数部分
uint tmp2=0,tmp3=0; //tmp2用于存储上一次温度值的整数部分,tmp3用于存储上一次温度值的小数部分
/**********************************************************************
函数功能:延时子函数
入口参数:设置延时时长
时间:2019年08月09日
**********************************************************************/
void delayus(uint z)
{
while(--z);
}
void delayms(uint x)
{
uchar y;
while(x--)
{
for(y=0;y<114;y++);
}
}
/**********************************************************************
函数功能:DHT11
时间:2019年08月20日
**********************************************************************/
void start()
{
DAT=1;
delayus(2);
DAT=0;
delayms(30); //主机拉低总线必须大于18ms,保证DHT11能检测到起始信号
DAT=1; //发送起始信号结束后,拉高等待
delayus(10); //等待20~40us
}
/**********************************************************************
函数功能:从DHT11中获取 一个字节数据
时间:2019年08月20日
**********************************************************************/
uchar ReadByte(void)
{
uchar dat=0,i;
for(i=0;i<8;i++)
{
while(!DAT); //等待50us的低电平开始信号结束
delayus(5); //开始信号结束后,延时26~28us
if(DAT==1)
dat|=0x01; //时间为26~28us,还为高电平,表示接收的数据为1
else
dat|=0x00;
while(DAT); //等待数据信号高电平,0为26~28us,1为70us
dat<<=1;
}
return dat;
}
/**********************************************************************
函数功能:读温度值和湿度值,并校验温度值与湿度值
校验过程:校验数=温度值+湿度值
出口参数:读取的温度值
时间:2019年08月20日
**********************************************************************/
void DHT11()
{
uchar Hh,Hl,Th,Tl,Rc;
start(); //开始信号
DAT=1;
delayus(10);
Hh=ReadByte(); //接收湿度高8位
Hl=ReadByte(); //接收湿度低8位
Th=ReadByte(); //接收温度高8位
Tl=ReadByte(); //接收温度低8位
Rc=ReadByte(); //接收校正位
DAT=0; //传输完40位,拉低结束,拉低时间54us,然后释放总线
delayus(20); //输出40位数据后,继续输出低电平54us后转为输入状态
DAT=1;
if((Hh+Hl+Th+Tl)==Rc) //校正数据,如果等于,则执行下面语句,否则保持上一个数据不变
{
RH0=Hh; //湿度整数部分
tmp0=Th;
tmp1=Tl;
Rh=RH0; //将得到的温度值放入Rh中以便不满足校验值时显示出来
tmp2=tmp0; //
tmp3=tmp1;
}
else
{
RH0=Rh; //不满足校验要求显示上一次的湿度值
tmp0=tmp2; //不满足校验要求显示上一次的温度值
tmp1=tmp3;
}
}
/**********************************************************************
函数功能:显示温/湿度子函数
入口参数:要显示的温度值和湿度值
时间:2019年08月20日
**********************************************************************/
void display()
{
uchar s1,s2,w1,w2,w3;
s1=RH0/10; //分离出湿度值十位数
s2=RH0%10; //分离出湿度值个位数
w1=tmp0/10; //分离出温度值十位数
w2=tmp0%10; //分离出温度值个位数
w3=tmp1/10; //分离出温度值十分位数
P2=0xff;
P0=dula[s1]; //显示湿度值十位数
LED0=0;
delayus(200);
P2=0xff;
P0=dula[s2]; //显示湿度值个位数
LED1=0;
delayus(200);
P2=0xff;
if(tmp0>=10)
P0=dula[w1]; //显示温度值十位数
else
P0=0x00;
LED2=0;
delayus(200);
P2=0xff;
P0=dula[w2]|0x80; //显示温度值个位数
LED3=0;
delayus(200);
P2=0xff;
P0=dula[w3]; //显示温度值个位数
LED4=0;
delayus(200);
}
void main()
{
uint sum=0;
DAT=1;
delayms(1000);
while(1)
{
sum++;
if(sum==100)
{
sum=0;
DHT11();
}
display();
delayms(10);
}
} |