找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2493|回复: 0
打印 上一主题 下一主题
收起左侧

DHT11驱动程序

[复制链接]
跳转到指定楼层
楼主
ID:253955 发表于 2017-11-26 22:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*********************************************************************************************
程序名:    DHT11驱动程序
编写人:    王朗的诱惑
编写时间:  2015年8月4日
硬件支持:  STC12C5A60S2  DHT11
接口说明:  DHT11:VCC GND DATA
*********************************************************************************************
说明:1、单片机是STC12C5A60S2,晶振频率12MHz,实验成功。换用12T单片机或别的晶振的时候要修改
          延时函数和JUDGE。程序里判断超时的变量t的阀值也要改。
          2、好东西要共享,大家随意折腾~~
*********************************************************************************************/
#include <STC12C5A60S2.H>

typedef unsigned char        uchar;
typedef unsigned int        uint;

#define JUDGE        30                //用于判断通信的0和1,与单片机速度和晶振频率有关

sbit DATA = P1^0;                //定义数据引脚

uchar dat_r[5];                        //用于存放从DHT11读取到的数值

/*********************************************************************************************
函数名:延时函数
调  用:Delay30us();/Delay20ms();/Delay1s();
参  数:无
返回值:无
结  果:延时相应时间
备  注:振荡晶体为12MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
**********************************************************************************************/
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);
}

/*********************************************************************************************
函数名:UART串口初始化函数
调  用:UART_Init();
参  数:无
返回值:无
结  果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)
备  注:振荡晶体为12MHz,PC串口端设置 [ 4800,8,无,1,无 ]
**********************************************************************************************/
void UART_Init (void){
        EA = 1; //允许总中断(如不使用中断,可用//屏蔽)
        ES = 1; //允许UART串口的中断

        TMOD = 0x20;        //定时器T/C1工作方式2
        SCON = 0x50;        //串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收)
        TH1 = 0xF3;        //定时器初值高8位设置
        TL1 = 0xF3;        //定时器初值低8位设置
        PCON = 0x80;        //波特率倍频(屏蔽本句波特率为2400)
        TR1 = 1;        //定时器启动   
}

/*********************************************************************************************
函数名:UART串口发送函数
调  用:UART_T (?);
参  数:需要UART串口发送的数据(8位/1字节)
返回值:无
结  果:将参数中的数据发送给UART串口,确认发送完成后退出
备  注:
**********************************************************************************************/
void UART_T (uchar UART_data){ //定义串口发送数据变量
        SBUF = UART_data;        //将接收的数据发送回去
        while(TI == 0);                //检查发送中断标志位
        TI = 0;                        //令发送中断标志位为0(软件清零)
}

/*********************************************************************************************
函数名:DHT11读数据函数
调  用:? = GetData();
参  数:无
返回值:失败->-1,-2,-3,-4;成功->0
结  果:读DHT11数据并保存到数组dat_r[]
备  注:
**********************************************************************************************/
char GetData (void)
{
        uchar i,j;                                //for循环变量
        uchar t;                                //超时判断
        uchar dat8=0;                        //一次读取的8位数据,需要读5次

        DATA = 0;                                //主机发起始信号
        Delay20ms();                        //主机拉低总线至少18ms
        DATA = 1;                                //主机拉高总线20~40us
        Delay30us();

        t = 80;                                        //设置超时等待时间
        while(DATA && t--);                //等待DHT11拉低总线
        if(t == 0)                                //超时
        {
                DATA = 1;
                return -1;                        //通信错误退出,返回错误信号:-1
        }

        //等80us响应信号
        t = 250;                                //设置超时等待时间
        while(!DATA && t--);        //等待DHT11拉高总线
        if(t == 0)                                //超时
        {
                DATA = 1;
                return -2;                        //通信错误退出,返回错误信号:-2
        }

        //等80us响应信号
        t = 250;                                //设置超时等待时间
        while(DATA && t--);                //等待DHT11拉低总线
        if(t == 0)                                //超时
        {
                DATA = 1;
                return -3;                        //通信错误退出,返回错误信号:-3
        }

        for(j=0; j<5; j++)                //5次读取
        {
                for(i=0; i<8; i++)                        //1次8个位
                {
                        //等待50us开始时隙
                        t = 150;                                //设置超时等待时间
                        while(!DATA && t--);        //等待DHT11拉高总线
                        if(t == 0)                                //超时
                        {
                                DATA = 1;
                                return -4;                        //通信错误退出,返回错误信号:-4
                        }
                        t = 0;                                        //记录时间清零
                        while(DATA && ++t);                //等待并记录高电平持续时间
                        dat8 <<= 1;
                        if(t > JUDGE)                        //高电平持续时间较长(70us)
                                dat8 += 1;                        //传输值为1
                        //else dat8 += 0;
                }
                dat_r[j] = dat8;
        }

        Delay30us();                //等待DHT11拉低50us
        Delay30us();
        DATA = 1;                        //结束,拉高总线
        return 0;                        //返回成功信号
}

/*********************************************************************************************
函数名:数据校验函数
调  用:? = Check();
参  数:无
返回值:成功->0;失败->-1;
结  果:数据校验
备  注:数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
**********************************************************************************************/
char Check (void)
{
        uchar i;                        //for循环变量
        uint chk=0;                        //校验和
        for(i=0; i<4; i++)
                chk += dat_r[i];                //累加
        if((uchar)chk != dat_r[4])        //比对
                return -1;                                //返回错误信号:-1
        else
                return 0;                                //返回正确信号:0
}

/*********************************************************************************************
函数名:主函数
调  用:无
参  数:无
返回值:无
结  果:读DHT11数据并送到串口显示
备  注:
**********************************************************************************************/
void main (void)
{
        char i;
        UART_Init();                //串口初始化
        Delay1s();                        //等待DHT11稳定
        do
        {
                i = GetData();        //读数据
                if(i != 0)                //有错误
                {
                        UART_T(-i);        //返回错误值
                        break;                //重新开始
                }

                i = Check();        //数据校验
                if(i != 0)                //有错误
                {
                        UART_T(-i);        //返回错误值
                        break;                //重新开始
                }

                UART_T(dat_r[0]);                //湿度整数
                //UART_T(dat_r[1]);                //湿度小数(根据数据手册,DHT11小数部分一直是0没用)
                UART_T(dat_r[2]);                //温度整数
                //UART_T(dat_r[3]);                //温度小数(根据数据手册,DHT11小数部分一直是0没用)
                UART_T(dat_r[4]);                //校验值

                Delay1s();                                //经测试,两次连读要至少延时80ms        
        }while(1);
}//main

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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