鉴于人们对于醉酒驾驶的逐渐重视,酒精测试课题便引起了广泛的关注。酒后驾车引起的交通事故是由于司机的过量饮酒造成人体内酒精浓度过高,麻痹神经,造成大脑反应迟缓,肢体不受控制等症状。为本课题研究的是一种以气敏传感器和单片机为主,监测空气酒精浓度,并具有LCD显示功能的空气酒精浓度监测仪。此需要设计一智能仪器能够监测驾驶员体内酒精含量。本课题研究的是一种以气敏传感器和单片机为主,监测空气酒精浓度,并具有声报警功能及LCD显示功能的空气酒精浓度监测仪。其可监测出空气环境中和呼气中酒精浓度值,并根据不同的环境设定不同的阀值,对超过的阀值进行声报警,并显示阀值.来提示危害。从而达到以下目的:
(1)有利于社会公共交通安全;
(2)提高人们法律意识
(3)使之便捷、安全、准确、高效,便于提高家庭酒精测试的普及化。本作品是基于单片机控制ADC0809对TGS822酒精浓度取样来反映人体血液酒精浓度;
以及对DS18B20获取温度关键词:ADC0809;TGS822;DS18B20;单片机
设计思路:
//程序头函数
#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;
}
}
}
实物详细咨询 wx:2313901444
2313901444