电工优优今天要和大家分享的单片机相关信息,接下来我将从基于51单片机的酒精检测仪设计这个方面来介绍。
引言
随着我国经济的蓬勃发展,国民生产总值的不断提高,人均可支配财产也大大增加,汽车拥有量持续增加,与此同时,每年死于交通事故的人数也在持续增加,道路交通安全形势变得十分严峻,多部门都对此高度重视。
在全球范围内,人均酒精消费量从1990年的5.9L增加到2017年的6.5L,未来还将持续增加。而人体血液中积累一定程度的酒精,但未及时分解排出体外时,便会影响大脑和中枢神经,致使神经麻痹,大脑反应滞后,身体不受控制等症状,在处理紧急情况时的反应速度和控制能力会有些许下降,严重者丧失行动能力。而我国的酒文化历史悠久,源远流长,在世界上也是独领风骚,在接待贵宾,亲朋好友相聚,酒水必不可少,随之也带来了一系列社会问题,例如酒后打架、醉酒驾驶引发交通事故等,酒后驾驶甚至被列为车祸致死的主要原因之一,一旦发生,将是一个甚至多个家庭的不幸,为了降低发生此类事情的概率,使更多人的生命财产安全得到保障,急需一种仪器来判断驾驶员是否醉酒驾驶。
本文提出并设计了一种可以实时检测呼出气体的酒精含量,且超出设定值时会声光报警的测试仪。本文详细介绍了设计所提出的背景和研究意义,对于所用到的各个器件做了对比介绍,以及各个硬件电路模块的工作原理,在软件程序方面,对于各个模块做了详细的流程框图,可以快速看出程序设计思路,最后列举了硬软件在设计调试所出现的一系列问题以及与之对应的解决办法。
1 课题背景意义及研究内容
1.1 课题背景及研究意义
此次毕业设计的课题是《基于单片机的酒精检测仪》,是工程设计类的课题。
现如今,已全面步入信息化时代,电子设备充斥着我们生活的方方面面。带来了巨大的便利,在实际生活中,酒精检测仪也应用于食品加工,酿酒,交通查酒驾等领域,平时见到最多的便是交警查酒驾,而最准确确定人体酒精浓度的方法是抽血化验检测,但是这种办法操作过程过于繁琐,技术难度相对较高。测量呼出的气体来判断气体的酒精浓度相对较为实用,一个人在深呼吸2~4秒后,便会释放出肺部深处的气体,而血液中的酒精浓度与肺部的比值大致为1:2200,通过这种方式便可来推算人的饮酒量。
根据酒精检测仪的原理,可以将其划分为电化学、红外、气体色谱、比色、半导体型等五大类。受价格等因素的影响,半导体和电化学型的应用较广。目前,许多国家都使用呼气酒精检测仪在现场进行检测,来判断驾驶员是否饮酒。其中电化学型的稳定性较好,精确度较高,且抗干扰性强,但是要求结构较为精密,且制造困难,只有个别国家可以生产,相反半导体类型的较为廉价,但性能不如燃料电池性的。
酒精检测仪的现实意义在交通方面主要是可以解决社会上的车祸乱象,可以很大程度的减少车祸的发生,对道路出行多了一份安全保障,挽救了无数个家庭,同时也给国家做了巨大的贡献,树立了国家安全的良好形象,让每一个人都能生活在一个良好的社会环境中,其次在其他如食品加工等领域,可以检测生产产品的质量以及确保生产安全。
1.2 课题研究内容
设计要求:
(1)能对酒精含量进行测量和显示,并显示醉酒阈值;
(2)当酒精浓度大于醉酒阈值时,声光报警;
(3)能够显示年、月、日、星期、时、分、秒。
2 设计方案选择
2.1 系统控制芯片选择
方案一:选择STC89C52单片机作为主控制芯片。该单片机是8位微控制器,有8K的程序存储空间,有256个字节数据存储空间,3个16位定时器/计数器,4个外部中断,全双工串行口,具有高速、低功耗、具有超强抗干扰性的特点,其指令代码完全兼容8051,市场价格较为廉价,且具有灵活的编程方式。
方案二:选择MSP430单片机作为主控制芯片。该单片机的汇编语言使用起来较为灵活,有许多寻址方式,且具有强大的处理能力,电压低,功耗较低,片内集成资源丰富,且加密性强,有强抗干扰能力。但是由于工作电压低,接口电路麻烦,而且I/O口无保护,所以过压电流会击穿。其次不易上手,学习资料较少。
综合以上的描述,鉴于STC89C52较为常用,市场上价格相对较低,设计开发难度较小,查找学习资料便捷,且此单片机已可满足设计要求,因此选择STC89C52作为主控制芯片。
2.2 显示器件的选择
方案一:使用LCD1602液晶显示屏。该显示屏可以直接和STC89C52直接接口,可显示32个字符,因是字符型液晶,所以可以较为便捷地显示字母和数字,且控制简单,市场价格低廉,但是所显示的字体大小不可随意改动,对于曲线和图形等也无法显示。
方案二:使用LCD12864液晶显示屏。该液晶显示屏的各个显示点都与一个二进制数对应,因此可自行设计输出的图形和汉字,分辨率较高,功耗较低,且轻薄,由于显示信息量大,造成电路及程序的设计较为困难。
综合以上方案,本设计主要显示酒精含量、时间和日期,需要显示的内容较少,选用LCD1602为显示屏,已可满足设计要求,且该显示屏价格低廉,在网络上可查找资料较多,方便学习参考,设计难度相对较小。
2.3 A/D转换芯片的选择
方案一:采用ADC0832作为模数转换器件。该芯片是双通道的模数转换芯片,在0~5V的电压下可以正常工作,采用250KHZ的频率,采用双输出方式对数据进行严格的校对,可有效减少芯片的数据错误,并具有较好的稳定性。独立的允许输入模式使得多个设备的安装和控制过程更加方便。
方案二:采用ADC0808作为A/D转换器件。该芯片是ADC0809的简化版,功能大致相同,ADC0808是采样分辨率为8位的、以逐次逼近原理进行模/数转换的器件。
这两种设备的基本性能相似,因为本次设计只需一个通道,所以使用ADC0832芯片已可满足需求,可节省资源,且此芯片兼容性好,较为划算。
2.4 酒精检测传感器的选择
半导体型的酒精传感器MQ-3所处环境中含有酒精蒸气时,当乙醇气体浓度增大时,传感器的导电性能也随之提高,接着将检测到的酒精含量转化为电信号,可以得到关于周围环境中被测气体状态的信息。MQ-3对酒精较为敏感,以及有较强的抗干扰能力,对于油烟水汽有较强的抵抗性,且市场价格较低,适用于多种应用,最终方案选择MQ-3酒精传感器。
2.5 时钟芯片的选择
DS1302时钟芯片可提供时间等信息,在2V~5.5V之间可以正常工作,具备主电源后备电源双电源引脚,1脚为主电源接口,8脚作为后备电源接口,可搭配纽扣电池做后备电源,以极低的消耗可保持时钟运行很长时间,运行时间可达到几个月甚至几年,即使断电后再次上电使用设备也可做到时间同步标准时间。虽然单片机内部也有定时器,但它是对单片机工作节拍的技术的精确度较高,但不适合长时间定时。相比之下,选择DS1302做时钟芯片更能满足课题要求。
2.6 系统整体设计方案
结合上面选择的解决方案,确定了总体系统框图,如图2-1所示。
图2-1 总体系统框图
最终将STC89C52单片机作为系统的主控芯片,人机交互通过独立按键和LCD1602液晶显示屏来实现,并可通过独立按键来设定醉酒阈值,调节时间显示,与标准时间同步。使用MQ-3酒精传感器来得到电信号,经过电路处理成模拟电压后输送给单片机,经ADC0832转换器件转化为数字电压。模拟信号由A/D转换模块输出,用于检测酒精的浓度,从而降低设备的使用。将所获得的数据与预先设置的醉酒阈值进行比较,超过设定值值时,LED亮,同时蜂鸣器发出报警声。整个电路包括:最小MCU,时钟,功能按键,LCD液晶四大部分。该供电模块由一个滤波电容,一个自锁开关,一个LED显示,可5V直流供电,供电给各模块;由LCD1602液晶显示屏和可调电阻器组成液晶显示模块。
3 系统硬件设计
3.1 单片机最小系统
3.1.1单片机STC89C52
STC89C52单片机完全兼容8051,该单片机共有四组I/O口,全部提供给用户(程序长度小于4K)分别是P0、P1、P2、P3。有6个中断源,3个16位的定时/计数器,片内振荡器和时钟电路在5.5V~3.8V之间可正常工作,11.0592MHz和12MHz是常用的时钟工作频率,安全性高,功耗低,运行速度快,性能卓越,且市场价格便宜,在多个领域都有应用。
3.1.2单片机最小系统
单片机最小系统电路如图3-1所示
图3-1 单片机最小系统
该产品采用STC89C52微控制器,以单片机为控制核心,配合晶振、电源、复位电路,具有优异的性能、较低功耗、充分开放的系统资源、灵活的界面,使用者可以通过自己的方式构建电路,实现各种功能。在晶振电路中,通常可以选择1.2-12MHz,甚至24MHz,功率随着频率的增大而增大。此次采用了2个30pF陶瓷电容器,12MHz的晶振。
MCS-52单片机通常采用上电复位和按键复位这两种复位方式[1]。RST的上方为一电容,并接一高电平,下方为一个电阻,并接地。在通电的情况下,电容器的两端就会产生短路,RST管脚就会变成高电平,电源就会对电容充电,RST端的电压就会缓慢地降低,直到达到一定的水平,单片机才能正常工作。
本设计改用了USB接口5V供电,通过一双掷开关来控制电源的关断,可连接充电宝或者手机充电器等,方便携带使用,其电路如图3-2所示。
图3-2 电源接口电路
3.2 MQ-3酒精气体传感器
MQ-3是一种半导体酒精感应器,当被测环境中含有酒精气体时,该传感器的导电性会随着被测环境中的酒精气体的浓度而发生变化,接着通过特定的电路,便可将传感器的电导率转化为一定的气体浓度的信号,MQ-3酒精感应器对酒精的敏感度很高,能够抵抗汽油,烟雾,水蒸气等。传感器在充电时,输出电压会迅速升高,当达到一定的温度后便会缓慢的下降,因此在使用之前,要先对传感器进行预热1-2分钟,这样就可以保证传感器的正常工作。被测环境中的酒精浓度与传感器输出电压有着一定的关系,在无酒精气体的环境中,传感器的输出电压大约为1V,在有酒精气体的环境中,每提高20 PPM (2毫克/100毫升)的酒精浓度,传感器的电压提高0.1V,该模块内部电路图如图3-3所示。
图3-3 MQ-3酒精检测模块内部电路图
3.3 ADC0832电路设计
ADC0832是一款双通道的A/D转换芯片,该芯片的模拟输入电压范围为0-5V,基于有双输出的数据,可以进行数据的校验,从而降低了数据的错误,具有较高的转换速度和较好的稳定性。独立的晶片允许输入,使得多个装置的连接与处理单元的控制更为便利。利用DI的数据输入,可以较为方便地进行信道功能的选取。如果ADC0832不工作,则其CS输入为高电平,此时,可将此芯片关闭,CLK及 DO/DI可供选择。与单片机的接口应为CS、CLK、DO、DI四条数据线路.由于DO和DI在通信过程中不能同时进行,并且与单片机之间的接口也是双向的,所以在电路上,DO和DI并联为一条数据线。图3-4显示了特定的电路。
图3-4 ADC0832电路图
3.4 时钟电路设计
在DS1302时钟电路中,管脚1用作主电源接口,管脚8提供低功率和低功耗的情况下的备用电源接口,当主电源断电时,Vccl可保证其正常工作,保存资料,保持时钟的正常运转,做到时间同步。并外加频率为32.768Hz晶振,提高时钟的稳定性。图3-5为本设计的时钟电路。
图3-5 时钟电路
3.5 报警电路设计
经A/D转换后所得的数字信号若比所设的阈值大,单片机的P2.3口输出低电平,此口与报警电路相连,当其为低电时,三极管导通,蜂鸣器通电,发出蜂鸣声,若为高电平时,三极管无法导通,保持静默。蜂鸣器报警电路如图3-6所示。
图3-6 报警模块电路图
3.6 功能按键模块
在按键上,一般采用独立的按键和矩阵的方式,各有利弊,而单独的按键电路则比较简单,编程也比较方便,一般用于一些简单的硬件电路。矩阵电路恰恰相反,编写程序不易,与独立按键相比更加节省IO口,多用于8个按键以上的硬件电路。本设计只需四个按键,因此该方案采用了独立按键电路,采用了多个单独的按键进行人机对话。通过按键操作,向系统发出操作指令,再与MCU进行串口通讯,显示在液晶显示屏上,按键的一端与单片机的输入/输出端口相连。
这个设计是因为在悬置状态下,单片机的I/O是置1,不按按键的话,I/O就等于悬空,按下按钮后,此端口的电压会降低,单片机可以根据输入/输出接口是否存在低电平来判定是否按下了按钮,当然,该按键使用的是金属开锁,会出现抖动,因此在程序中要加上一个延迟消除。此外,再按下按键时会产生抖动,所以在程序中要加一个延迟消除程序。三个按键的功能分别是:按键2按下后进入设置模式,可以选择需要调节的参数,可连续选择。在设置的模式下,按键2按下后,对应的参数加一,按键3按下后对应参数减一。功能按键电路如图3-7所示。
图3-7 功能按键电路
3.7 LCD1602液晶显示模块
显示LCD1602总共有11个指令,通过MCU将其传输到LCD1602中,可以实现诸如屏幕清屏、切换、显示等功能。LCD1602本身就有一个字库,可以在显示的时候直接调用字库来显示,当然,如果字库里没有的字符也可以按照自己的要求写在CGROM里,比如5*8个字符,但是定制的字符数量是有限制的,所以要按照一定的顺序来设置,最多可以设置8个字符。在LCD的CGROM中写入定制的字符之后,可以任意调用,调用方法与普通的显示字符相同。通过读状态操作、写指令操作、读数据操作可以控制液晶显示器,其中写数据操作有固定的对应引脚电平。电路图如图3-8所示。
4 系统软件设计
4.1 程序语言及软件开发环境
本课题的编写涉及到软体的编程,所以必须选用程式语言和软体的开发环境。在编程语言上,选择了C。C语言是一种面向过程、抽象的通用编程语言。可以说,这是一种具有两种语言特性的语言,同时也是一个优秀的程序设计工具,可以使用模块化的方法编写代码,方便调试,同时,C语言还具有很强的数据处理能力,可根据不同的指针,直接对硬件进行访问,从而实现对存储和硬件的访问。
KeilC51是一个可以兼容51系列单片机和C的软件开发平台,与C语言的编程十分契合,它的集成环境简单、方便,软件调试的功能强大,大大增加了程序的成功概率。而Proteus则是一个EDA的开发工具,可以通过计算机模拟单片机的电路来模拟实际的工作状况。通过对系统的模拟,可以对系统的整体功能进行检验。
4.2 主函数的设计
程序开始运行后,LCD1602液晶显示器和定时器开始初始化,单片机开始读取EEPROM存储的限制数据,接着判断一分钟预热是否完成,保障传感器可以正常工作,预热完成后,程序要检测是否有按键按下,若按下便进行数据处理,并判断显示是否正常,若不正常则跳到显示界面,正常则继续下一步,单片机读取经A/D转换后的数字信号,并发送给液晶显示器,最终显示出酒精浓度。系统框图如图4-1所示。
图4-1 系统程序流程图
4.3 LCD1602显示程序
LCD1602的显示只要严格按照生产厂商的时间顺序进行程序设计即可实现。显示器首先要用指令写出要显示的位置,再按照一定的顺序写下数据。在第一次写时,会自动增加一个地址。参数为x,y,*s,其中的x,y表示在液晶显示屏上的位置坐标,*s是需要显示的字符数组。软件通过所输入的坐标来确定所要显示的地址。具体的流程图如图4-2所示。
4.4 ADC0832转换函数的设计
单片机控制ADC0832采集电压,首先要发送初始化信号,接着选择需要采集的通道,选择完通道后单片机发送下降沿开始读数据,数据是一位位的串行传输并且高位在前,低位在后,直到将八位数据都采集完毕后将采集到的数据返回。具体流程图如图4-3所示。
5 系统调试
5.1 系统软件调试
此次课题是基于单片机的酒精检测仪,设计主要要求是检测酒精浓度,超出阈值便声光报警,随后查找参考文献及学习资料,了解所使用元器件的功能和使用原理,开始设计电路,将设计好的电路在Proteus仿真软件上画好仿真原理图,模拟各个模块的功能,其中使用一个滑动变阻器来模拟酒精传感器的变化。
使用Keil uVision4软件编写程序,主要采用模块化的方式,编写出各个模块的功能子函数,再将写好的子函数调用到主函数中,一步步的完善编程,全部写完后,编译没有报错,然后生成hex文件,打开仿真软件烧录进单片机检查功能是否正确,在仿真时发现液晶显示屏不显示,按下按键也不能显示出文字字母,以为是LCD602液晶显示模块电路画错,在查找资料对比后发现无误,又仔细其检查代码,发现有一两个控制端的定义出错,修改后重新编译生成hex文件,重新下载后测试成功显示,之后又发现星期显示往右偏移导致不完整显示,又仔细查找LCD1602的相关资料,考虑是显示位置语句的参数未设置好,修改后变的正常,要计算好每条信息的位置,利用好显示屏的空间,使得参数可以完整显示。
5.2 硬件制作与调试
原理图的绘制主要使用的软件是AD15,一些器件的封装不在现有的器件封装库中,需查找相关器件的封装资料,画好所需要的全部器件封装后,将事先设计好的电路图绘制出来,画出各个模块后使用网络标号连接,之后导入pcb,发现通过网络标号连接的电路,pcb中并未连接,经检查发现是芯片引脚引出来的线用错,修改后再次导入,开始绘制pcb,布局始终遵循紧凑的原则,线宽尽量不要太细,防止后续腐蚀时出现断路短路,安全距离尽量大一些,焊盘大小在不影响其他引脚的情况下,尽可能的大一点,方便后续钻孔,防止将焊盘打掉造成器件无法焊接,接着将电路图打印在热转印纸上,通过熨斗印在腐蚀板上,接着通过腐蚀剂等进行手工制板,打完孔后使用数字万用表的蜂鸣档测量地线、电源线和信号线是否连通,焊接时先焊小器件,再焊大器件,使成品更加美观。
焊接完成后,对未插芯片的板子进行测试,防止因电压过高而烧坏芯片,并检查是否有缺焊漏焊,接着使用数字万用表的直流电压档测量芯片插座处的电压,发现STC89C52单片机的20引脚和40引脚电压为4.9V,LCD1602液晶显示屏的1脚和16脚电压为4.9V,DS1302时钟芯片的1脚和4脚的电压为4.8V,均在可正常工作电压范围内,可将芯片插上。
接着将单片机和电脑相连,使用STC-ISP烧录软件将程序烧录进单片机芯片中,之后在板子上插上芯片上电后,拨动双掷开关看到电源指示灯亮起,液晶显示器可以正常显示,显示年、月、日、周、时、分、秒,并开始初始化一分钟倒计时,演示图如图5-1所示。
图5-1 上电初始化演示图
但在使用过程中有时显示乱码,考虑到有时使用是没问题的,猜测是工作不稳定,可能是写代码的时序太快,致使LCD工作不稳定,查找资料后在写指令时加一些延时,试了几次后恢复正常,之后也正常使用。调节好时间后拔掉电源,过一段时间后再次连通电源,发现时间仍与实际时间同步,表明时钟芯片使用的后备电源生效。通过按键来调节时间和设置酒精阈值,具体的演示图如图5-2所示。
当检测环境中的酒精含量超过了规定的酒精阈值,则LED灯将点亮,蜂鸣器会持续地发出声音,LCD屏幕将会实时显示被检测的环境中的酒精含量,当检测到的酒精含量超过规定范围时,光亮和声音将会自动关闭,将一瓶酒精凑到MQ-3酒精传感器前,因酒精浓度较高,显示屏所显示数值会迅速升高,拿开酒精后,会慢慢下降直至清零,演示图如图5-3所示。
部分程序展示:
sbit led = P1^7;
sbit buzz = P1^6;
sbit key_set = P1^0;
sbit key_jia = P1^1;
sbit key_jian= P1^2;
/*********************全局变量定义***************************/
#define K_MG_MV 2
#define IN_V 500
long ALValue;
uchar K_ZERO;
uint jiujia_up;
uint set_f;
uchar num;
/********************************************************
函数名称:void display1()
函数作用:显示实际浓度值
参数说明:
********************************************************/
void display1()
{
uchar xq;
xq=GetWeekDay(time[6],time[4],time[3]);
switch(xq)
{
case 1:lcd1602_write_character(11,1,"Mon"); break;
case 2:lcd1602_write_character(10,1,"Tues"); break;
case 3:lcd1602_write_character(9,1,"Wednes"); break;
case 4:lcd1602_write_character(10,1,"Thurs"); break;
case 5:lcd1602_write_character(10,1,"Frid"); break;
case 6:lcd1602_write_character(10,1,"Satur"); break;
case 7:lcd1602_write_character(11,1,"Sun"); break;
default: break;
}