本设计仅供参考
基于51单片机的酒精浓度检测仪设计(proteus仿真+程序+原理图+报告)
原理图:Altium Designer
仿真:proteus 8.9
程序编译器:keil 4/keil 5
编程语言:C语言
编号C0031
功能说明:
由STC89C51单片机+MQ-3酒精传感器+ADC0832模块+LCD1602模块+报警模块+电源构成。
1、LCD1602实时显示酒精浓度;
2、可以按键设置报警值,实现声光报警;三个按键:设置键、加键、减键;
3、当浓度未超过阀值时,绿灯闪烁;当超过阈值时,红灯闪烁并蜂鸣器报警;
开题报告
交通事故已成为对人类生命安全威协最大的“第一公害”。全球每年有50万人因车祸丧生。引起交通事故的基本因素有人、车、路、环境与管理等,其中驾驶员本身因素占70%。而酒后驾车是驾驶员驾驶事故重要因素之一。
世界各国统计,30%~50%的交通事故由饮酒后驾车所至。我国交通部门报道,酒后驾车的交通事故率比平常人高出至少5~6倍。在1989~1990年中,因酒后驾车引起的交通事故平均每年高达3万余起。
我国交通法规规定:禁止酒后驾车。在我们的调查中,驾驶员承认有酒后驾车者达11.99%,且有2.43%的驾驶员经常酒后驾车。酒后驾车与车祸的关系是无可辩驳的。
美国近46%的交通事故与酒精有关,且酒后驾车是美国车祸的三种主要危险因素之一。联邦德国有70%的交通事故与酒后开车有关。美、日等国的研究表明,血液中酒精浓度为0.03%、0.09%、0.15%时,驾驶能力分别可下10%、25%、30%。饮酒可致驾驶员视觉功能、触觉敏感度、判断能力、注意力等下降,从而致交通事故的发生。
目前,我国对于酒后驾车行为的监控主要采取出动警力,定期抽查的方式。但由于人员有限等原因,管理仍存在一定的难度。交管部门对此也非常苦恼。由于酒后驾车的危害,交管部门加大处罚力度。
现在一经查出是酒后驾驶的,即使只喝了一小口,将处以50元罚款,吊扣驾驶证3个月,记6分;发现是醉酒驾驶的,将处以200元罚款,吊扣驾驶证6—12个月,记12分以及行政拘留15天。酒后驾车造成死亡1人或重伤3人以上的,将处以3年以上、7年以下有期徒刑。
需要注意的是,乘车人若明知驾驶人员饮酒了却依然乘坐,那么乘车者也将被处以警告或10元以上30元以下罚款。在英国,酒后驾车等于失去工作。因为他们上班的主要的交通工具就是汽车。
酒后驾车造成的交通事故对国家、他人、自己产生了难以估计的后果。为了减少这种现象的出现,世界各国都在想办法来解决这个问题。
二、项目概述
酒精浓度检测仪主要是用来检测酒精浓度的,它主要由酒精传感器、A/D模数转换器、MSC-51单片机、LCD数码管显示、键盘以及声光报警构成。
酒精传感器将检测到的酒精浓度转化为电信号,然后将电信号传送给模数转换器,经过模数转换器转换后,把转换后得到的数字信号传给单片机,单片机对所输入的数字信号进行分析处理,最后将分析处理的结果通过显示器显示出来。
由于不同的环境对酒精浓度的要求也不一样,所以,可以通过键盘来设定不同环境中酒精浓度的不同阀值。如果所检测到的空气中的酒精浓度超过了所设定的阀值,那么单片机将会控制小灯和蜂鸣器报警,用来提示。
本设计还加了继电器模块。当浓度超过阀值时,继电器吸合,可以切断汽车发动机等,这样更加智能。
三、实施方案
系统的主要是酒精的检测,所以传感器要选择合适的。FSS-A80型电化学酒精传感器是一种电化学库仑分析池型酒精浓度检测器件,专门用于呼气中酒精浓度检测。它的基本特征是:更好的准确性、极好的稳定性、极高灵敏度和较快的响应速度、较好的抗湿性能、对口气没有响应。
FSS-A80型电化学酒精传感的工作电流不到一个微安,功耗极低。FSS-A80型电化学酒精传感器适宜于呼气中酒精浓度的检测,用于警用酒精检测装置、汽车点火控制系统等。
MQ-3 酒精传感器是气敏传感器,其具有很高的灵敏度、良好的选择性、长期的使用寿命和可靠的稳定性。MQ-3 型气敏传感器由微型Al2O3、陶瓷管和SnO2 敏感层、测量电极和加热器构成的敏感元件固定在塑料或者不锈钢的腔体内,加热器为气敏元件的工作提供了必要的工作条件。
传感器的标准回路有两部分组成:其一为加热回路;其二为信号输出回路,它可以准确反映传感器表面电阻的变化。传感器表面电阻RS 的变化,是通过与其串联的负载电阻RL 上的有效电压信号VRL 输出面获得的。二者之间的关系表述为:RS/RL=(VC-VRL)/VRL,其中VC 为回路电压,10V。负载电阻RL 可调为0.5~200K,加热电压Uh 为5V。
上述这些参数使得传感器输出电压为0~5V。MQ3 型气敏传感器的结构和外形如图一所示,标准回路如图二所示,传感器阻值变化率与酒精浓度、外界温度的关系如图三所示。为了使测量的精度达到最高,误差最小,需要找到合适的温度,一般在测量前需要将传感器预热5 分钟。
经过对比,两者都可以用来测量,但是电化学的传感器价格要比MQ-3贵十几倍,所以本设计从经费上考虑选用MQ-3酒精传感器。
仿真
程序:
//程序头函数
#include <reg52.h>
#include <intrins.h> //包含头文件
//显示函数
#include <display.h>
#include "eeprom52.h"
//宏定义
#define uint unsigned int
#define uchar unsigned char
//管脚声明
sbit LED_R= P2^2; //红色指示灯
sbit LED_G= P2^0; //绿色指示灯
sbit FENG = P2^5; //蜂鸣器
sbit CS = P1^4;
sbit Clk = P1^2;
sbit DATI = P1^3;
sbit DATO = P1^3; //ADC0832引脚
//按键
sbit Key1=P2^6;
sbit Key2=P2^7;
sbit Key3=P3^7;
/*******************************定义全局变量********************************/
unsigned char dat = 0; //AD值
unsigned char CH=0; //通道变量
unsigned int sum=0; //平均值计算时的总数
unsigned char m=0;
bit bdata flag; //定义位变量
uchar set; //设置变量
uchar K_ZERO=40; //传感器零点漂移,约130mV
//函数声明
extern void Key();
/*
void delay(uint z)
{
uint i,j;
for(i=0;i<z;i++)
for(j=0;j<121;j++);
}
*/
//酒精含量变量
uchar temp=0;
//指示灯变量
uchar WARNING=25; //报警值变量
/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
SectorErase(0x2000);
byte_write(0x2000, WARNING);
byte_write(0x2060, a_a);
}
/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
WARNING = byte_read(0x2000);
a_a = byte_read(0x2060);
}
/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
read_eeprom(); //先读
if(a_a != 1) //新的单片机初始单片机内问eeprom
{
WARNING = 25;
a_a = 1;
write_eeprom(); //保存数据
}
}
/****************************************************************************
函数功能:AD转换子程序
入口参数:CH
出口参数:dat
****************************************************************************/
unsigned char adc0832(unsigned char CH)
{
unsigned char i,test,adval;
adval = 0x00;
test = 0x00;
Clk = 0; //初始化
DATI = 1;
_nop_();
CS = 0;
_nop_();
Clk = 1;
_nop_();
if ( CH == 0x00 ) //通道选择
{
Clk = 0;
DATI = 1; //通道0的第一位
_nop_();
Clk = 1;
_nop_();
Clk = 0;
DATI = 0; //通道0的第二位
_nop_();
Clk = 1;
_nop_();
}
else
{
Clk = 0;
DATI = 1; //通道1的第一位
_nop_();
Clk = 1;
_nop_();
Clk = 0;
DATI = 1; //通道1的第二位
_nop_();
Clk = 1;
_nop_();
}
Clk = 0;
DATI = 1;
for( i = 0;i < 8;i++ ) //读取前8位的值
{
_nop_();
adval <<= 1;
Clk = 1;
_nop_();
Clk = 0;
if (DATO)
adval |= 0x01;
else
adval |= 0x00;
}
for (i = 0; i < 8; i++) //读取后8位的值
{
test >>= 1;
if (DATO)
test |= 0x80;
else
test |= 0x00;
_nop_();
Clk = 1;
_nop_();
Clk = 0;
}
if (adval == test) //比较前8位与后8位的值,如果不相同舍去。若一直出现显示为零,请将该行去掉
dat = test;
nop_();
CS = 1; //释放ADC0832
DATO = 1;
Clk = 1;
return dat;
}
void init() //定时器初始化函数
{
TMOD=0x01; //定时器工作方式
TL0=0xb0;
TH0=0x3c; //赋初值50ms
EA=1; //打开中断总开关
ET0=1; //打开定时器0中断允许开关
TR0=1; //打开定时器0定时开关
}
void AlcoholCalibration(void) //酒精初始化校准函数
{
sum = 0;
for(m=0;m<50;m++) //读50次AD值
{
sum = adc0832(0)+sum; //读到的AD值,将读到的数据累加到sum
}
temp=sum/50; //跳出上面的for循环后,将累加的总数除以50得到平均值temp
K_ZERO = 500 * temp / 256; //8位ADC,首先得到电压值,单位10毫伏
Display_1602(0,WARNING); //显示AD数值和报警值
}
void main() //主函数
{
Init1602(); //初始化液晶函数
init(); //初始化定时器
init_eeprom(); //开始初始化保存的数据
while(1) //进入循环
{
for(m=0;m<50;m++) //读50次AD值
sum = adc0832(0)+sum; //读到的AD值,将读到的数据累加到sum
temp=sum/50; //跳出上面的for循环后,将累加的总数除以50得到平均值temp
if (temp > K_ZERO)
temp = temp - K_ZERO; //首先减去零点漂移,一般是130mV
else
temp= 0;
sum=0; //平均值计算完成后,将总数清零
if(set==0) //set为0,说明现在不是设置状态
Display_1602(temp,WARNING); //显示AD数值和报警值
if(temp<WARNING&&set==0) //AD数值小于报警值
{
flag=0; //关闭报警
}
else if(temp>WARNING&&set==0)//AD值大于报警值
{
flag=1; //打开报警
}
Key(); //调用按键函数
}
}
void Key() //按键函数
{
if(Key1==0) //设置键按下
{
while(Key1==0); //按键松开
FENG=0; //蜂鸣器响
set++; //设置变量加
flag=0; //关闭报警
TR0=0; //关闭定时器
}
if(set==1) //设置报警值时
{
write_com(0x38);//屏幕初始化
write_com(0x80+0x40+7);//位置
write_com(0x0f);//打开显示 无光标 光标闪烁
write_com(0x06);//当读或写一个字符是指针后一一位
FENG=1; //关闭蜂鸣器
}
else if(set>=2) //设置完成时
{
set=0; //变量清零
write_com(0x38);//屏幕初始化
write_com(0x0c);//打开显示 无光标 无光标闪烁
FENG=1; //关闭蜂鸣器
flag=1; //打开报警
TR0=1; //打开定时器
}
if(Key2==0&&set!=0) //设置报警值时加键按下
{
while(Key2==0); //按键松开
FENG=0; //打开蜂鸣器
WARNING++; //报警值加
if(WARNING>=255) //最大加到255
WARNING=0; //清零
write_com(0x80+0x40+5); //选中液晶屏上的第二行第十一列
write_data('0'+WARNING/100); //开始显示报警值。例如报警值是123,123除以100的商是1,加上‘0’是为了得到液晶中对应1的显示码
write_data('0'+WARNING%100/10);//123除以100的余数是23,23再除以10得到的商是2
write_data('0'+WARNING%100%10);//23除以10的余数是3
write_com(0x80+0x40+7);//位置
FENG=1; //关闭蜂鸣器
write_eeprom(); //保存数据
}
else if(Key2==0&&set==0)
{
AlcoholCalibration(); //酒精初始化校准
}
if(Key3==0&&set!=0) //注释同加按键
{
while(Key3==0);
FENG=0;
WARNING--;
if(WARNING<=0)
WARNING=255;
write_com(0x80+0x40+5);
write_data('0'+WARNING/100);
write_data('0'+WARNING/10%10);
write_data('0'+WARNING%10);
write_com(0x80+0x40+7);//位置
FENG=1;
write_eeprom(); //保存数据
}
}
void time1_int(void) interrupt 1 //定时器工作函数
{
uchar count; //定义计时变量
TL0=0xb0;
TH0=0x3c; //重新赋初值50ms
count++; //变量加一次就是50ms
if(count==10) //加到10次就是500ms
{
if(flag==0) //flag=0时,也就是不开启报警
{
LED_G=0; //绿灯点亮
LED_R=1; //红灯熄灭
FENG=1; //关闭蜂鸣器
}
if(flag==1) //flag为1时,也就是打开报警
{
LED_G=1; //绿灯熄灭
LED_R=0; //红灯点亮
FENG=0; //打开蜂鸣器
}
}
if(count==20) //计数20次,就是1s
{ //在1s时,红绿灯都是熄灭状态,蜂鸣器也是关闭状态,装可以达到闪烁的目的
count=0; //变量清零
if(flag==0) //不是报警状态时
{
LED_G=1;
LED_R=1;
FENG=1;
}
if(flag==1) //报警状态时
{
LED_G=1;
LED_R=1;
FENG=1;
}
}
}
原理图
设计报告
器件清单:
【腾讯文档】C0031 网盘链接
https://docs.qq.com/doc/DS2dTRkFiSHF1b2tF