注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

信息 灵感 创新

III = Information,Inspiration,Innovation

 
 
 

日志

 
 
关于我

we are 5. Mathematics, Computation, Programming, Engineering, and Making fun of life.

网易考拉推荐

DHT11温湿度传感器程序  

2017-08-23 09:26:21|  分类: 数字电路 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
这是一款含有已校准数字信号输出的温湿度复合传感器,这款传感器和传统的传感器不同,一般的传感器使用高低电平表示0和1,而这个传感器是采用高电平持续的时间长度表示0和1,属于是PPM(脉冲位置调制)。理解其工作原理之后就很容易写出相应的程序,废话少说,直接上代码。
DHT11.h头文件:
#include <reg51.h>
/*
DHT11读取的五个字节:
DATA[0]:湿度整数部分
DATA[1]:湿度小数部分,目前一直为0
DATA[2]:温度整数部分
DATA[3]:温度小数部分,目前一直为0
DATA[4]:检验和,等于前四个字节的和(溢出截断)
*/

sbit DHT11=P2^7;

void Delay30us_DHT11();
void Delay20ms_DHT11();
void Delay1s_DHT11();

//
#define NOACK 0xFF
#define OVERTIME 0xFE

unsigned char ReadData_DHT11(unsigned char *buffer);
unsigned char Validate_DHT11(unsigned char* buffer);
然后是DHT11.c文件:
#include "DHT11.h"

/*
在晶振频率为12MHz时,延时30微秒
*/
void Delay30us_DHT11()
{
    //LCALL         //2MC
    #pragma ASM
    PUSH ACC        //2MC
    MOV ACC,#06H    //2MC,6
DL30US:
    DEC A           //(1MC)
    JNZ DL30US      //(2MC)
                    //LOOP 6*(1+2)=18MC
    POP ACC         //2MC
    NOP             //1MC
    NOP             //1MC
    #pragma ENDASM
    //RET             2MC
    //2+2+2+18+2+2+2=30MC
}

/*
在晶振频率为12MHz时,延时20毫秒
*/
void Delay20ms_DHT11()
{
    //LCALL 2MC
    #pragma ASM
    MOV A,R7//1
    PUSH ACC//2
    MOV A,R6//2
    PUSH ACC//1
    //8MC ABOVE

    //(1+2*R6+2)*R7+1
    MOV R7,#55H//1,85
DLR7:
    MOV R6,#74H//1,116
DLR6:
    DJNZ R6,DLR6//(2) 
    DJNZ R7,DLR7//(2) 1+2*116+2=235
    //(1+2*R6+2)*R7+1=19976

    //16MC BELOW
    POP ACC//2
    MOV R6,A//1
    POP ACC//2
    MOV R7,A//1
    PUSH ACC//2
    POP ACC//2
    PUSH ACC//2
    POP ACC//2
    #pragma ENDASM
    //RET   2
}

/*
在晶振频率为12MHz时,延时1秒
*/
void Delay1s_DHT11()
{
    //LCALL 2MC
    #pragma ASM
    MOV A,R7//1
    PUSH ACC//2
    MOV A,R6//1
    PUSH ACC//2
    MOV A,R5//1
    PUSH ACC//2   
    //11MC ABOVE  
    
    
    //((2*R5+3)*R6+3)*R7+1
    //999909
    MOV R7,#0EFH//1
DL2:
    MOV R6,#25H//1
DL1:
    MOV R5,#37H//1
DL0:
    DJNZ R5,DL0//2,DL0:2*R5
    DJNZ R6,DL1//2,DL1:(1+2*R5+2)*R6
    DJNZ R7,DL2//2,DL2:(1+(1+2*R5+2)*R6+2)*R7+1
    
    
    //12MC BELOW
    NOP
    POP ACC//2
    MOV R5,A//1
    POP ACC//2
    MOV R6,A//1
    POP ACC//2
    MOV R7,A//1
    #pragma ENDASM
    //RET 2MC
}

/*
从DHT11中读取一字节
*/
unsigned char ReadByte_DHT11()
{
    unsigned char i,temp,dat=0;

    for(i=0;i<8;i++)
    {
        //低电平表示位的开始
        while(!DHT11);//等待低电平结束
        
        //根据高电平持续时间长短决定该位为0,或者1
        //26-28us:低电平
        //116-118us:高电平
        Delay30us_DHT11();//延时30us
        if(DHT11)//如果依旧高电平,则表明持续了116-118us,此位为1
            temp=1;
        else
            temp=0;//否则只持续了26-28us,此位为0
        while(DHT11);//等待表示0或者1的高电平结束,下一位的开始
        dat<<=1;
        dat|=temp;//高位在前,低位在后
        
    }
    return dat;
}

/*
从DHT11中读取数据
buffer前五个字节将会被读取的数据填充
*/
unsigned char ReadData_DHT11(unsigned char *buffer)
{
    /*
    开始信号
    MCU发送起始信号,先拉低总线,
    保持至少18毫秒,
    保证DHT能检测到起始信号
    然后拉高总线
    */
    DHT11=0;
    Delay20ms_DHT11();
    DHT11=1;
        
    /*
    MCU检查DHT11响应
    在MCU将总线拉高后等待20~40us,
    DHT11通过将总线拉低表明响应
    */
    Delay30us_DHT11();
    
    //检查总线,是否为低电平
    if(DHT11!=0)
        return NOACK;//无响应

    /*
    如果代码执行到此处,则表明有响应
    让MCU将总线拉高,或者等DHT11会将总线拉高,并保持在40-50us
    准备接收数据
    */
    while(!DHT11);//等待表示响应的低电平结束
    
    //此处总线被DHT11拉高,准备输出
    
    while(DHT11);//等待DHT11拉低电平,开始输出数据
        
    buffer[0]=ReadByte_DHT11();
    buffer[1]=ReadByte_DHT11();
    buffer[2]=ReadByte_DHT11();
    buffer[3]=ReadByte_DHT11();
    buffer[4]=ReadByte_DHT11();
    //DHT11每秒最多读取1次温度
    Delay1s_DHT11();
    return 0;
}

/*
校验数据是否有效,一共五个字节
校验通过返回1,否则返回0
*/
unsigned char Validate_DHT11(unsigned char* buffer)
{
    unsigned int checkSum=0;
    unsigned char i;
    for(i=0;i<4;i++)//前四个字节
        checkSum+=buffer[i];
    if(checkSum==0)
        return 0;
    if((unsigned char)checkSum==buffer[4])
        return 1;
    return 0;
}
虽然延时函数是在12MHz晶振频率下的延时,但是用在11.0592MHz下也是可以的。但如果晶振频率过高,因为延时时间会变短,则会出现数据读取错误的问题。
  评论这张
 
阅读(24)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017