找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3276|回复: 3
收起左侧

单片机+DHT11+1602显示程序Proteus仿真 有详细注释 蓝牙串口传输

[复制链接]
ID:428799 发表于 2021-5-18 21:18 | 显示全部楼层 |阅读模式
基于51单片机的温湿度检测设计,有蓝牙向手机传输功能
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

仿真图效果

仿真图效果


电路原理图如下:

原理图

原理图


注释很详细的单片机源程序如下:
  1. #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
  2. #include<intrins.h>

  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define lcddata  P0    //数据端口;

  6. sbit io=P1^0;           //dht11data端接单片机的P1^0口//

  7. sbit SPK =P1^1;         //蜂鸣器;
  8. sbit LED =P1^2;         //报警灯 ;
  9. sbit JDQ_WenDu =P1^3;   // 控制风扇的继电器;
  10. sbit JDQ_ShiDu =P1^4;   // 控制风扇的继电器;

  11. sbit K1=P3^2;       //手动/自动复位功能;
  12. sbit K2=P3^3;       //页面选择;
  13. sbit K3=P3^4;       //修改min,按键加1;
  14. sbit K4=P3^5;       //修改max,按键加1;

  15. sbit RS = P2^0;     //Pin4     数据命令选择;  高电平时为数据寄存器,低电平是为选择指令寄存器;
  16. sbit RW = P2^1;     //Pin5     读写模式选择;
  17. sbit E  = P2^2;     //Pin6     使能信号;

  18. bit di=1;
  19. bit flag_300ms ;

  20. unsigned char s[3]={0,0,'\0'};              //只读取两个字节,读到第三个结束;
  21. unsigned char table[]={0,1,2,3,4,5,6,7,8,9};                                                                                                                        

  22. unsigned int j=40,i=0,sum=0;
  23. int tempeature;         //整型变量  tempeature:温度
  24. uchar yemian=0;         //(定义变量)
  25. uchar flat=1;
  26. unsigned char WenDu=20,ShiDu=40;//报警的温度和湿度

  27. typedef bit BOOL;  //此声明一个布尔型变量即真或假//
  28. uchar data_byte;
  29. uchar RH,RL,TH,TL;

  30. void receive();                   //接收数据//
  31. /******************************************************************/
  32. void DelayUs(unsigned char us)//delay us
  33. {
  34.                  unsigned char uscnt;
  35.                  uscnt=us>>1;        /*12MHz频率*/
  36.                  while(--uscnt);
  37. }
  38. /******************************************************************/
  39. /*                    毫秒函数声明                                */
  40. /******************************************************************/
  41. void DelayMs(unsigned int ms)
  42. {
  43. while(--ms)
  44.          {
  45.                  DelayUs(250);
  46.                  DelayUs(250);
  47.                  DelayUs(250);
  48.                  DelayUs(250);
  49.          }
  50. }

  51. //***************延时函数*************************************
  52. void delay(uchar ms) //延时模块//
  53. {
  54.                 uchar i;
  55.                 while(ms--)               
  56.                 for(i=0;i<100;i++);
  57. }
  58. void delay1()  //一个for循环大概需要8个多机器周期 一个机器周期为1us 晶振为12MHz  也就是说本函数延时8us多 此延时函数必须德稍微精确一点
  59. {
  60.                 uchar i;
  61.                 for(i=0;i<1;i++);
  62. }
  63. //  对液晶经行写指令;
  64. void wr_i_lcd(uchar content)
  65. {
  66.                  DelayMs(5);//操作前短暂延时,保证信号稳定
  67.                  E=0;          //E端的由高电平跳变成低电平时,液晶模块执行命令;  此处位E端清零操作
  68.                  RS=0;     
  69.                  RW=0;         
  70.                  E=1;
  71.                  lcddata=content;
  72.                  E=0;
  73. }

  74. //    液晶初始化,清除显示,归为地址;
  75. void  lcd_csh()
  76. {
  77. //        wr_i_lcd(0x01);     //清除显示;
  78. //        wr_i_lcd(0x30);     //地址归位;    30H:设定8位控制界面;
  79. //                            //             00H:基本指令集;
  80. //                            //             34H:设定扩展指令集;
  81. //        wr_i_lcd(0x0c);     //开显示,无光标,光标不闪烁;   0x0e:开显示,有光标,光标不闪烁;  0x0f:开显示,有光标,光标闪烁;
  82. //        wr_i_lcd(0x10);     //光标向左移;
  83. //  wr_i_lcd(0x06);    /*光标的移动方向   */
  84.         
  85.                 DelayMs(15);
  86.                 wr_i_lcd(0x38);
  87.                 DelayMs(5);
  88.                 wr_i_lcd(0x38);
  89.                 DelayMs(5);
  90.                 wr_i_lcd(0x38);
  91.                 DelayMs(5);
  92.                 wr_i_lcd(0x0c);
  93.                 DelayMs(5);
  94.                 wr_i_lcd(0x06);
  95.                 DelayMs(5);
  96.                 wr_i_lcd(0x01);
  97.                 DelayMs(5);        
  98. }

  99. //  对液晶进行写数据;
  100. void wr_d_lcd(uchar content)
  101. {        
  102.          DelayMs(5);  //操作前短暂延时,保证信号稳定
  103.          E=0;
  104.          RS=1;
  105.          RW=0;
  106.          E=1;
  107.          lcddata=content;
  108.          E=0;
  109.          RS=0;
  110. }

  111. //   显示坐标位置的函数;
  112. void  gotoxy(uchar y,uchar x)
  113. {
  114.          if(y==1)             //第一行第一列;
  115.                 wr_i_lcd(0x80|x);   //对液晶经行写指令;
  116.          
  117.          if(y==2)             //第二行第一列;
  118.                 wr_i_lcd(0xc0|x);   //对液晶经行写指令;
  119. }

  120. //   printf输入字符串操作;
  121. void printf(uchar *str)
  122. {
  123.         while(*str!='\0')
  124.         {
  125.                 wr_d_lcd(*str);
  126.                 str++;
  127.         }
  128. }

  129. // 液晶显示主程序操作;  初始显示welcome
  130. void  show()
  131. {
  132.                 gotoxy(1,4);
  133.                 printf("welcome");        
  134. }


  135. void shezhi()  //对里面的数值进行修改
  136. {
  137.     if(!K3)    //温湿度数据大小加++;
  138.                 {  
  139.                             DelayMs(50);
  140.                             if(!K3)
  141.                       {   
  142.               while(K3==0);        
  143.                                                         if(yemian==1)
  144.                                                         {               
  145.                                                                  WenDu+=1;
  146.                                                                   if(WenDu>99) { WenDu=99; }  //温度上限加
  147.                                                         
  148.                                                          }
  149.                                                          if(yemian==2)
  150.                                                          {
  151.                                                       ShiDu+=1;
  152.                                                                   if(ShiDu>99) { ShiDu=99; }  //湿度下限加
  153.                                                                 }         
  154.                                    }
  155.                  }                 
  156.                 if(!K4)
  157.                 {  
  158.                          DelayMs(50);
  159.                          if(!K4)
  160.                                  {   
  161.                                            while(K4==0);     //按一次,防止按下不松,加多次
  162.                                                  if(yemian==1)
  163.                                                          {
  164.                                                         if(WenDu<1) {WenDu=1; }        
  165.                                                                      WenDu-=1;          //湿度下限减                                                   
  166.                                                          }                                 
  167.                                                  if(yemian==2)
  168.                                                          {
  169.                                                                     if(ShiDu<1) { ShiDu=1; }
  170.                                                                     ShiDu-=1;         //湿度下限减               
  171.                                                          }        
  172.                                  }
  173.                  }
  174. }                        

  175. // 中断初始化
  176. void Int()
  177. {
  178.                         EA=1;
  179.                         EX0=1;
  180.                         IT0=1;
  181.         
  182.                         PX0=1;     //(中断0为最高优先级)
  183.         
  184.                         EX1=1;
  185.                         IT1=1;
  186. }

  187. //   报警部分
  188. void warn()
  189. {
  190.          
  191. //         if((ShiDu>RH)||(WenDu<TH))
  192. //                {
  193. //                           SPK=1;
  194. //                     LED=1;
  195. //                }
  196. //                else
  197. //                {
  198. //                           SPK=0;        
  199. //                           LED=0;
  200. //                }        
  201.                
  202.           if(ShiDu<RH)
  203.                 {
  204.                         JDQ_ShiDu =1;     // 控制加湿器的继电器;
  205.                         SPK=1;
  206.             LED=1;
  207.                 }
  208.                 else
  209.                 {
  210.                         JDQ_ShiDu =0;     // 控制加湿器的继电器;
  211.                         SPK=0;
  212.                         LED=0;
  213.                 }
  214.                
  215.           DelayMs(200);
  216.           if(WenDu>TH)        //WenDu为设定值,TH测量值;
  217.                 {
  218.                         SPK=1;
  219.                         LED=1;
  220.                         JDQ_WenDu =1;     // 控制风扇的继电器;
  221.                 }
  222.                 else
  223.                 {
  224.                         SPK=0;
  225.                         LED=0;
  226.                         JDQ_WenDu =0;     // 控制风扇的继电器;
  227.                 }
  228.                
  229. }
  230. /***************************选择界面工作状态*********************************/
  231. void  Xuanze()
  232. {
  233. //                  key();
  234. //====================yemian==0时 进入工作状态=================================
  235.                          if(yemian==0)  
  236.                         {
  237.                                 if(flat==1)
  238.                                  {
  239.            flat=0;
  240.                                          lcd_csh(); //初始化
  241.                                          
  242.                                           gotoxy(1,0);
  243.                                                 printf("Temp:00");
  244.                                          
  245.                                           gotoxy(1,8);
  246.                                                 s[0]=0xdf;   //由一个字符串转化为一个字符;
  247.                         s[1]=0x43;        
  248.                               printf(s);               
  249.                                          
  250.                                           gotoxy(2,0);
  251.                                                 printf("Humi:00");
  252.                                                                   
  253.                                           gotoxy(2,7);
  254.                                                 printf("%RH");
  255.                                                                  
  256.                                           gotoxy(1,12);
  257.                                           printf("T:");
  258.                                                 
  259.                   s[0]=WenDu/10+0x30;   //由一个字符串转化为一个字符;
  260.                                     s[1]=WenDu%10+0x30;        
  261.                                                 printf(s);
  262. //          display(0x0e,WenDu/10+0x30);  //报警温度
  263. //                      display(0x0f,WenDu%10+0x30);
  264.                                    
  265.                                           gotoxy(2,12);
  266.                                           printf("H:");

  267.             s[0]=ShiDu/10+0x30;   //由一个字符串转化为一个字符;
  268.                                     s[1]=ShiDu%10+0x30;        
  269.                                                 printf(s);
  270. //                                  display(0x4e,ShiDu/10+0x30);  //报警湿度
  271. //                      display(0x4f,ShiDu%10+0x30);
  272.                                          
  273.           }
  274. // ***********DHT11读取显示部分************                                 
  275.                                   receive();
  276.                                         gotoxy(1,5);
  277.                                         s[0]=TH/10+0x30;   //由一个字符串转化为一个字符;
  278.                                         s[1]=TH%10+0x30;        
  279.                                         printf(s);
  280.                                                 
  281.                                         gotoxy(2,5);
  282.                                         s[0]=RH/10+0x30;   //由一个字符串转化为一个字符;
  283.                                         s[1]=RH%10+0x30;        
  284.                       printf(s);                        
  285.              }

  286. //====================yemian==1 温度设置===========================
  287.                    if(yemian==1)  //温度
  288.                             {
  289.                          if(flat==1)
  290.                                      {
  291.                flat=0;  
  292.                                                          lcd_csh(); //初始化
  293. //                                                          bee=1;
  294.                                                          gotoxy(1,0);
  295.                                                    printf("Temp max:");
  296.              }                                                
  297.                                                 shezhi();
  298.                                                 gotoxy(2,7);
  299.                                                 s[0]=WenDu/10+0x30;   //由一个字符串转化为一个字符;
  300.                                     s[1]=WenDu%10+0x30;        
  301.                                                 printf(s);
  302.                                                 
  303.                                                  SPK=1;
  304.                    LED=1;
  305.                       }               
  306. //====================yemian==1湿度设置==========================        
  307.                                 if(yemian==2)   //湿度设置
  308.                             {
  309.                          if(flat==1)
  310.                                      {
  311.                flat=0;  
  312. //                                                          bee=1;
  313.                lcd_csh(); //初始化
  314.                                                          gotoxy(1,0);
  315.                                                    printf("Humi min:");
  316.                                                  }
  317.                                                 shezhi();
  318.                                                 gotoxy(2,7);
  319.                                                 s[0]=ShiDu/10+0x30;   //由一个字符串转化为一个字符;
  320.                                     s[1]=ShiDu%10+0x30;        
  321.                                                 printf(s);
  322.                                                 
  323.                                                  SPK=1;
  324.                    LED=1;
  325.                       }
  326. }

  327. //**************************dht11测试某块*************************************//
  328. void start()           //开始信号
  329. {
  330.                 io=1;
  331.                 delay1();
  332.                 io=0;
  333.                 delay(30);          // 主机把总线拉低必须大于18ms 保证DHT11能检测到起始信号
  334.                 io=1;               //发送开始信号结束后 拉高电平延时20-40us
  335.         
  336.                 delay1();           //以下三个延时函数差不多为24us 符合要求
  337.                 delay1();
  338.                 delay1();
  339.         
  340.                 delay1();
  341.                 delay1();
  342. }
  343. uchar receive_byte()             //接收一个字节//
  344. {
  345.                 uchar i,temp;
  346.                 for(i=0;i<8;i++)    //接收8bit的数据
  347.                 {
  348.                                 while(!io);     //等待50us的低电平开始信号结束
  349.                                 delay1();       //开始信号结束之后 延时26us-28us 以下三个延时函数
  350.                                 delay1();
  351.                                 delay1();
  352.                                 temp=0;         //时间为26us-28us 表示接收的为数据'0'
  353.                                 if(io==1)
  354.                                 temp=1;         //如果26us-28us之后 还为高电平 则表示接收的数据为'1'
  355.                                 while(io);      //等待数据信号高电平 '0'为26us-28us '1'为70us
  356.                                 data_byte<<=1;  //接收的数据为高位在前 右移
  357.                                 data_byte|=temp;
  358.                 }
  359.                 return data_byte;
  360. }
  361. void receive()                   //接收数据//
  362. {
  363.                         uchar T_H,T_L,R_H,R_L,check,num_check,i;
  364.                         start();                   //开始信号//
  365.                         io=1;                      //主机设为输入 判断从机 DHT11 响应信号
  366.                         if(!io)                    //判断从机是否有低电平响应信号//
  367.                         {
  368.                                         while(!io);                 //判断从机发出 80us 的低电平响应信号是否结束//
  369.                                         while(io);                  //判断从机发出 80us 的高电平是否结束 如结束则主机进入数据接收状态
  370.                                         R_H=receive_byte();         //湿度高位
  371.                                         R_L=receive_byte();         //湿度低位
  372.                                         T_H=receive_byte();         //温度高位
  373.                                         T_L=receive_byte();         //温度低位
  374.                                         check=receive_byte();       //校验位
  375.                                         io=0;                       //当最后一bit数据接完毕后 从机拉低电平50us//
  376.                                         for(i=0;i<7;i++)            //差不多50us的延时
  377.                                         delay1();
  378.                                         io=1;                        //总线由上拉电阻拉高 进入空闲状态
  379.                                         num_check=R_H+R_L+T_H+T_L;
  380.                                         if(num_check==check)          //判断读到的四个数据之和是否与校验位相同
  381.                                         {
  382.                                                         RH=R_H;
  383.                                                         RL=R_L;
  384.                                                         TH=T_H;
  385.                                                         TL=T_L;
  386.                                                         check=num_check;
  387.                                         }
  388.                 }
  389. }
  390. /*************************串口初始化*********************************/
  391. void UsartConfiguration()
  392. {
  393.                 SCON=0x50;        //设置位方式1; REN=1(接收允许)
  394.                 TMOD=0x20;        //计数器工作方式2;  计数器T1
  395.                 PCON=0x00;        //SMOD=0;
  396.                 TH1=0xfd;         //波特率位9600bit/s;
  397.                 TL1=0xfd;
  398.                 TR1=1;                  //打开计数器;
  399.                 ES=1;             //打开接收中断;
  400.                 EA=1;             //打开总中断;
  401. }
  402. /***************************主程序*********************************/
  403. void main()
  404. {
  405.           SPK=1;
  406.             LED=1;
  407.         Int();                    //中断初始化;
  408.         lcd_csh();                //LCD1602初始化;
  409.         UsartConfiguration();     //串口初始化;
  410.         show();
  411.         DelayMs(1000);    //3s以后,进入主程序部分,初始化部分结束;
  412.         while(1)
  413.         {  
  414.                
  415.                         RI=1;
  416.                   Xuanze();
  417.                   DelayMs(200);
  418.                   if(yemian==0)  {  warn(); }
  419.         }
  420. }

  421. /*********************页面选择*****************************/
  422. void int0(void) interrupt 0  //
  423. {
  424.         
  425.          if(!K1)    //页面选择;
  426.           {  
  427.                    DelayMs(20);    //程序消抖;
  428.                         if(!K1)      
  429.                         {   
  430.                                 yemian++;
  431.                                 flat++;
  432.                                 while(!K1);
  433.                                 if(yemian>=3)                  {  yemian=0;  }
  434.                   }
  435.           }
  436. }
  437. //************手机APP发送端*************
  438. void uart() interrupt 4
  439. {
  440.         
  441. //************发送湿度部分***************************        
  442.                         RI=0;             //                                             //清除收到中断标志位;
  443.                         SBUF=RH/10+0x30;                             //将接收到的数据放回发送缓存器;
  444.                         while(!TI);                                               //等待发送数据完成;
  445.                   TI=0;                                                                                                 //清除发送中断标志位;  
  446.                         
  447.                         RI=0;                                                            //清除收到中断标志位;
  448.                         SBUF=RH%10+0x30;                              //将接收到的数据放回发送缓存器;
  449.                         while(!TI);                                               //等待发送数据完成;
  450.                   TI=0;                                                                //清除发送中断标志位;

  451.             RI=0;             //  %                                         //清除收到中断标志位;
  452.                         SBUF=37;                             //将接收到的数据放回发送缓存器;
  453.                         while(!TI);                                               //等待发送数据完成;
  454.                   TI=0;                                                                                                 //清除发送中断标志位;  
  455.                         
  456.                         RI=0;             //  R                                          //清除收到中断标志位;
  457.                         SBUF=82;                              //将接收到的数据放回发送缓存器;
  458.                         while(!TI);                                               //等待发送数据完成;
  459.                   TI=0;                                          
  460.                  
  461.                         RI=0;             //  H                                           //清除收到中断标志位;
  462.                         SBUF=72;                             //将接收到的数据放回发送缓存器;
  463.                         while(!TI);                                               //等待发送数据完成;
  464.                   TI=0;                                                                                                 //清除发送中断标志位;  
  465.                         
  466.                 for(i=0;i<10;i++)
  467.                 {
  468.                         RI=0;             //空格                                              //清除收到中断标志位;
  469.                         SBUF=32;                              //将接收到的数据放回发送缓存器;
  470.                         while(!TI);                                               //等待发送数据完成;
  471.                   TI=0;                  
  472.                 }        
  473. //************发送温度部分***************************               
  474.             RI=0;             //                                             //清除收到中断标志位;
  475.                         SBUF=TH/10+0x30;                             //将接收到的数据放回发送缓存器;
  476.                         while(!TI);                                               //等待发送数据完成;
  477.                   TI=0;                                                                       //清除发送中断标志位;  
  478.                         
  479.                         RI=0;                                                            //清除收到中断标志位;
  480.                         SBUF=TH%10+0x30;                              //将接收到的数据放回发送缓存器;
  481.                         while(!TI);                                               //等待发送数据完成;
  482.                   TI=0;                  
  483.                                                                                    //清除发送中断标志位;         
  484.             RI=0;                                                            //清除收到中断标志位;
  485.                         SBUF=96;                                     //将接收到的数据放回发送缓存器;
  486.                         while(!TI);                                               //等待发送数据完成;
  487.                   TI=0;                                                                                                 //清除发送中断标志位;  
  488.         
  489.             RI=0;                                         //清除收到中断标志位;
  490.                         SBUF=67;                               //将接收到的数据放回发送缓存器;
  491.                         while(!TI);                                         //等待发送数据完成;
  492.                   TI=0;                                              //清除发送中断标志位;  

  493.             SBUF=10;  // (换行)     
  494.                   while(!TI);                                        //等待发送数据完成;
  495.                         TI=0;                                                          //清除发送中断标志位;
  496.         
  497. }
复制代码

所有资料51hei提供下载:
无限温湿度检测f(仿真).zip (25.01 KB, 下载次数: 123)

评分

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

查看全部评分

回复

使用道具 举报

ID:807430 发表于 2021-5-19 15:32 | 显示全部楼层
分享资料,功德无量!!!
回复

使用道具 举报

ID:922803 发表于 2021-6-7 11:09 | 显示全部楼层
蜂鸣器一直会响是咋回事
回复

使用道具 举报

ID:922803 发表于 2021-6-9 11:01 | 显示全部楼层
老干爹 发表于 2021-6-7 11:09
蜂鸣器一直会响是咋回事

你可能是传感器所处环境温度高于设定值或者湿度低于设定值了程序给的温度是20  湿度40这个你可以自己更换
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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