综述
对于酒后驾车行为的监督在人民的人身和财产安全中起着重要的作用。随着社会的发展,气体传感器逐渐向着低功耗、多功能、集成化方向的发展,以便于更准确更方便的检测出酒精浓度,更大程度上防范事故发生,因此,便携式酒精浓度检测仪具有十分广阔的现实市场和潜在的市场要求。
目前国际公认的酒后驾车的限定有两种,一种是酒后驾车,一种是酒醉驾车。根据我国2003年的修订规定,当驾驶者每毫升血液中酒精含量大于或等于0.2mg时,就会被认定为酒后驾车;大于或等于0.8mg时,则会被认定为醉酒驾车。当驾驶者血液中酒精含量达到80mg/100ml时,发生交通事故的几率是血液中不含酒精时的2.5倍;达到100mg/100mg时,发生交通事故的几率是血液中不含酒精时的4.7倍。即使在少量饮酒的状态下,交通事故的危险也可达到未饮酒状态的2倍左右。
本文设计的基于单片机的便携式酒精浓度检测仪以单片机和酒精传感器为核心,具有LCD实时显示浓度值的功能,不同颜色LED彩灯显示酒精浓度的不同范围,从而判断司机是否处于酒驾状态,如若酒驾则判断是酒后驾驶还是醉酒驾驶,一旦超过一定阈值即蜂鸣器报警同时报警灯亮。而且还可以通过按键进行待机与检测功能随时切换,在待机时进行简易计时,超过十分钟则自动进入休眠状态,可用硬件复位来唤醒单片机。本设计采用C语言来实现其软件功能。该仪器硬件电路设计简单、软件功能完善、灵敏度高、工作性能好,并且具有尺寸小、方便携带的优点。
1
邱微:基于单片机的便携式酒精浓度检测仪
1方案论证
1.1方案设计与分析
本文设计的便携式酒精浓度测试仪具有以下特点:
(1)数据采集系统以AT89S52单片机为控制核心,外围电路带有LCD显示以及键盘电路,无需其他计算机,用户就可以与其进行交互工作,完成数据的采集、存储、计算、分析,显示,休眠等功能。其中显示功能如下:
A.酒精含量<20mg/100ml时,安全灯(绿色LED灯)亮;
B.20mg/ml≤酒精含量≤80mg/ml时,警告灯(黄色LED灯)闪烁; C.80mg/ml≤酒精含量时,危险灯(红色LED灯)闪烁,蜂鸣器报警; 本仪器酒精含量测试范围:0-190mg/100ml,要求其测量精度优于0.5%。 (2)系统具有低功耗、方便携带、高性价比,低成本等特点。
(3)从便携式的角度设计,系统成功使用了大屏幕LCD显示器以及小键盘。由单片机系统控制键盘和LCD 显示来实现人机交互操作,界面友好。
(4)软件系统采用C语言编写,既兼顾实时性处理的要求又能很方便地进行数据处理。
1.2设计总体框图
MQ3传感器MCU控制中心(AT89S52)LCD显示模块报警与待机指示灯电路放大电路按键A/D转换模块 图1-1总体设计框图
2
辽宁工程技术大学智能仪器课程设计
本设计采用的是AT89S52单片机,传感器则选用MQ—3酒精浓度传感器。系统将由MQ-3酒精浓度传感器输出的微弱电流经具有放大滤波等功能的调理电路后,输入以模数转换芯片ADC0804为核心的转换电路转换为八位数字信号,再由单片机进行处理,最终送入LCD液晶显示屏显示实时检测的酒精浓度以及实现超值报警功能,通过判断酒精浓度范围,实现酒后驾驶和醉酒驾驶的判断。系统上电后自动进入待机状态,在工作时可以随时通过按键控制进入待机状态,待机状态中系统不进行酒精浓度采集、显示和报警,而是给传感器预热并显示十分钟以内的简易计时,让使用者大致掌握预热时间。待机状态中也可随时通过按键进入工作状态。
2信号采集与放大的硬件设计
2.1 酒精浓度传感器的选择
气体传感器是气体检测系统的核心,通常安装在探测头内。探测头通过气体传感器对气体样品进行调理,通常包括滤除杂质和干扰气体、干燥或制冷处理、样品抽吸,甚至对样品进行化学处理,以便化学传感器进行更快速地测量【1】。
在选择传感器的时候,一定要考虑到稳定性、灵敏度、选择性和抗腐蚀性,MQ3 酒精传感器具有很高的灵敏度、良好的选择性、长期的使用寿命和可靠的稳定性,所以本系统选择MQ3 型酒精传感器。
2.2采集信号与放大电路图
MQ-3 气体传感器有6 个针状管脚,其中4 个用于信号取出,2 个用于提供加热电流. LM393是由两个独立的、高精度电压比较器组成的集成电路,失调电压低,最低为2.0 mV,专为获得宽电压范围、单电源供电而设计,也可以用双电源供电,电源电流低. 即使采用单电源供电,比较器的共模输入电压范围也接近低电平。 LM393 被设计成能直接连接TTL 和CMOS,当用双电源供电时,它能兼容MOS逻辑电路,这是低功耗LM393相较于标准比较器的独特优势【2】。
3
邱微:基于单片机的便携式酒精浓度检测仪
图2-1 MQ-3酒精浓度传感器采集信号与放大电路图
MQ-3酒精浓度传感器探头感知到酒精气体,MQ3开始起作用,输出的微弱电流送入由LM393运算放大器和电阻电容构成的调理电路,使信号放大并滤去杂波,经放大滤波后有OUT输出。模拟信号输出端口能输出0到+VCC(+5v) 的模拟信号,当检测的酒精浓度越大时输出电压越高。此端口接入ADC0804的6号引脚,实现AD转换【3】。
3 AD转换硬件设计
3.1 AD转换器的选择及介绍
A/D转换其的主要技术指标包括分辨率(位数)、量化误差、转换精度和转换时间【4】。 根据本文设计的技术参数要求:测量精度优于0.5%。 从精度方面考虑方案如下:
方案一:用8位的A/D转换器,其测量精度为0.39% 方案二:用12位的A/D转换器,其测量精度为0.02% 从测量精度的方面考虑都符合要求。 从A/D转换器的分类方面考虑方案如下:
1、逐次比较式A/D转换器:转换时间一般在μs级,转换精度一般在0.1%上下,适用于一般场合。
2、积分式A/D转换器:其核心部件是积分器,因此转换时间一般在ms级或更长,但抗干扰性能强,转换精度可达0.01%或更高。适于数字电压表类仪器采用。
3、并行比较式又称闪烁式:采用并行比较,其转换时间可达ns级,但抗干扰性能较
4
辽宁工程技术大学智能仪器课程设计
差,由于工艺限制,其分辨率一般不高于8位。可用于数字示波器等要求转换速度较快的仪器中。
4、改进型是在上述某种形式A/D转换器的基础上,为满足某项高性能指标而改进或复合而成的。例如余数比较式即是在逐次比较式的基础上加以改进,使其在保持原有较高转换速率的前提下精度可达0.01%以上。
基于以上比较,综合性价比,选择8为主次逼近式A/D转换器:ADC0809和ADC0804。 ADC0809的功能是将输入模拟量转换为与其成正比例的数字量,它具有8路模拟输入端口,地址线可决定对哪一路模拟输入做AD转换.
ADC0804的功能与ADC0809基本相同,不同点在于它有一路输入。对于本设计的要求是有一路的输入信号,所以从性价比的方面考虑选择ADC0804更优。
3.2 本设计中ADC0804外围硬件连接
图3-1 ADC0804外围电路连接
5
邱微:基于单片机的便携式酒精浓度检测仪
3.3本设计中AD转换软件实现
3.3.1 ADC程序流程图
开始初始化判断ADC是否转换完毕YN读出数据计算
图3-2 ADC程序流程图
单片机对ADC进行初始化,使其能进入正常工作状态,通过判断ADC转换判断标志EOC,看其是否转换完毕,如果没有,则继续判断,如若完成则将ADC转换的数据由单片机读取并计算,然后进入下一环节。
3.3.2 ADC转换原则及程序
转换原则:ACD0804有八位数据输出口,即转换精度为256,它将最高值分为255份,当得到一个转换数据时,用最大值除以255,再乘以该数据值便是最终转换值。
AD转换子函数分析: void ad() { wr=0;
//将WR拉低,让芯片开始读6、7号引脚电压值
delay(1); //延时约一毫秒,让芯片忙完
wr=1; //将WR拉高,上升沿到来时,AD转换开始 delay(5); //软件延时约五毫秒,等待AD转换完成 P3=0xff; //将P3口全部拉高,等待测试数据 delay(1); //延时一会,避免紊乱 rd=0; //将RD拉低,芯片送出数据 delay(1); //延时约一毫秒,让P3口
6
辽宁工程技术大学智能仪器课程设计
temp=P3; //将数据存入temp
rd=1; //将RD拉高 }
4单片机最小系统模块设计
CPU最小系统是单片机运行工作起来所必需的最基本电路组成。它包括电源电路、时钟电路、复位电路。最小硬件电路组成见图4-1。
图4-1 最小系统电路图
4.1 AT89S52简介
本设计以AT89S52单片机为控制核心。单片机也就是MCU,即微控制单元。AT89S52 是低功耗、高性能、采用CMOS工艺的8位单片机,其片内具有8KB 的可在线编程的Flash 存储器,该单片机采用了ATMEL 公司的高密度、非易失性存储器技术,与工业标准型80C51 单片机的指令系统和引脚完全兼容,它能以3V的超低电压工作,晶振时钟最高可达24MHz。通用的8位CPU与在线可编程Flash 集成在一块芯片上,从而使AT89S52 功能更加完善,应用更加灵活;具有较高的性能价格比,使其在嵌入式控制系统中有着广泛的应用前景【5】。
4.2 复位电路设计
图4-2 复位电路电路图
单片机复位的两种基本形式:上电复位和RST按键复位。
7
邱微:基于单片机的便携式酒精浓度检测仪
本设计采用RST按键复位。在复位电路的设计中,要选择合适的元器件参数,电阻的阻值不宜过大或者过小,过大使得RST不可能获得高电平,过小也不能起到限流作用。另外电容容值也应该合适,要保证放电时,RST引脚上的高电平也能保持两个机器周期以上的高电平。
4.3 晶振电路设计
图4-3 晶振电路电路图
本系统中为了尽量降低功耗的原则,采用了内部时钟方式。晶振全称为晶体振荡器(英文Crystal Oscillators),其作用在于产生原始的时钟频率。内部时钟方式的电路实现方法是在XTAL1和XTAL2引脚外接石英晶体,与单片机片内震荡电路形成震荡回路,图中电容C3和C4的容值为22pF,它们的作用是加快起振和稳定频率。
5显示模块软硬件设计
5.1 LCD1602简介
LCD1602每行可以输出16个字符,可以显示两行,故称1602,它不带中文字库,故只能显示数字、字母和普通字符。1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线。在本设计中不检测液晶的忙与闲,用前面对待ADC0804的方法,用软件延时来等待液晶的忙操作时间。
液晶显示输出D0到D7口接P0.0到 P0.7,单独使用一个口,另外还要接上10K上拉电阻来提高P0口带负载能力。
当处于读状态时,RS处于低脉冲,R/W为高脉冲,E为高脉冲,D0~D7=状态字 当处于读数据时,RS为高脉冲,R/W为高脉冲,E为高脉冲,D0~D7=数据。 当处于写指令时,RS为低脉冲,R/W为低脉冲,D0~D7=指令码,E=高脉冲。 当处于写数据时,RS为高脉冲,R/W为低脉冲,E为高脉冲,D0~D7=数据。
5.2本设计中LCD1602的硬件连接
8
辽宁工程技术大学智能仪器课程设计
图5-1 LCD1602硬件连接图
5.3液晶写命令子函数和写数据子函数程序分析
在初始化函数void init(){…}中,已将R/W拉低(对应lcden=0;语句),即只对液晶进行写操作,不读液晶状态。
之前有位定义sbit lcdrs=P2^5; sbit lcdrw=P2^6; sbit lcden=P2^7; 写命令函数各语句分析: void write_com(uchar com)
{ lcdrs=0; //将RS拉低,对指令操作, 上电时是默认高电平 P0=com; //对P0赋值,该值是对应命令码 ,com为形参 delay(5); //延时约五毫秒
lcden=1; //E拉高,让液晶读P0口,写入对应命令码
delay(5); //延时约五毫秒,让液晶忙完再对其操作,防止数据丢失 lcden=0; //将E拉低 } 写数据函数各语句分析: void write_com(uchar da)
{ lcdrs=1; //将RS拉低高(读写数据),说明对数据操作 P0=da; //对P0赋值,该值是要写入的数据 ,da为形参 delay(5); //延时约五毫秒
lcden=1; //E拉高,让液晶读P0口,写入数据
delay(5); //延时约五毫秒,让液晶忙完再对其操作,防止数据丢失
9
邱微:基于单片机的便携式酒精浓度检测仪
lcden=0; //将E拉低 }
值得注意的是,在写数据的操作中,写入的都是字符ASCII码,例如想写1,让液晶在某处显1,可写write_data(’1’);或者write_data(0x30+1)。
5.4 本设计中用的液晶指令介绍
一些指令码的介绍:
0x38:液晶初始化指令,让液晶按每行显示16个字符,显示两行,并且每个字符显示处的点阵为5X7;
0x0C:不显示光标,光标不闪烁;
0x06:在写入一个数据后地址自动加一,显示不移动;
1即0x01:清屏指令,即将液晶内部存储数据清楚,地址指针指向零; 0x80+……:设置写入数据的地址,所加的就是对应地址。
5.5字符串显示和数据实时更新的实现
1)写字符串子程序: void write_str(uchar *p) {while(*p)
write_data(*p++);}
这里灵巧的应用了数组指针,比传统的for嵌套循环写入方便很多。用while(*p)……自动检测是否写完,当写完后指针变为零,跳出循环。如想写入\"AC value:\只需先定义数组uchar code str[]=\"AC value:\";,再写语句write_str(str);写完后指针变为零,自动结束。
2)数据实时更新的实现方法,检测时不断调用显示子函数,display(); 显示函数如下: void display() {
uint value; //定义局部变量value uchar a,b,c; //定义局部变量a、b、c
value=3.92*temp; //获得value值,它是以ppm为单位 a=value/100; //a为value的百位
10
辽宁工程技术大学智能仪器课程设计
}
b=value%100/10; //b为value的十位 c=value%10; //c为value的个位
write_com(0x80+0x40+4); //将数据写在第二行,第五个字符处 write_data(0x30+a); //在第二行,第五个字符处写入value百位 write_com(0x80+0x40+5); //将数据写在第二行,第六个字符处 write_data(0x30+b); //在第二行,第六个字符处写入value十位 write_com(0x80+0x40+6); //将数据写在第二行,第七个字符处 write_data(0x30+c); //在第二行,第七个字符处写入value个位
在循环语句中不断调用AD转换程序, ad();,又不断调用显示函数,数据就能实时检测更新。
在待机时,循环程序中不断执行语句:
write_com(0x80+6); //将数据写在第一行,第七个字符处 write_data(table[a]); //在第一行,第七个字符处写入时钟的分钟
write_com(0x80+7); //将数据写在第一行,第八个字符处
由于是在不断循环调用,即不断数据刷新,而a、b、c、d的改变是通过定时器零实现的。
write_data(table[b]); //在第一行,第八个字符处写入闪烁的冒号 write_com(0x80+8); //将数据写在第一行,第九个字符处
write_data(table[c]); //在第一行,第九个字符处写入时钟的秒钟十位 write_com(0x80+9); //将数据写在第一行,第十个字符处
write_data(table[d]); //在第一行,第十个字符处写入时钟的秒钟个位
11
邱微:基于单片机的便携式酒精浓度检测仪
6其它外围设备软硬件设计
6.1 报警电路软硬设计
6.1.1 硬件部分设计
图6-1 报警电路
将蜂鸣器的正端接电源正,负端接P1.0。低电平有效,蜂鸣器响起。
Da,Db,Dc为检测报警指示灯。Da为浓度不超限的指示灯,Db与Dc分别为酒后驾驶指示灯和醉酒驾驶指示灯,低电平有效。
当酒精含量<20mg/100ml时,安全灯(绿色LED灯)亮;
当20mg/ml≤酒精含量≤80mg/ml时,警告灯(黄色LED灯)闪烁; 当80mg/ml≤酒精含量时,危险灯(红色LED灯)闪烁,蜂鸣器报警。
6.1.2 软件部分设计
位定义语句:
sbit beep=P1^0; //定义蜂鸣器 sbit da=P1^2; sbit db=P1^3;
sbit dc=P1^4; //定义报警灯 用程序让蜂鸣器响:
beep=0; //低电平输出时,蜂鸣器打开 用程序让蜂鸣器关闭:
beep=1; //高电平输出时,蜂鸣器关闭 用程序将Da,Db,Dc点亮: Da =0; Db =0;
12
辽宁工程技术大学智能仪器课程设计
Dc =0; //低电平输出时,Da,Db,Dc点亮 用程序将Da,Db,Dc熄灭: Da =1; Db =1;
Dc =1; //高电平输出时,Da,Db,Dc熄灭
6.2待机指示灯软硬件设计
6.2.1 硬件部分设计
图6-2 待机指示灯电路
发光二极管D1为待机指示灯,它的正端接电源正,负端与470K电阻相连再接上P1.1。低电平有效,D1点亮,开始待机。电阻起到限流电阻的作用。
6.2.2 软件部分设计
位定义语句:
sbit d1=P1^1; //待机指示灯 用程序将D1点亮:
D1=0; //低电平输出时,D1点亮 用程序将D1熄灭:
D1=1; //高电平输出时,D1熄灭
6.3 按键软硬件设计
6.3.1 硬件部分设计
图6-3 按键电路
S2和S3分别和单片机的P2.1和P2.0,再与GND相接。S2为待机控制按键。S3为检测控制按键。R18和R19与VCC相连再并接在开关前,是为了在松手时,使I/O获得稳定的高电平。
13
邱微:基于单片机的便携式酒精浓度检测仪
6.3.2 软件部分设计
位定义语句:
sbit k1=P2^0; //S3位定义 sbit k2=P2^1; //S2位定义 S2按键检测:
if(k1==0) //检测按键是否按下 { }
S3按键检测:
if(k2==0) //检测按键是否按下 { }
delay(5); //消抖
if(k2==0) //再检测按键是否按下
flag=1; //写入要进行的操作,这里是将标志数flag置一 while(!k2); //松手检测 delay(5); //消抖
if(k1==0) //再检测按键是否按下
flag=0; //写入要进行的操作,这里是将标志数flag置零 while(!k1); //松手检测
6.4 电源电路
图6-4 电源电路
如上图为本设计的电源电路。接入220V交流电后从变压器输出12V交变电压,再经过桥式整流电路整流,输出直流电。稳压芯片7805使电压稳定在5V, C5和C6为电解电
14
辽宁工程技术大学智能仪器课程设计
容起到滤除杂波的作用
【6】
。S4为紧锁开关,电源总开关。D4与R17串联,跨接在VCC与
GND之间,作为电源指示灯。
6.5 休眠(空闲)状态的设定
当单片机进入掉电模式时,外部晶振停振、CPU、定时器、串行口全部停止工作,只有外部中断继续工作。使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。
本文中则采用硬件复位唤醒单片机。
让单片机进入休眠(空闲)模式的目的是为了降低系统的功耗,例如在正常使用万用表时表内部的单片机处于正常工作模式,当不用时,又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,它便会自动将液晶显示关闭,以降低系统功耗,通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA~7mA,进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。所以采用休眠对于低功耗是非常重要的。
15
邱微:基于单片机的便携式酒精浓度检测仪
7 软件设计
7.1主程序流程图
开始系统初始化AD采样Y浓度小于20NY浓度大于80N红灯亮黄灯亮绿灯亮蜂鸣报警 数码管显示浓度结束图7-1主程序流程图
7.2检测与待机功能切换设计及程序流程图
为了能让主函数分清是执行执行待机程序还是检测程序报警程序,引进标志数flag。当flag为1时执行待机程序;当flag为0时执行检测报警程序. 在初始化函数中先将flag置1,上电后则进入待机状态。按下k1后使flag置0,执行检测报警程序。按键k2后使flag置1,又执行待机程序,k1、k2均为开关【7】。
下图为系统执行检测功能和待机功能的选择流程图:
16
辽宁工程技术大学智能仪器课程设计
开始检测按键k1与k2是否按下k1与k2未按下(标志 数flag为初始值1)k2按下(标志 数flag为初始值1)k1按下(标志 数flag为初始值0)执行待机程序,液晶显示简易计时,不检测和不显示酒精浓度
图7-2待机与检测程序流程图
执行酒精浓度的实时检测,显示和报警
7.3定时器与定时器中断
本设计在待机时,执行一个简易的十分钟以内的计时程序。这时用定时器零产生中断,让其计时。定时器是独立与cpu的单独部件,与软件延时比起来,它不占用程序时间,定时很精确。当时间到一定时,它就产生定时中断,让主程序让执行定时器中断函数。
设置TMOD=0x01;使定时器零工作在方式一,工作方式一是十六位不能自动重装初值的方式,所以在进入定时器中断函数后要重新装初值【8】。
17
邱微:基于单片机的便携式酒精浓度检测仪
心得与体会
本文给出了基于单片机的便携式酒精浓度检测仪的设计方法,设计过程包括了硬件电路设计和软件程序的编写两部分。硬件电路部分结构简单、使用方便、灵活性强,适合大众化使用。软件部分采用模块化设计思想,各个子程序的功能相对独立,便于调试和修改。
本论文设计的便携式酒精浓度检测仪可应用在实际生活中,用于警方可以监督驾驶员的醉酒行为,亦可以用在特定场合,例如酒精生产工厂等,进行酒精浓度的检测,防止恶性爆炸事件的发生,减少大型事故的发生,避免人员伤亡,从而保证了人民的生命和财产安全,对人们的生活非常重要,所以此便携式酒精浓度检测仪具有实际意义,可广泛应用在居民生产生活中。
本设计编程采用c语言,本人非常认真地且独立地完成了本课程设计的全部工作,有电路图的设计,原理图的绘制,程序的编写与调试、论文的撰写。在设计中查过许多资料,请教过老师和同学同时在设计过程中也学到了许多在书本上学不到的东西的知识,通过此次课程设计很好的锻炼了自己的学习能力。
18
辽宁工程技术大学智能仪器课程设计
致谢
本次课程设计设计是在指导老师李雅梅老师的悉心指导下,还有许多同学的帮助下完成的。在设计的过程中李老师严谨的治学态度,优秀的学术底蕴,孜孜不悔的教学精神,平易近人的人格魅力,对我影响很大,在她的细心指导下我顺利的完成了本次的课程设计。
此外,我周围的同学也在我为一些问题困惑时,给予了我很大的帮助,教会了我许多知识,例如绘图软件的应用等等。
在此向我向李老师表示深深地感谢!也对所有帮助过我课程设计的人在此一并表示感谢!
19
邱微:基于单片机的便携式酒精浓度检测仪
参考文献
[1] 岳睿.警用呼气式酒精传感器的研究进展[J].化学传感器,2006,26(3):6-11. [2] 祝诗平.传感器与检测技术[M].北京:北京大学出版社,2006.
[3] 袁剑蓉,金建祥,张渝晖. 一种高精度、低成本、多量程的A/D转换技术[J].自动化仪表, 2006,8(08):22-25.
[4] 李建忠.单片机原理及应用[M].西安电子科技大学出版社,2008.
[5] 王幸之.AT89系列单片机原理与接口技术[M].北京:北京航空航天大学出版社,2004. [6] 李振梅.模拟电子技术基础[M].北京:高等教育出版社,2010. [7] 邱力.C语言程序设计[M].北京:清华大学出版社,2004.
[8] 郭天祥.新概念51单片机C语言教程[M].北京:电子工业出版社,2009.
20
辽宁工程技术大学智能仪器课程设计
附录一 硬件设计原理图
21
邱微:基于单片机的便携式酒精浓度检测仪
附录二 程序
/***********定义包含reg52头文件***************/ #include /******************************************/ /*******************宏定义***********************/ #define uint unsigned int #define uchar unsigned char /******************************************/ /********************位定义**********************/ sbit beep=P1^0; sbit d1=P1^1; sbit da=P1^2; sbit db=P1^3; sbit dc=P1^4; sbit k1=P2^0; sbit k2=P2^1; sbit lcdrs=P2^5; sbit lcdrw=P2^6; sbit lcden=P2^7; sbit cs=P1^5; sbit rd=P1^6; sbit wr=P1^7; /******************************************/ /*******************定义字符数组***********************/ uchar code str[]=\"AC value:\"; uchar code str0[]=\"ppm\"; uchar code table[]=\"0123456789: \"; /******************************************/ /*********************定义无符号字符型全局变量*********************/ uchar flag,temp,a,b,c,d,tt; /******************************************/ /******************子函数声明************************/ void init(); //初始化函数 void delay(uint); //有无符号整型形参的延时函数 void write_str(uchar *); //向液晶写入字符串的函数 void write_com(uchar); //液晶写命令函数 void write_data(uchar); //液晶写数据函数 void ad(); //AD转换函数 void display(); //酒精浓度显示函数 /******************************************/ /*********************主函数部分*********************/ void main() { 22 辽宁工程技术大学智能仪器课程设计 init(); //调用初始化函数 while(1) { if(k1==0) //检测按键是否按下 { delay(5); //消抖,将程序的执行暂停五毫秒 if(k1==0) //再检测按键是否按下 flag=0; //写入要进行的操作,这里是将标志数flag置零 while(!k1); //松手检测如果k1取反 } if(k2==0) //按键检测 { delay(5); //消抖,将程序的执行暂停五毫秒 if(k2==0) //再检测按键是否按下 flag=1; //写入要进行的操作,这里是将标志数flag置一 while(!k2); //松手检测 } while(flag==0) //执行检测报警程序 { TR0=0; //采用定时器零产生中断 d1=1; //发光二极管1为高电平,待机指示灯为关状态 write_com(1); //清屏操作 write_com(0x80); //液晶初始化指令,让液晶按每行显示16个字符,显示两行 write_str(str); write_com(0x80+0x40+9); write_str(str0); while(flag==0) { ad(); display(); if(temp>=20) { if(20<=temp<=80) //为酒后驾驶 { beep=0; db=0; } if(temp>=80) //为醉酒驾驶 { beep=0; dc=0; //红灯亮起 } 23 邱微:基于单片机的便携式酒精浓度检测仪 } else { beep=1; //未饮酒区 da=0; //绿灯亮起 } if(k1==0) //按键检测 { delay(5); if(k1==0) flag=0; while(!k1); } if(k2==0) //按键检测 { delay(5); if(k2==0) flag=1; while(!k2); } } } while(flag==1) //执行待机程序 { beep=1; da=1; db=1; dc=1; //检测指示灯为关状态 tt=0; a=0; b=10; c=0; d=0; write_com(1); d1=0;//待机指示灯为开状态 TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; while(flag==1) { write_com(0x80+6); //将数据写在第一行,第七个字符处 write_data(table[a]);//在第一行,第七个字符处写入时钟的分钟 write_com(0x80+7); //将数据写在第一行,第八个字符处 write_data(table[b]);//在第一行,第八个字符处写入闪烁的冒号 24 辽宁工程技术大学智能仪器课程设计 } /******************************************/ /********************初始化子函数**********************/ void init() { lcdrw=0; lcden=0; write_com(0x38);//液晶初始化指令,让液晶按每行显示16个字符,显示两行,并且每个字符显示处的点阵为5X7; write_com(0x0c); //不显示光标,光标不闪烁; write_com(0x06); //在写入一个数据后地址自动加一,显示不移动 cs=0; flag=1; b=10; TMOD=0x01; //定时器零工作方式为方式一 EA=1; ET0=1; } /******************************************/ /********************延时子函数**********************/ void delay(uint z) { uint x,y; write_com(0x80+8); //将数据写在第一行,第九个字符处 write_data(table[c]);//在第一行,第九个字符处写入时钟的秒钟十位 write_com(0x80+9); //将数据写在第一行,第十个字符处 write_data(table[d]); //在第一行,第十个字符处写入时钟的秒钟个位 if(k1==0) //按键检测 { delay(5); if(k1==0) flag=0; while(!k1); } if(k2==0) //按键检测 {delay(5); if(k2==0) flag=1; while(!k2); } } } } 25 邱微:基于单片机的便携式酒精浓度检测仪 for(x=110;x>0;x--) for(y=z;y>0;y--); } void write_str(uchar *p) // 写字符串子程序 { while(*p) write_data(*p++); //用while(*p)……自动检测是否写完,当写完后指针变为零,跳出循环 } /******************************************/ /******************液晶写命令子函数************************/ void write_com(uchar com) { lcdrs=0; //将RS拉低,说明对指令操作, 上电时是默认高电平 P0=com; //对P0赋值,该值是对应命令码 ,com为形参 delay(5); //延时约五毫秒 lcden=1; //E拉高,让液晶读P0口,写入对应命令码 delay(5); //延时约五毫秒,让液晶忙完再对其操作,防止数据丢失 lcden=0; //将E拉低 } /******************************************/ /*******************液晶写数据子函数***********************/ void write_data(uchar da) { lcdrs=1; //将RS拉低高,说明对数据操作 P0=da; //对P0赋值,该值是要写入的数据 ,da为形参 delay(5); //延时约五毫秒 lcden=1; //E拉高,让液晶读P0口,写入数据 delay(5); //延时约五毫秒,让液晶忙完再对其操作,防止数据丢失 lcden=0; //将E拉低 } /******************************************/ /**********************AD转换子函数********************/ void ad() { wr=0; //将WR拉低,让芯片开始读6、7号引脚电压值 delay(1); //延时约一毫秒,让芯片忙完 wr=1; //将WR拉高,上升沿到来时,AD转换开始 delay(5); //软件延时约五毫秒,等待AD转换完成 P3=0xff; //将P3口全部拉高,等待测试数据 delay(1); //延时一会,避免紊乱 rd=0; //将RD拉低,芯片送出数据 delay(1); //延时约一毫秒,让P3口 26 辽宁工程技术大学智能仪器课程设计 temp=P3; //将数据存入temp rd=1; //将RD拉高 } /******************************************/ /********************酒精浓度显示子函数**********************/ void display() { uint value; uchar a,b,c; value=3.92*temp; a=value/100; b=value%100/10; c=value%10; write_com(0x80+0x40+4); write_data(0x30+a); write_com(0x80+0x40+5); write_data(0x30+b); write_com(0x80+0x40+6); write_data(0x30+c); } /******************************************/ /*****************定时器程序*************************/ void timer0()interrupt 1 { TMOD=0X01; //定时器工作方式设置为定时器0,方式1 TH0=(65536-50000)/256; //计数寄存器高8位 TL0=(65536-50000)%256; //计数寄存器低8位 TR0=1; //开启定时器0运行 ET0=1; //开定时器0中断 tt++; if(tt==20) { tt=0; if(b==10) b=11; else b=10; d++; if(d==10) { d=0; c++; if(c==6) { c=0; 27 邱微:基于单片机的便携式酒精浓度检测仪 a++; if(a==10) //掉电和空闲模式的进入 { ET0=0; //关定时器 PCON=0X02; //PD=1,进入掉电模式//或 PCON=0X01;//IDL=1,进入空闲模式 } } } } } /*****************休眠唤醒程序*************************/ void huan_xing() interrupt 2 //采用硬件复位唤醒单片机,按键K1 { PCON=0;//清除之前的掉电(空闲)模式 ET0=1; //开定时器0 } 28 因篇幅问题不能全部显示,请点此查看更多更全内容