找回密码
 立即注册

QQ登录

只需一步,快速开始

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

DHT11温湿度传感器程序 普中单片机开发版

[复制链接]
跳转到指定楼层
楼主
ID:974010 发表于 2022-4-19 21:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
简单修改成开发板使用的。开发板使用时记得把74HC595的oe端与vcc短接,不然会引脚冲突导致lcd乱码

单片机源程序如下:
    #include <reg52.h>                                   // 头文件包含
    #include <intrins.h>

    #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
    #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

    sfr ISP_DATA  = 0xe2;                        // 数据寄存器
    sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
    sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
    sfr ISP_CMD   = 0xe5;                        // 命令寄存器
    sfr ISP_TRIG  = 0xe6;                        // 命令触发寄存器
    sfr ISP_CONTR = 0xe7;                        // 命令寄存器


    sbit DHT11_P   = P1^5;                 // 温湿度传感器DHT11数据接入
    sbit LcdRs_P   = P2^6;    // 1602液晶的RS管脚      
    sbit LcdRw_P   = P2^5;    // 1602液晶的RW管脚
    sbit LcdEn_P   = P2^7;    // 1602液晶的EN管脚

    uchar temp;                                        // 保存温度
    uchar humi;                                        // 保存湿度



    /*********************************************************/
    // 单片机内部EEPROM不使能
    /*********************************************************/
    void ISP_Disable()
    {
            ISP_CONTR = 0;
            ISP_ADDRH = 0;
            ISP_ADDRL = 0;
    }


    /*********************************************************/
    // 从单片机内部EEPROM读一个字节,从0x2000地址开始
    /*********************************************************/
    unsigned char EEPROM_Read(unsigned int add)
    {
            ISP_DATA  = 0x00;
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x01;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
            ISP_TRIG  = 0x46;         
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
            return (ISP_DATA);
    }


    /*********************************************************/
    // 往单片机内部EEPROM写一个字节,从0x2000地址开始
    /*********************************************************/
    void EEPROM_Write(unsigned int add,unsigned char ch)
    {
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x02;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            ISP_DATA  = ch;
            ISP_TRIG  = 0x46;
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
    }


    /*********************************************************/
    // 擦除单片机内部EEPROM的一个扇区
    // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
    /*********************************************************/
    void Sector_Erase(unsigned int add)         
    {
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x03;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            ISP_TRIG  = 0x46;
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
    }


    /*********************************************************/
    // 毫秒级的延时函数,time是要延时的毫秒数
    /*********************************************************/
    void DelayMs(uint time)
    {
            uint i,j;
            for(i=0;i<time;i++)
                    for(j=0;j<112;j++);
    }


    /*********************************************************/
    // 1602液晶写命令函数,cmd就是要写入的命令
    /*********************************************************/
    void LcdWriteCmd(uchar cmd)
    {
            LcdRs_P = 0;
            LcdRw_P = 0;
            LcdEn_P = 0;
            P0=cmd;
            DelayMs(2);
            LcdEn_P = 1;   
            DelayMs(2);
            LcdEn_P = 0;      
    }


    /*********************************************************/
    // 1602液晶写数据函数,dat就是要写入的数据
    /*********************************************************/
    void LcdWriteData(uchar dat)
    {
            LcdRs_P = 1;
            LcdRw_P = 0;
            LcdEn_P = 0;
            P0=dat;
            DelayMs(2);
            LcdEn_P = 1;   
            DelayMs(2);
            LcdEn_P = 0;
    }


    /*********************************************************/
    // 1602液晶初始化函数
    /*********************************************************/
    void LcdInit()
    {
            LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
            LcdWriteCmd(0x0C);        // 开显示,不显示光标
            LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
            LcdWriteCmd(0x01);        // 清屏
    }


    /*********************************************************/
    // 液晶光标定位函数
    /*********************************************************/
    void LcdGotoXY(uchar line,uchar column)
    {
            // 第一行
            if(line==0)        
                    LcdWriteCmd(0x80+column);
            // 第二行
            if(line==1)        
                    LcdWriteCmd(0x80+0x40+column);
    }


    /*********************************************************/
    // 液晶输出字符串函数
    /*********************************************************/
    void LcdPrintStr(uchar *str)
    {
            while(*str!='\0')                         // 判断是否到字符串的尽头了
                    LcdWriteData(*str++);
    }


    /*********************************************************/
    // 液晶输出数字
    /*********************************************************/
    void LcdPrintNum(uchar num)
    {
            LcdWriteData(num/10+48);        // 十位
            LcdWriteData(num%10+48);         // 个位
    }


    /*********************************************************/
    // 液晶显示内容的初始化
    /*********************************************************/
    void LcdShowInit()
    {
            LcdGotoXY(0,0);                                                                // 第0行的显示内容
            LcdPrintStr("  DHT11 System  ");
            LcdGotoXY(1,0);                                                           // 第1行的显示内容
            LcdPrintStr("T:   C   H:   %");
            LcdGotoXY(1,4);                                                                // 温度单位摄氏度上面的圆圈符号
            LcdWriteData(0xdf);      
    }



    /*********************************************************/
    // 10us级延时程序
    /*********************************************************/
    void Delay10us()
    {
            _nop_();        // 执行一条指令,延时1微秒
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
    }


    /*********************************************************/
    // 读取DHT11单总线上的一个字节
    /*********************************************************/
    uchar DhtReadByte(void)
    {   
            bit bit_i;
            uchar j;
            uchar dat=0;

            for(j=0;j<8;j++)   
            {
                    while(!DHT11_P);        // 等待低电平结束      
                    Delay10us();                        // 延时
                    Delay10us();
                    Delay10us();
                    if(DHT11_P==1)                // 判断数据线是高电平还是低电平
                    {
                            bit_i=1;
                            while(DHT11_P);
                    }
                    else
                    {
                            bit_i=0;
                    }
                    dat<<=1;                                   // 将该位移位保存到dat变量中
                    dat|=bit_i;   
            }
            return(dat);  
    }


    /*********************************************************/
    // 读取DHT11的一帧数据,湿高、湿低(0)、温高、温低(0)、校验码
    /*********************************************************/
    void ReadDhtData()
    {            
            uchar HumiHig;                // 湿度高检测值
            uchar HumiLow;                // 湿度低检测值
            uchar TemHig;                        // 温度高检测值
            uchar TemLow;                        // 温度低检测值
            uchar check;                        // 校验字节
         
            DHT11_P=0;                                // 主机拉低
            DelayMs(20);                        // 保持20毫秒
            DHT11_P=1;                                // DATA总线由上拉电阻拉高

            Delay10us();                         // 延时等待30us
            Delay10us();
            Delay10us();

            while(!DHT11_P);        // 等待DHT的低电平结束
            while(DHT11_P);                // 等待DHT的高电平结束

            //进入数据接收状态
            HumiHig = DhtReadByte();         // 湿度高8位
            HumiLow = DhtReadByte();         // 湿度低8为,总为0
            TemHig  = DhtReadByte();         // 温度高8位
            TemLow  = DhtReadByte();         // 温度低8为,总为0
            check   = DhtReadByte();        // 8位校验码,其值等于读出的四个字节相加之和的低8位

            DHT11_P=1;                                // 拉高总线

            if(check==HumiHig + HumiLow + TemHig + TemLow)                 // 如果收到的数据无误
            {
                    temp=TemHig;                         // 将温度的检测结果赋值给全局变量temp
                    humi=HumiHig;                        // 将湿度的检测结果赋值给全局变量humi
            }
    }


    /*********************************************************/

    // 主函数
    /*********************************************************/
    void main()
    {
            uchar i;

            LcdInit();                                                        // 液晶功能的初始化                       
            LcdShowInit();                                         // 液晶显示的初始化

         
         
            while(1)
            {
                    ReadDhtData();                                 // 检测温湿度数据

                    LcdGotoXY(1,2);                                 // 定位到要显示温度的地方
                    LcdPrintNum(temp);                // 显示温度值
                    LcdGotoXY(1,11);                        // 定位到要显示湿度的地方
                    LcdPrintNum(humi);                // 显示湿度值
                  
                  

                    for(i=0;i<25;i++)
                    {
                           
                            DelayMs(20);                                // 延时      
                    }
            }



评分

参与人数 1黑币 +20 收起 理由
admin + 20 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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