找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2235|回复: 6
收起左侧

51单片机CO2浓度检测程序Proteus仿真图 ADC0832模数转换

  [复制链接]
ID:948122 发表于 2022-1-13 20:45 | 显示全部楼层 |阅读模式
基于51单片机proteus仿真以及程序
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif 仿真截图.png

单片机源程序如下:
  1. //程序头函数
  2. #include <reg52.h>
  3. #include <intrins.h>        //包含头文件
  4. //显示函数
  5. #include <display.h>

  6. //宏定义
  7. #define uint unsigned int
  8. #define uchar unsigned char

  9. //管脚声明
  10. sbit LED_R= P2^2;                          //红色指示灯
  11. sbit LED_G= P2^0;                          //绿色指示灯
  12. sbit FENG = P2^5;                          //蜂鸣器
  13. sbit CS   = P1^4;
  14. sbit Clk = P1^2;
  15. sbit DATI = P1^3;
  16. sbit DATO = P1^3;                        //ADC0832引脚
  17. //按键
  18. sbit Key1=P2^6;
  19. sbit Key2=P2^7;
  20. sbit Key3=P3^7;
  21. /*******************************定义全局变量********************************/
  22. unsigned char dat = 0;      //AD值
  23. unsigned char CH=0;       //通道变量
  24. unsigned int sum=0;                         //平均值计算时的总数
  25. unsigned char m=0;
  26. bit bdata flag;                                  //定义位变量
  27. uchar set;                                          //设置变量
  28. uchar   K_ZERO=40;       //传感器零点漂移,约130mV


  29. //函数声明
  30. extern void Key();
  31. /*
  32. void delay(uint z)
  33. {
  34.         uint i,j;
  35.         for(i=0;i<z;i++)
  36.         for(j=0;j<121;j++);
  37. }
  38. */

  39. //CO2浓度变量
  40. uchar temp=0;

  41. //指示灯变量

  42. uchar WARNING=150;                //报警值变量


  43. /****************************************************************************
  44. 函数功能:AD转换子程序
  45. 入口参数:CH
  46. 出口参数:dat
  47. ****************************************************************************/
  48. unsigned char adc0832(unsigned char CH)
  49. {
  50.         unsigned char i,test,adval;
  51.         adval = 0x00;
  52.         test = 0x00;
  53.         Clk = 0;       //初始化
  54.         DATI = 1;
  55.         _nop_();
  56.         CS = 0;
  57.         _nop_();
  58.         Clk = 1;
  59.         _nop_();
  60.         
  61.         
  62.         if ( CH == 0x00 )      //通道选择
  63.         {
  64.                 Clk = 0;
  65.                 DATI = 1;      //通道0的第一位
  66.                 _nop_();
  67.                 Clk = 1;
  68.                 _nop_();
  69.                 Clk = 0;
  70.                 DATI = 0;      //通道0的第二位
  71.                 _nop_();
  72.                 Clk = 1;
  73.                 _nop_();
  74.         }
  75.         else
  76.         {
  77.                 Clk = 0;
  78.                 DATI = 1;      //通道1的第一位
  79.                 _nop_();
  80.                 Clk = 1;
  81.                 _nop_();
  82.                 Clk = 0;
  83.                 DATI = 1;      //通道1的第二位
  84.                 _nop_();
  85.                 Clk = 1;
  86.                 _nop_();
  87.         }
  88.         
  89.         Clk = 0;
  90.         DATI = 1;
  91.         for( i = 0;i < 8;i++ )      //读取前8位的值
  92.         {
  93.                 _nop_();
  94.                 adval <<= 1;
  95.                 Clk = 1;
  96.                 _nop_();
  97.                 Clk = 0;
  98.                 if (DATO)
  99.                 adval |= 0x01;
  100.                 else
  101.                 adval |= 0x00;
  102.         }
  103.         for (i = 0; i < 8; i++)      //读取后8位的值
  104.         {
  105.                 test >>= 1;
  106.                 if (DATO)
  107.                 test |= 0x80;
  108.                 else
  109.                 test |= 0x00;
  110.                 _nop_();
  111.                 Clk = 1;
  112.                 _nop_();
  113.                 Clk = 0;
  114.         }
  115.         if (adval == test)      //比较前8位与后8位的值,如果不相同舍去。若一直出现显示为零,请将该行去掉
  116.         dat = test;
  117.         nop_();
  118.         CS = 1;        //释放ADC0832
  119.         DATO = 1;
  120.         Clk = 1;
  121.         return dat;
  122. }

  123. void init()                                //定时器初始化函数
  124. {
  125.         TMOD=0x01;                        //定时器工作方式
  126.          TL0=0xb0;
  127.          TH0=0x3c;                        //赋初值50ms
  128.          EA=1;                                //打开中断总开关
  129.         ET0=1;                                //打开定时器0中断允许开关
  130.          TR0=1;                                //打开定时器0定时开关
  131. }

  132. void AlcoholCalibration(void)     //CO2浓度初始化校准函数
  133. {
  134.         sum = 0;
  135.         for(m=0;m<50;m++)                        //读50次AD值
  136.         {
  137.                 sum = adc0832(0)+sum;                //读到的AD值,将读到的数据累加到sum
  138.         }
  139.         temp=sum/50;                                //跳出上面的for循环后,将累加的总数除以50得到平均值temp
  140.         K_ZERO = 500 * temp / 256;        //8位ADC,首先得到电压值,单位10毫伏
  141.         Display_1602(0,WARNING);         //显示AD数值和报警值
  142. }

  143. void main()                                //主函数
  144. {
  145.         Init1602();                                                 //初始化液晶函数
  146.         init();                                                         //初始化定时器
  147.         while(1)                                                 //进入循环
  148.         {
  149.                 for(m=0;m<50;m++)                        //读50次AD值
  150.                 sum = adc0832(0)+sum;                //读到的AD值,将读到的数据累加到sum
  151.                 temp=sum/50;                                //跳出上面的for循环后,将累加的总数除以50得到平均值temp
  152.                 if (temp > K_ZERO)
  153.                                 temp = temp - K_ZERO;              //首先减去零点漂移,一般是130mV
  154.                 else
  155.                                 temp= 0;
  156.                 sum=0;                                                 //平均值计算完成后,将总数清零
  157.                 if(set==0)                                         //set为0,说明现在不是设置状态
  158.                 Display_1602(temp,WARNING);         //显示AD数值和报警值
  159.                 if(temp<WARNING&&set==0)         //AD数值小于报警值
  160.                 {
  161.                         flag=0;                                         //关闭报警
  162.                 }
  163.                 else if(temp>WARNING&&set==0)//AD值大于报警值
  164.                 {
  165.                         flag=1;                                         //打开报警
  166.                 }
  167.                 Key();                                                 //调用按键函数
  168.         }
  169. }

  170. void Key()                                          //按键函数
  171. {
  172.         if(Key1==0)                                  //设置键按下
  173.         {
  174.                 while(Key1==0);                  //按键松开
  175.                 FENG=0;                                  //蜂鸣器响
  176.                 set++;                                  //设置变量加
  177.                 flag=0;                                  //关闭报警
  178.                 TR0=0;                                  //关闭定时器
  179.         }
  180.         if(set==1)                                  //设置报警值时
  181.         {
  182.                 write_com(0x38);//屏幕初始化
  183.                 write_com(0x80+0x40+8);//位置
  184.                 write_com(0x0f);//打开显示 无光标 光标闪烁
  185.                 write_com(0x06);//当读或写一个字符是指针后一一位
  186.                 FENG=1;                                //关闭蜂鸣器

  187.         }
  188.         else if(set>=2)                //设置完成时
  189.         {
  190.                 set=0;                        //变量清零
  191.                 write_com(0x38);//屏幕初始化
  192.                 write_com(0x0c);//打开显示 无光标 无光标闪烁
  193.                 FENG=1;                        //关闭蜂鸣器
  194.                 flag=1;                        //打开报警
  195.                 TR0=1;                        //打开定时器
  196.         }
  197.         if(Key2==0&&set!=0)                        //设置报警值时加键按下
  198.         {
  199.                 while(Key2==0);                        //按键松开
  200.                 FENG=0;                                        //打开蜂鸣器
  201.                 WARNING++;                                //报警值加
  202.                 if(WARNING>=255)                //最大加到255
  203.                 WARNING=0;                                //清零
  204.                 write_com(0x80+0x40+6);           //选中液晶屏上的第二行第7
  205.                 write_data('0'+WARNING/100);   //开始显示报警值。例如报警值是123,123除以100的商是1,加上‘0’是为了得到液晶中对应1的显示码
  206.                 write_data('0'+WARNING%100/10);//123除以100的余数是23,23再除以10得到的商是2
  207.                 write_data('0'+WARNING%100%10);//23除以10的余数是3
  208.                 write_com(0x80+0x40+8);//位置
  209.                 FENG=1;                                                //关闭蜂鸣器
  210.         }
  211.         else if(Key2==0&&set==0)
  212.         {
  213.                 AlcoholCalibration(); //CO2浓度初始值
  214.         }
  215.         if(Key3==0&&set!=0)                                //注释同加按键
  216.         {
  217.                 while(Key3==0);
  218.                 FENG=0;
  219.                 WARNING--;
  220.                 if(WARNING<=0)
  221.                 WARNING=255;
  222.                 write_com(0x80+0x40+6);
  223.                 write_data('0'+WARNING/100);
  224.                 write_data('0'+WARNING/10%10);
  225.                 write_data('0'+WARNING%10);
  226.                 write_com(0x80+0x40+8);//位置
  227.                 FENG=1;
  228.         }
  229. }

  230. void  time1_int(void) interrupt 1                  //定时器工作函数
  231. {
  232.         uchar count;                                                  //定义计时变量
  233.         TL0=0xb0;
  234.          TH0=0x3c;                                                          //重新赋初值50ms
  235.           count++;                                                          //变量加一次就是50ms
  236.         if(count==10)                                                  //加到10次就是500ms
  237.         {
  238.                 if(flag==0)                                                  //flag=0时,也就是不开启报警
  239.                 {
  240.                         LED_G=0;                                          //绿灯点亮
  241.                         LED_R=1;                                          //红灯熄灭
  242.                         FENG=1;                                                  //关闭蜂鸣器
  243.                 }
  244.                 if(flag==1)                                                  //flag为1时,也就是打开报警
  245.                 {
  246.                         LED_G=1;                                          //绿灯熄灭
  247.                         LED_R=0;                                          //红灯点亮
  248.                         FENG=0;                                                  //打开蜂鸣器
  249.                 }
  250.         }

  251.           if(count==20)                                                  //计数20次,就是1s
  252.            {                                                                          //在1s时,红绿灯都是熄灭状态,蜂鸣器也是关闭状态,装可以达到闪烁的目的
  253.                 count=0;                                                  //变量清零
  254.                 if(flag==0)                                                  //不是报警状态时
  255.                 {
  256.                         LED_G=1;
  257.                         LED_R=1;
  258.                         FENG=1;
  259.                 }
  260.                 if(flag==1)                                                  //报警状态时
  261.                 {
  262.                         LED_G=1;
  263.                         LED_R=1;
  264.                         FENG=1;
  265.                 }
  266.         }
  267. }
