查看:2687|回复:2
本设计基于STC12C5A16AD单片机设计的酒精气体浓度探测仪,可用来检测酒精气体浓度,酒精气体浓度测试仪在生产生活中有重要的应用,比如,在一些环境要求严格的生产车间,用这种酒精浓度探测仪,可随时检测车间内的酒精气体浓度,当酒精气体浓度高于允许限定值时,发出警报,提醒人们及时通风换气,做到安全生产,此酒精测试仪经过再一步的改进可以使用到酒后驾驶测试上面去,利用该测试仪来告诫驾驶员请勿酒后驾驶。
在这次的设计中,利用了MQ-3型酒精的传感器通过对空气中的酒精浓度测试转换成0~5V的模拟量电压进行输出,把这个0~5V的电压传送到STC12C5A16AD内部自带的A/D转换模块中去,通过模拟量模块的转换输出一个8位0~255的数据给单片机的P1口,再通过单片机进行一些软件程序的处理显示在LCD的液晶上面。
- #include "STC12c5A.h"
- #include "1602.h"
- #include "2402.h"
- #define uchar unsigned char
- #define uint unsigned int
- //声明常量
- #define ALCH 80 //醉驾标准80mg/L
- //K_MG_MV和K_ZERO为传感器校准系数,要根据每个MQ-3模块校准
- #define K_MG_MV 160/66 //传感器灵敏度系数,每毫克/L对应的10毫伏数
- #define K_ZERO 0 //传感器零点漂移,约130mV
- //定义按键
- sbit Key_Up = P3^6;
- sbit Key_Down = P3^7;
- //定义LED报警灯
- sbit Led_Warn1 = P3^4;
- sbit Led_Warn2 = P3^5;
- //定义乙醇传感器TTL电平输出引脚
- sbit DOUT = P1^4;
- //定义标识
- volatile bit FlagStartAL = 0; //开始转换标志
- volatile bit FlagKeyPress = 0; //有键弹起标志
- //全局变量定义
- uchar Threshold; //酒精浓度上限报警值
- uint ALCounter; //酒精转换计时器
- uint ALValue; //酒精测量值
- float ALtemp; //计算临时变量
- uint keyvalue, keyUp, keyDown; //键值
- char * pSave; //EEPROM存盘用指针
- //函数声明
- void Data_Init();
- void Timer0_Init();
- void Port_Init();
- void ADC_Init();
- uchar GetADVal();
- void KeyProcess(uint );
- //数据初始化
- void Data_Init()
- {
- ALCounter = 0;
- ALValue = 0;
- Led_Warn1 = 1;
- Led_Warn2 = 2;
- keyvalue = 0;
- keyUp = 1;
- keyDown = 1;
- }
- //定时器0初始化,中断时间约2毫秒
- //计算:晶振11.0592MHz,定时器时钟11059200/12=921600,每毫秒922个脉冲
- // 16位定时器初值65536-1844=63692=0xf8cc
- void Timer0_Init()
- {
- ET0 = 1; //允许定时器0中断
- TMOD = 1; //定时器工作方式选择
- TL0 = 0xcc; //
- TH0 = 0xf8; //定时器赋予初值,大约为2毫秒中断1次
- TR0 = 1; //启动定时器
- }
- //定时器0中断
- void Timer0_ISR (void) interrupt 1 using 0
- {
- TL0 = 0xcc;
- TH0 = 0xf8; //定时器赋予初值
- //每1秒钟启动一次AD转换
- ALCounter ++;
- if (ALCounter >= 500)
- {
- FlagStartAL = 1;
- ALCounter = 0;
- }
- }
- void Port_Init() //设定AD启动;
- {
- P1M0 = 0x80; //10000000,P1.7作为AD输入;
- P1M1 = 0x80; //
- }
- void ADC_Init()
- {
- uint i;
- P1ASF = 0x80; //设P1.7为AD输入
- ADC_RES = 0; //清先前的结果
- ADC_CONTR|=0x80; //POWER=1,打开ADC电源
- for(i=5000;i>0;i--) ; //延时
- ADC_CONTR = ADC_CONTR&0xE0; //1110,0000 清ADC_FLAG,ADC_START位和低3位
- ADC_CONTR = ADC_CONTR&0xf8|0x07; //设置当前通道号为P1.7
- for(i=2500;i>0;i--) ; //延时
- }
- //进行AD转换,得到当前酒精值
- uchar GetADVal()
- {
- uint i;
- ADC_CONTR&=0xf7;
- for(i=250;i>0;i--); //待输入电压稳定后开始转换
- //ADC_RES = 0;
- ADC_CONTR |= 0x08; //ADC_Start=1, 启动转换
-
while((ADC_CONTR&0x10)==0); //等待转换结束ADC_FLAG=1
- ADC_CONTR&=0xe7; //清ADC_FLAG和ADC_START位,停止转换
- return ADC_RES;
- }
- //存入设定值
- void Save_Setting()
- {
- pSave = (char *)&Threshold; //地址低位对应低8位,高位对应高8位
- wrteeprom(0, *pSave); //存醉酒阈值低8位
- DELAY(300);
- pSave ++;
- wrteeprom(1, *pSave); //存醉酒阈值高8位
- DELAY(300);
- }
- //载入设定值
- void Load_Setting()
- {
- pSave = (char *)&Threshold;
- *pSave++ = rdeeprom(0);
- *pSave = rdeeprom(1);
-
if ((Threshold>=255)||(Threshold<0)) Threshold = 80;
- }
- //按键处理程序,参数为键值,1为Up键,2为Down键
- void KeyProcess(uint num)
- {
- switch (num)
- {
- case 1:
- if (Threshold<255) Threshold++;
- break;
- case 2:
- if (Threshold>1) Threshold--;
- break;
- default:
- break;
- }
- L1602_int(2,9,Threshold);
- Save_Setting();
- }
- void main()
- {
- uint i,j;
- EA = 0;
- Data_Init(); //数据初始化
- Timer0_Init(); //定时器0初始化
- Port_Init(); //端口初始化
- ADC_Init(); //ADC初始化
- EA = 1;
- L1602_init();
- L1602_string(1,1,"Welcome to ALCT! ");
- L1602_string(2,1,"Lijiang Nbjsxy ");
-
//L1602_string(2,1,"Designed by AAA ");
- //延时
- for (i=0;i<1000;i++)
- for (j=0;j<1000;j++)
- {;}
- //清屏
- L1602_string(1,1," ");
- L1602_string(2,1," ");
-
L1602_string(1,1,"Alcohol: mg/L");
-
L1602_string(2,1,"Setting: mg/L");
- //载入设定值
- Load_Setting();
- L1602_int(2,9,Threshold);
- while(1)
- {
- //如果FlagStartAL标志置位,则进行AD转换
- if (FlagStartAL == 1)
- {
- //酒精浓度换算,50mg/L=62.5ppm,传感器灵敏度应事先校准
- ALValue = 500 * GetADVal() / 256; //8位ADC,首先得到电压值,单位10毫伏
- ALValue = ALValue - K_ZERO; //首先减去零点漂移,一般是130mV
- if (ALValue< 0) ALValue = 0;
- ALValue = ALValue * K_MG_MV; //将mV转变成mg/L,K_MG_MV系数需要校准
- L1602_int(1,9,ALValue);
- if (ALValue > Threshold) Led_Warn1 = 0; //超过阈值,则 Led_Warn1灯报警,否则报警灯灭。
- else Led_Warn1 = 1;
- FlagStartAL = 0;
- }
- //查询乙醇传感器TTL电平,该指示灯为传感器模块报警
- if (DOUT == 0) Led_Warn2 = 0;
- else Led_Warn2 = 1;
- //键盘查询,在弹起时响应
- if ((Key_Up)&&(keyUp==0)) {FlagKeyPress = 1; keyvalue = 1;}
-
else if ((Key_Down)&&(keyDown==0)) {FlagKeyPress = 1; keyvalue = 2;}
- if (FlagKeyPress == 1)
- {
- KeyProcess(keyvalue);
- FlagKeyPress = 0;
- }
- if (!Key_Up) keyUp = 0;
- else keyUp = 1;
- if (!Key_Down) keyDown = 0;
- else keyDown = 1;
- DELAY(100);
- }
- }