单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:2687|回复:2
打印上一主题下一主题

单片机酒精浓度检测仪设计资料

[复制链接]
跳转到指定楼层
楼主
ID:339166发表于 2018-5-27 16:38|显示全部楼层回帖奖励
本设计基于STC12C5A16AD单片机设计的酒精气体浓度探测仪,可用来检测酒精气体浓度,酒精气体浓度测试仪在生产生活中有重要的应用,比如,在一些环境要求严格的生产车间,用这种酒精浓度探测仪,可随时检测车间内的酒精气体浓度,当酒精气体浓度高于允许限定值时,发出警报,提醒人们及时通风换气,做到安全生产,此酒精测试仪经过再一步的改进可以使用到酒后驾驶测试上面去,利用该测试仪来告诫驾驶员请勿酒后驾驶。
在这次的设计中,利用了MQ-3型酒精的传感器通过对空气中的酒精浓度测试转换成0~5V的模拟量电压进行输出,把这个0~5V的电压传送到STC12C5A16AD内部自带的A/D转换模块中去,通过模拟量模块的转换输出一个8位0~255的数据给单片机的P1口,再通过单片机进行一些软件程序的处理显示在LCD的液晶上面。

  1. #include "STC12c5A.h"
  2. #include "1602.h"
  3. #include "2402.h"

  4. #define uchar unsigned char
  5. #define uint  unsigned int

  6. //声明常量
  7. #define ALCH     80     //醉驾标准80mg/L
  8. //K_MG_MV和K_ZERO为传感器校准系数,要根据每个MQ-3模块校准
  9. #define K_MG_MV   160/66  //传感器灵敏度系数,每毫克/L对应的10毫伏数
  10. #define K_ZERO     0     //传感器零点漂移,约130mV

  11. //定义按键
  12. sbit Key_Up = P3^6;
  13. sbit Key_Down = P3^7;

  14. //定义LED报警灯
  15. sbit Led_Warn1 = P3^4;
  16. sbit Led_Warn2 = P3^5;

  17. //定义乙醇传感器TTL电平输出引脚
  18. sbit DOUT = P1^4;

  19. //定义标识
  20. volatile bit FlagStartAL = 0;  //开始转换标志
  21. volatile bit FlagKeyPress = 0; //有键弹起标志

  22. //全局变量定义
  23. uchar Threshold;             //酒精浓度上限报警值
  24. uint  ALCounter;           //酒精转换计时器
  25. uint   ALValue;             //酒精测量值
  26. float ALtemp;               //计算临时变量

  27. uint keyvalue, keyUp, keyDown; //键值
  28. char * pSave;             //EEPROM存盘用指针

  29. //函数声明
  30. void Data_Init();
  31. void Timer0_Init();
  32. void Port_Init();
  33. void ADC_Init();
  34. uchar GetADVal();
  35. void KeyProcess(uint );

  36. //数据初始化
  37. void Data_Init()
  38. {
  39.    ALCounter = 0;
  40.    ALValue = 0;
  41.    Led_Warn1 = 1;
  42.    Led_Warn2 = 2;
  43.    keyvalue = 0;
  44.    keyUp = 1;
  45.    keyDown = 1;
  46. }

  47. //定时器0初始化,中断时间约2毫秒
  48. //计算:晶振11.0592MHz,定时器时钟11059200/12=921600,每毫秒922个脉冲
  49. //     16位定时器初值65536-1844=63692=0xf8cc
  50. void Timer0_Init()
  51. {
  52.      ET0 = 1;       //允许定时器0中断
  53.      TMOD = 1;     //定时器工作方式选择
  54.      TL0 = 0xcc;     //
  55.      TH0 = 0xf8;     //定时器赋予初值,大约为2毫秒中断1次
  56.      TR0 = 1;       //启动定时器
  57. }

  58. //定时器0中断
  59. void Timer0_ISR (void) interrupt 1 using 0
  60. {
  61.      TL0 = 0xcc;
  62.      TH0 = 0xf8;     //定时器赋予初值

  63.      //每1秒钟启动一次AD转换
  64.    ALCounter ++;
  65.    if (ALCounter >= 500)
  66.    {
  67.      FlagStartAL = 1;
  68.        ALCounter = 0;
  69.    }
  70. }

  71. void Port_Init()  //设定AD启动;
  72. {
  73.    P1M0 = 0x80;     //10000000,P1.7作为AD输入;
  74.    P1M1 = 0x80;     //
  75. }

  76. void ADC_Init()
  77. {
  78.    uint i;
  79.    P1ASF = 0x80;         //设P1.7为AD输入
  80.    ADC_RES = 0;           //清先前的结果
  81.    ADC_CONTR|=0x80;           //POWER=1,打开ADC电源
  82.    for(i=5000;i>0;i--) ; //延时
  83.    ADC_CONTR = ADC_CONTR&0xE0; //1110,0000 清ADC_FLAG,ADC_START位和低3位
  84.    ADC_CONTR = ADC_CONTR&0xf8|0x07; //设置当前通道号为P1.7
  85.    for(i=2500;i>0;i--) ; //延时

  86. }

  87. //进行AD转换,得到当前酒精值
  88. uchar GetADVal()
  89. {
  90.    uint i;
  91.    ADC_CONTR&=0xf7;
  92.    for(i=250;i>0;i--);       //待输入电压稳定后开始转换
  93.    //ADC_RES = 0;
  94.    ADC_CONTR |= 0x08;       //ADC_Start=1, 启动转换
  95.    while((ADC_CONTR&0x10)==0); //等待转换结束ADC_FLAG=1
  96.    ADC_CONTR&=0xe7;             //清ADC_FLAG和ADC_START位,停止转换
  97.    return ADC_RES;
  98. }

  99. //存入设定值
  100. void Save_Setting()
  101. {
  102.    pSave =  (char *)&Threshold;       //地址低位对应低8位,高位对应高8位
  103.    wrteeprom(0, *pSave);         //存醉酒阈值低8位
  104.    DELAY(300);
  105.    pSave ++;
  106.    wrteeprom(1, *pSave);         //存醉酒阈值高8位
  107.    DELAY(300);
  108. }

  109. //载入设定值
  110. void Load_Setting()
  111. {
  112.    pSave =  (char *)&Threshold;
  113.    *pSave++ = rdeeprom(0);
  114.    *pSave = rdeeprom(1);
  115.    if ((Threshold>=255)||(Threshold<0)) Threshold = 80;
  116. }

  117. //按键处理程序,参数为键值,1为Up键,2为Down键
  118. void KeyProcess(uint num)
  119. {
  120.    switch (num)
  121.    {
  122.      case 1:
  123.          if (Threshold<255) Threshold++;
  124.          break;
  125.        case 2:
  126.          if (Threshold>1) Threshold--;
  127.          break;
  128.        default:
  129.          break;
  130.    }
  131.    L1602_int(2,9,Threshold);
  132.    Save_Setting();
  133. }

  134. void main()
  135. {
  136.    uint i,j;

  137.    EA = 0;
  138.    Data_Init();     //数据初始化
  139.    Timer0_Init();   //定时器0初始化
  140.    Port_Init();     //端口初始化
  141.    ADC_Init();     //ADC初始化
  142.    EA = 1;
  143.    L1602_init();
  144.    L1602_string(1,1,"Welcome to ALCT! ");
  145.    L1602_string(2,1,"Lijiang Nbjsxy  ");
  146.    //L1602_string(2,1,"Designed by AAA  ");
  147.    //延时
  148.    for (i=0;i<1000;i++)
  149.      for (j=0;j<1000;j++)
  150.          {;}
  151.    //清屏
  152.    L1602_string(1,1,"           ");
  153.    L1602_string(2,1,"           ");
  154.    L1602_string(1,1,"Alcohol:   mg/L");
  155.    L1602_string(2,1,"Setting:   mg/L");
  156.    //载入设定值
  157.    Load_Setting();
  158.    L1602_int(2,9,Threshold);
  159.    while(1)
  160.    {
  161.      //如果FlagStartAL标志置位,则进行AD转换
  162.        if (FlagStartAL == 1)
  163.        {
  164.          //酒精浓度换算,50mg/L=62.5ppm,传感器灵敏度应事先校准
  165.        ALValue = 500 * GetADVal() / 256;       //8位ADC,首先得到电压值,单位10毫伏
  166.          ALValue = ALValue - K_ZERO;           //首先减去零点漂移,一般是130mV
  167.            if (ALValue< 0) ALValue = 0;              
  168.            ALValue = ALValue * K_MG_MV;         //将mV转变成mg/L,K_MG_MV系数需要校准        
  169.        L1602_int(1,9,ALValue);
  170.            if (ALValue > Threshold) Led_Warn1 = 0;  //超过阈值,则 Led_Warn1灯报警,否则报警灯灭。
  171.            else Led_Warn1 = 1;
  172.            FlagStartAL = 0;
  173.        }
  174.      //查询乙醇传感器TTL电平,该指示灯为传感器模块报警
  175.        if (DOUT == 0)  Led_Warn2 = 0;
  176.        else         Led_Warn2 = 1;
  177.        //键盘查询,在弹起时响应
  178.        if ((Key_Up)&&(keyUp==0)) {FlagKeyPress = 1; keyvalue = 1;}
  179.      else if ((Key_Down)&&(keyDown==0)) {FlagKeyPress = 1; keyvalue = 2;}
  180.        if (FlagKeyPress == 1)
  181.        {
  182.        KeyProcess(keyvalue);
  183.        FlagKeyPress = 0;        
  184.        }
  185.      if (!Key_Up) keyUp = 0;
  186.        else keyUp = 1;
  187.      if (!Key_Down) keyDown = 0;
  188.        else keyDown = 1;
  189.        DELAY(100);
  190.    }
  191. }
复制代码


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

Powered by 单片机教程网