复制代码

所有资料51hei附件下载:
co2仿真和程序.7z (171.01 KB, 下载次数: 105)

评分

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

查看全部评分

回复

使用道具 举报

ID:948122 发表于 2022-1-13 20:50 | 显示全部楼层
补充:本人第一次发帖子不熟练,我这里还有word文档和仿真视频有需要留言
回复

使用道具 举报

ID:1015495 发表于 2022-4-3 22:09 | 显示全部楼层
楼主你好 请问关于co2测量的硬件就只需co2传感器吗?
回复

使用道具 举报

ID:1014556 发表于 2022-4-6 09:56 | 显示全部楼层
威爱吃水果123 发表于 2022-1-13 20:50
补充:本人第一次发帖子不熟练,我这里还有word文档和仿真视频有需要留言

需要,谢谢
回复

使用道具 举报

ID:284488 发表于 2022-4-6 15:02 | 显示全部楼层
感谢楼主的分享,也需要楼主提供word文档和仿真视频,谢谢!
回复

使用道具 举报

ID:940657 发表于 2022-4-19 09:47 | 显示全部楼层
谢谢楼主的启发,需要楼主word参考一下
回复

使用道具 举报

ID:1017860 发表于 2022-4-20 09:55 来自手机 | 显示全部楼层
请问楼主知不知道为什么调节滑动变阻器改变浓度的时候,液晶显示屏上的数值不改变嘛,是不是8.9版本的ADC0832的问题呀
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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