找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+GP2Y1014AU pm2.5测量+DHT11温湿度仿真设计源码

  [复制链接]
跳转到指定楼层
楼主
    这个单片机程序目前是显示PM2.5,温湿度,PM2.5传感器用的是GP2Y1014AU(模拟输出),温湿度用的是DHT11(数字输出),有个问题就是当K=Adc0832();这句放到中断里面,温湿度会变化,但是PM2.5就没有值,不会自己变化,得按一下复位键才显示值,当K=Adc0832();这句放到主函数里面,PM2.5就有值变化,但是温湿度的值没有了,按复位键也没有值。开始我怀疑中断函数影响了液晶屏的时序,但是后面直接给一个K值,PM2.5和温湿度都会变,我就找不到是哪里的问题了。有没有大神能帮忙看看是哪里的问题,程序和仿真图都在附件里。

PM2.5驱动条件:
关于驱动条件
根据LED驱动周期(脉冲周期:T (ms) ),LED驱动时间(脉冲:宽度Pw(ms) )输出电压会变动,规格书特性的规格值是脉冲周期T:10ms,脉冲宽度Pw:0.32ms,取样时间:0.28ms,根据此条件变动,规格书上规定的特性值(无尘时输出电压、检出感度)也随之变动。
   

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4.   int temp;
  5. typedef unsigned int u16;          //对数据类型进行声明定义
  6. typedef unsigned char u8;
  7. sbit LCDE=P1^2;
  8. sbit RS=P1^0;
  9. sbit RW=P1^1;
  10. sbit ADCS=P2^0;  //ADC0832 chip seclect
  11. sbit ADDO=P3^7;  //ADC0832 k in
  12. sbit ADDI=P3^7;  //ADC0832 k in
  13. sbit ADCLK=P3^6;  //ADC0832 clock signal
  14. sbit DHTIO=P2^1; //DHT11输出
  15. sbit LED=P2^7;        //LED脉冲驱动
  16. unsigned char code digit[10]={"0123456789"};
  17. volatile   uchar  K=0;//AD转换数字量
  18.    uint tempshi,tempge,humshi,humge;
  19. unsigned char  U8FLAG=0,U8temp=0;
  20. unsigned char  U8T_data_H=0,U8T_data_L=0,U8RH_data_H=0,U8RH_data_L=0,U8checkdata=0;
  21. unsigned char str[5];

  22. //humidity 湿度  
  23. //temperature 温度  
  24. //integer 整数  
  25. //decimal 小数  
  26. unsigned char humidity_interger=0,humidity_decimal;  
  27. unsigned char temperature_integer=0,temperature_decimal;  
  28. unsigned char check;  
  29.   void delay(unsigned int z) //延时长
  30. {
  31.          unsigned char x,y;
  32.          for(x=z;x>0;x--)
  33.          {
  34.                  for(y=20;y>0;y--);
  35.          }
  36. }
  37. void delay40us()  
  38. {  
  39.      unsigned char a,b;  
  40.      for(b=3;b>0;b--)  
  41.         for(a=4;a>0;a--);  
  42. }  

  43.   void delayms(uint del)  
  44. {
  45. uint u,v;
  46. for(u=0;u<del;u++)
  47.    for(v=0;v<=100;v++);
  48. }

  49. void delay20ms()  
  50. {  
  51.     unsigned char a,b,c;  
  52.     for(c=1;c>0;c--)  
  53.         for(b=222;b>0;b--)  
  54.             for(a=40;a>0;a--);  
  55. }  
  56. unsigned char Adc0832()     //AD转换,返回结果
  57. {
  58.            uchar u=0;
  59.    
  60.     uchar dat=0;

  61.         ADCLK=0;
  62.          delayms(1);
  63.         ADCS=0;//拉低CS端
  64.      delayms(1);
  65.     ADDI=1;
  66.     delayms(1);
  67.     ADCLK=1;//拉高CLK端
  68.    delayms(1);
  69.     ADCLK=0;//拉低CLK端,形成下降沿1
  70.    delayms(1);
  71.     ADCLK=1;//拉高CLK端
  72.     ADDI=1;
  73.     delayms(1);
  74.     ADCLK=0;//拉低CLK端,形成下降沿2
  75.    delayms(1);
  76.     ADCLK=1;//拉高CLK端
  77.     ADDI=1;
  78.    delayms(1);
  79.     ADCLK=0;//拉低CLK端,形成下降沿3
  80.    delayms(1);
  81.     ADDI=1;//控制命令结束
  82.     delayms(1);
  83.     dat=0;
  84.     for(u=0;u<8;u++)
  85.     {       
  86.                 ADCLK=1;
  87.          delayms(1);
  88.                 ADCLK=0;//形成一次时钟脉冲
  89.                delayms(1);
  90.                         dat|=ADDO;//收数据
  91.                         if(u<7)
  92.                 dat<<=1;
  93.     }  
  94.     for(u=0;u<8;u++)
  95.     {
  96.         
  97.         ADCLK=1;
  98.       delayms(1);
  99.         ADCLK=0;//形成一次时钟脉冲
  100.        delayms(1);
  101.     }
  102.     ADCS=1;//拉低CS端
  103.     ADCLK=0;//拉低CLK端
  104.     ADDO=1;//拉高数据端,回到初始状态
  105.    
  106.     return dat;            //return ad k
  107.        
  108. }  
  109. void dht_start()             //等待接受初始化
  110. {  
  111.      DHTIO=1;          //初始高电平  
  112.      delay40us();  
  113.      DHTIO=0;          //主机拉低电平  
  114.      delay20ms();      //保持电平时间大于18ms  
  115.      DHTIO=1;          //主机拉高电平  
  116.      delay40us();      //延迟等待20-40us等待从机响应  
  117. }  
  118.   
  119. unsigned char recieve_data() //数据接收
  120. {  
  121.     unsigned char i,flag,data_byte;  
  122.     for(i=0;i<8;i++)  
  123.     {  
  124.         flag=2;  
  125.         while((!DHTIO)&&flag++);//等待从机发出50us低电平结束  
  126.         delay40us();            //延时超过26us-28us不超过70us  
  127.         data_byte=data_byte<<1;  
  128.         if(DHTIO)                 //如果此时dhtio为1则表示此时从机输出数据为1否则说明此时从机输出数据为0  
  129.         {  
  130.             data_byte|=0x01;  
  131.             flag=2;  
  132.             while((DHTIO)&&flag++);//等待剩下的高电平结束  
  133.         }  
  134.         if(!flag)  
  135.             break;  
  136.     }                   
  137.     return data_byte;  
  138. }  
  139. void dht_take_sample()     //采样
  140. {  
  141.      unsigned char flag;  
  142.      dht_start();  
  143.      if(!DHTIO)         //从机发出响应信号  
  144.      {  
  145.           flag=2;  
  146.           while((!DHTIO)&&flag++);//检测从机发出80us低电平是否结束  
  147.           flag=2;  
  148.           while((DHTIO)&&flag++); //检测从机发出80us高电平是否结束  
  149.           //开始采集数据  
  150.           humidity_interger=recieve_data();     //采集湿度整数部分  
  151.           humidity_decimal=recieve_data();      //采集湿度小数部分  
  152.           temperature_integer=recieve_data();   //采集温度整数部分  
  153.           temperature_decimal=recieve_data();   //采集温度小数部分  
  154.           check=recieve_data();                 //采集校验位  
  155.             
  156.           DHTIO=1;  //采集数据后主机拉高电平  
  157.      }  
  158. }  







  159. void write_com(unsigned char com)   //将模式设置指令或显示地址写入液晶模块
  160. {
  161.          RS=0;
  162.          RW=0;
  163.          LCDE=0;
  164.          P0=com;
  165.          delay(5);
  166.          LCDE=1;
  167.          delay(5);
  168.          LCDE=0;
  169. }
  170. void write_date(unsigned char date)//将数据(字符ASCII码)写入液晶模块
  171. {
  172.          RS=1;
  173.          RW=0;
  174.          LCDE=0;
  175.          P0=date;
  176.          delay(5);
  177.          LCDE=1;
  178.          delay(5);
  179.          LCDE=0;
  180. }
  181. void L1602_string(unsigned char hang,unsigned char lie,unsigned char p)   //将数据写入液晶模块
  182. {
  183.         unsigned char a;
  184.         if(hang == 1) a = 0x80;                                         //显示在第一行
  185.         if(hang == 2) a = 0xc0;                                         //显示在第一行
  186.         a = a + lie -1;
  187.         write_com(a);
  188.         write_date(p);
  189. }
  190. void init()                         //1602初始化
  191. {
  192.          write_com(0x38);
  193.          write_com(0x0e);
  194.          write_com(0x06);
  195.          write_com(0x01);
  196.          write_com(0x80);
  197. }


  198. void xianshi1()          //pm2.5显示
  199. {
  200.        
  201.        
  202.     L1602_string(1,1,'P');
  203.     L1602_string(1,2,'M');
  204.     L1602_string(1,3,'2');
  205.     L1602_string(1,4,'.');
  206.     L1602_string(1,5,'5');
  207.         L1602_string(1,6,':');
  208.         L1602_string(1,7,' ');
  209.        
  210.         L1602_string(1,8,K/100+0x30);
  211.         L1602_string(1,9,(K-100*(K/100))/10+0x30);
  212.         L1602_string(1,10,K%10+0x30);
  213.         L1602_string(1,11,' ');
  214.         L1602_string(1,12,'u');
  215.         L1602_string(1,13,'g');
  216.         L1602_string(1,14,'/');                               
  217.         L1602_string(1,15,'m');       
  218.         L1602_string(1,16,'3');

  219.     L1602_string(2,1,'T');
  220.         L1602_string(2,2,'e');
  221.         L1602_string(2,3,'m');
  222.         L1602_string(2,4,'p');
  223.         L1602_string(2,5,':');
  224.         L1602_string(2,6,digit[tempshi]);
  225.     L1602_string(2,7,digit[tempge]);       
  226.         L1602_string(2,8,'C');
  227.         L1602_string(2,9,' ');
  228.         L1602_string(2,10,'H');
  229.         L1602_string(2,11,'u');
  230.         L1602_string(2,12,'m');
  231.         L1602_string(2,13,':');
  232.         L1602_string(2,14,digit[humshi]);
  233.                 //L1602_string(2,14,(K-100*(K/100))/10+0x30);
  234.         L1602_string(2,15,digit[humge]);
  235.         //L1602_string(2,15,K%10+0x30);
  236.         L1602_string(2,16,'%');
  237. }
  238. void readDH() //温湿度读取
  239. {                  
  240.                  dht_start();
  241.                  recieve_data();
  242.                  dht_take_sample();
  243.                  humshi=humidity_interger/10;
  244.                  humge=humidity_interger%10;
  245.                  tempshi=temperature_integer/10;
  246.                  tempge=temperature_integer%10;
  247. }

  248. void Timer0Init()
  249. {  
  250.     RW=0;
  251.     LED=0;
  252.         TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
  253.         TH0=(65536-10000)%256;
  254.         TL0=(65536-10000)/256; //定时10ms        
  255.         ET0=1;//打开定时器0中断允许
  256.         EA=1;//打开总中断
  257.         TR0=1;//打开定时器       
  258.                
  259. }

  260. void main()           //主函数
  261. {               
  262.                   int liu=0;
  263.                   LCDE=0;
  264.          init();
  265.                 Timer0Init();
  266.                  
  267.          while(1)
  268.          {
  269.                
  270.                            //liu++;
  271.                         // if(liu==245)
  272.                          //liu=0;
  273.                         // K=Adc0832();
  274.                          readDH();
  275.                           xianshi1();
  276.                  }
  277. }

  278. /**************************************
  279. /*****定时器0中断服务程序****/
  280. void Timer0() interrupt 1
  281. {
  282.         static u16 j;
  283.    
  284.                    // temp++;
  285. TH0 = (65536-10000)%256;   
  286. TL0 = (65536-10000)/256;     
  287.   
  288.      LED=1;
  289.       //开启传感器的LED
  290.      for (j=0;j<222;j++);  //0.28ms  //延时0.28ms
  291.                    K=Adc0832();  //开启ADC采集
  292.         /*        if(temp==20){
  293.                          K+=40;
  294.                         temp=0;
  295.                 }          */
  296.                 //if(K>240)
  297.                 //K=0;
  298.                      //xianshi1();
  299.           TR0 = 0;   //先关闭定时器0
  300.      EA = 0;
  301.           
  302. LED=0;
  303. }  
  304.          
