51单片机通过DHT11温度传感器读取温度(1)

一.传感器介绍

1.基本介绍

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度符合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。

应用平台:

暖通空调     测试及检测设备    汽车    数据记录器    消费品     自动控制等      

2.管脚说明

管脚作用
Vcc模块供电正极(供电电压范围:3-5.5V)
gnd模块数据传输管脚
GND模块供电负极

 3.data数据接口串行数据传输

一次完整的数据传输需要40bit数据,高位先出

传输具体过程如下:8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据 +8bit校验和

用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主 机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.

二.数据传输时序图、

1.模块存在检测时序图

 流程如下

单片机方面:单片机首先会给模块高电平,然后会将电平拉低,同时延时至少18ms,接着将电平拉高,同时延迟最多40us,可设定30us。

模块方面:模块会将管脚的电平拉低,并延迟80us,如果单片机检测在80us时间内,管脚一直属于低电平,那么就可以判断模块存在。

可以写出如下代码:判断模块是否存在

sbit LED = P2^0;
sbit DATA = P1^0;

void Delay25ms()        //@11.0592MHz
{
    unsigned char i, j;

    i = 45;
    j = 208;
    do
    {
        while (--j);
    } while (--i);
}

void Delay70us()        //@11.0592MHz
{
    unsigned char i;

    _nop_();
    i = 29;
    while (--i);

void check_DHT11()
{
    DATA = 1;  //将电平拉高
    DATA = 0;  //将电平拉低
    Delay25ms();  //低电平延迟25ms(至少18ms)
    DATA = 1;  //延时过后将电平拉高
    Delay70us();   //延迟大约70us,用来判断是否处于低电平
    if(DATA ==0)
    {
        LED = 0;  //如果一直处于低电平,则模块存在,指示灯点亮
    }
}
 

2.数据读取时序图

(1)数据0时序图

(2)数据1时序图

编程思路:由数据组成可以知道,该组数据由5组构成,每组有8位,因此我们可以建立两个变量,一个是轮数,读取5轮,一个是每轮读取的位数,读取8位。通过时序图可以得知,当data数据变成高电平时,开始进行数据读取,这时可以进行延时大约50us来判断读取的数据,(因为0信号高电平最多28us,而1信号最多70us,因此延迟50us来进行判断),如果经过50us依旧是高电平,则读取数据就是1,由于70us不好把握,因此需要进行“卡电平”,卡出电平降低的点,否则就是0,可以新建一个变量,将读取到的数据进行临时存放,为了保存一组完整的数据,需要新建一个char型变量,用于存储一组变量,这时可以将这个char型变量进行左移,然后将读取过来的“0”、“1”数据和char的地位进行按位与运算,直到将整个char型变量替换完毕,将替换完成的变量存储在数组中,直到整个数组全被存储,这时数据读取完毕。

实现代码如下:

sbit DATA = P1^0;
char save_data[5]; //画出数据存储区域

void Delay50us()        
{
    unsigned char i;

    _nop_();
    i = 20;
    while (--i);
}

int i;   //定义读取的轮数
int j;   //定义读取的位数
int tep;   //定义一组的临时存储区(8位)
int flag;   //定义读取的0、1数据
for(i = 0;i < 5;i ++)
{
    for(j = 0;j < 8;j++)
{
     while(!DATA);   //如果data数据管脚编程高电平,则开始数据传输
     Delay50us();    //延迟50us,然后判断data的电平状态
     if(DATA == 1)
{
      flag = 1;
      while(DATA);
}    
     else
{
      flag = 0;
}
      tep = tep<<1;
      tep |= flag;
}
    save_data[i] = tep;
}

三.全代码实现

#include <REGX52.H>
#include <intrins.h>
sbit LED = P2^0;
sbit DATA = P1^0;
char save_data[5]; //画出数据存储区域
void Delay25ms()        //@11.0592MHz
{
    unsigned char i, j;

    i = 45;
    j = 208;
    do
    {
        while (--j);
    } while (--i);
}
void Delay70us()        //@11.0592MHz
{
    unsigned char i;

    _nop_();
    i = 29;
    while (--i);
}
void Delay50us()        //@11.0592MHz
{
    unsigned char i;

    _nop_();
    i = 20;
    while (--i);
}
/*串口初始化*/
void UartInit(void)        //9600bps@11.0592MHz
{
    SCON = 0x40;        //8位数据,可变波特率
    TMOD &= 0x0F;        //清除定时器1模式位
    TMOD |= 0x20;        //设定定时器1为8位自动重装方式
    TL1 = 0xFD;        //设定定时初值
    TH1 = 0xFD;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
}
void send_byte(char msg_data)
{
    SBUF = msg_data; //将形式参数msg_data传送到SBUF中
    
}


/*判断温度检测模块是否存在*/
void check_DHT11()
{
    DATA = 1;
    DATA = 0;
    Delay25ms();
    DATA = 1;
    Delay70us();
    if(DATA ==0)
    {
        LED = 0;
    }
}
/*读取温度检测模块发送的数据*/
void send_DHT_data()
{
    int i;//轮数
    int k;//每轮的位数
    char flag;
    char tmp;
    check_DHT11();
    for(i=0;i<5;i++)
    {
        for(k=0;k<8;k++)
        {
            while(!DATA);//等待模块在低电平结尾处
            Delay50us();//延迟50微秒之后,读取DATA数据,如果依旧是高电平代表1,否则就是低电平,表示0
            if(DATA == 1)
            {
                flag = 1;
                while(DATA); //如果是高电平信号,那么就需要卡电平,因为高电平信号会持续将近70微秒
            }
            else
            {
                flag = 0;
            }
            /*通过将DATA的每一位数据把tmp的从低位一直替换到高位,直到替换完毕。*/
            tmp = tmp << 1;
            tmp |= flag;
        }
        save_data[i] = tmp;
    }
}
 

#include #define uchar unsigned char #define uint unsigned int sbit led=P2^5; sbit wei=P2^7; sbit duan=P2^6; sbit DQ=P2^2; uchar mazhi_duan[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; uchar mazhi_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xff}; void delayl(uint n) { uint i,j; for(i=n;i>0;i--) for(j=114;j>0;j--); } void delays(uchar i) { while(i--); } bit init_DS18B20() //DS8B20初始化 { bit x; DQ=1; //DQ复位 delays(8); DQ=0; //单片机将DQ拉低 delays(75); DQ=1; //拉高总线 delays(15); x=DQ; //延时过后 若x=0则初始化成功 若x=1则初始化失败 delays(5); return x; } void write_data(uchar dat) { uchar i,temp; temp=dat; DQ=1; for(i=0;i>=1; } } uchar read_data() { uchar i,dat; DQ=1; for(i=0;i>=1; DQ=1;//配置为输入 if(DQ) dat|=0x80; delays(4); } return dat; } uint readtemp() { uchar temph,templ; uint temp; float wendu; init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0x44);//启动温度转换 //delayl(100); init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0xBE);//读温度 //以下读温度,低八位在前 //高8位在后 templ=read_data(); temph=read_data(); temp = (temph<<8)|templ; wendu = temp*0.625+0.5;//温度扩大10倍,四舍五入 temp = wendu;//10倍温度 return temp; } void STC_init() { P1=0x00;//关闭led led=0; //锁存 wei=0; duan=0; } void display(uchar weil,uchar duanl,bit dp) { wei=1; P0=mazhi_wei[weil-1]; wei=0; duan=1; if(dp==1) P0=(mazhi_duan[duanl]|0x80); else P0=mazhi_duan[duanl]; duan=0; } void main() { uchar i; uint wendu; STC_init(); wendu=readtemp(); delayl(500); wendu=readtemp(); delayl(500); while(1) { wendu=readtemp(); for(i=0;i<80;i++) { display(1,wendu/100,0); delayl(3); display(2,wendu0/10,1); delayl(3); display(3,wendu,0); delayl(3); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值