复制代码


所有资料51hei提供下载:
压缩文件.rar (75.7 KB, 下载次数: 462)


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

使用道具 举报

沙发
ID:272459 发表于 2018-5-17 15:09 | 只看该作者
你AD值都没传出来,K=adc0832()  K要么是0 要么是1;
回复

使用道具 举报

板凳
ID:327052 发表于 2018-5-17 18:03 | 只看该作者
abcarry 发表于 2018-5-17 15:09
你AD值都没传出来,K=adc0832()  K要么是0 要么是1;

哥能发我一分吗
回复

使用道具 举报

地板
ID:130743 发表于 2019-3-11 09:14 | 只看该作者
感谢楼主分享
回复

使用道具 举报

5#
ID:480151 发表于 2019-3-19 07:45 | 只看该作者
感谢楼主分享,有电路连接图吗?
回复

使用道具 举报

6#
ID:521658 发表于 2019-4-27 19:51 | 只看该作者
仿真图里没有dht11和pm2.5的传感器吗
回复

使用道具 举报

7#
ID:509243 发表于 2019-5-19 20:59 来自手机 | 只看该作者
解决了吗兄弟,我的pm怎么一直不显示,能把新的发我一份哦啊,13122319913@163.com,谢谢
回复

使用道具 举报

8#
ID:250245 发表于 2020-5-9 13:35 | 只看该作者
应该是AD转换是需要时间的,AD转换放在定时器里面,导致你while循环的延时函数不准,DHT11无法满足时序,可以将AD循环放在主函数,定时器里面计数,当到达0.28ms的时候AD转换,然后在检测DHT11,检测完以后继续等待下一个0.28ms
回复

使用道具 举报

9#
ID:250245 发表于 2020-5-9 13:36 | 只看该作者
而且你定时器里还有一个280us的延时,这个远远操过了DHT11的30和20us的延时
回复

使用道具 举报

10#
ID:1112270 发表于 2024-3-11 13:59 | 只看该作者
请问你解决了嘛,我做pm2.5检测,传感器输出电压太低,没有任何显示
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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