基于单片机的防酒驾控制系统设计

基于单片机的防酒驾控制系统设计

**技术说明:**本文围绕《基于单片机的防酒驾控制系统设计》进行技术和设计过程整理,重点关注需求分析、系统架构、数据建模、功能实现和测试验证等内容。内容用于软件工程和信息系统设计复盘,不涉及商业推广或服务宣传。

第1章 概述1

1.1 研究背景与意义1

1.2 国内外研究现状1

1.3 本文结构安排2

第2章 总体设计方案4

2.1 系统总体设计4

2.2 系统硬件器件选择及介绍4

2.2.1 单片机4
2.2.2 MQ-3酒精传感器5
2.2.3 GSM短信模块6
2.2.4 显示模块6

第3章 硬件设计8

3.1 STM32最小单片机系统电路8

3.1.1 主控单片机介绍8
3.1.2 单片机的复位电路9
3.1.3 单片机的晶振电路9
3.1.4 其他电路9

3.2 酒精传感器模块的电路设计10

3.3 GSM短信提醒电路设计11

3.4 GPS模块电路设计12

3.5 OLED显示电路设计12

3.6 继电器电路设计13

3.7 声光报警电路设计13

第4章 软件设计15

4.1 Keil5软件开发环境15

4.2 主程序设计15

4.3 子程序设计16

4.3.1 酒精浓度采集程序设计16
4.3.2 GSM串口通信程序设计17
4.3.3 GPS程序设计18
4.3.4 OLED屏幕显示模块程序设计18
4.3.5 报警模块程序设计19
4.3.6 按键设置程序设计19

第5章 系统调试21

5.1 系统硬件调试21

5.2 系统软件调试21

5.3 实物测试21

5.3.1 传感器测试22
5.3.2 GSM短信模块测试22
5.3.3 GPS模块测试23
5.3.4 报警电路、继电器测试25

5.4 本章小结26

第6章 总结27

参考文献28

致 谢29

附 录30

附录一:电路原理图30

附录二:PCB设计图31

附录三:实物图31

附录四:元器件清单31

附录五:设计主程序代码32

第1章 概述

1.1 研究背景与意义

随着社会经济水平的提升,汽车已普及至千家万户,截至2024年底,全国机动车保有量已高达4.4亿辆。面对这一庞大的数字,公众关注的焦点不仅限于出行便捷性的提升,更深刻地意识到预防交通事故的紧迫性。从历来的交通事故统计资料中,不难发现,饮酒后进行车辆驾驶,尤其在醉酒状态,是导致交通事故的显著且靠前的原因之一。现今,在《道路交通安全法》的明确规定下,对于驾驶机动车辆时因饮酒后乃至醉酒状态引发重大交通事故,且此行为已触及刑法构成犯罪的个体,将严格依照规定追究其相应的刑事责任。与此同时,为加强道路安全管理,公安机关交通管理部门将吊销其机动车驾驶证,并宣告其终生都不能再次取得机动车驾驶证。驾驶员在饮酒后驾车,由于酒精对大脑的负面影响,导致其无法如常时般做出精准的操作与判断,以这一状态在道路上行驶构成了极其严峻的安全隐患1。这恰恰凸显了检测驾驶员是否酒驾至关重要,因为阻止因酒驾引发交通事故,已经成为了一项刻不容缓的任务。此外,在日常生活中,荔枝、榴莲、葡萄、蛋黄派、提拉米苏、红牛饮料等,甚至是漱口水,都可以造成在酒精测试时,检测到酒精含量超标的情况2,为减少不必要的麻烦和占用公共资源,就可以选择使用防酒驾控制系统。

随着公众对醉酒驾驶危害性的日益重视,酒精检测议题已广泛进入视野。然而,不容忽视的是,仍有一部分群体抱有侥幸心理,无视酒后驾车的严重后果,严重威胁着公共交通安全。同时,误食含酒精食物导致被误判为酒驾的尴尬情况也时有发生,本设计致力于帮助解决这些问题,减少不必要的纠纷和公共资源的浪费。它不仅能够直接提升道路安全、在一定程度上保护公众的安全,还能够支持法律的有效执行,推动了相关技术的进一步发展,并在此过程中增强了社会整体的安全意识与责任感。

1.2 国内外研究现状

为有效减少酒驾事故,提升道路安全水平,国内在酒精检测控制系统的研发领域倾注了大量资源,致力于通过技术创新达成这一目标。当前,我国已在该课题相关领域取得了显著进展,开发出了一系列成熟技术,包括但不限于呼气检测技术、车载酒精自动检测系统及多传感器融合技术,这些技术的应用为防范酒驾提供了强有力的支持。其中呼气式酒精检测仪是国内最常用的酒精检测设备,广泛应用于交通执法领域;车载酒精检测系统具备实时监测功能,能够不间断地检测驾驶员体内的酒精含量,一旦发现驾驶员处于酒驾状态,便会立即触发预设的安全措施;多传感器融合技术将呼气传感器与皮肤传感器等多种传感器采集的数据进行深度整合与综合分析,通过复杂的算法处理,有效排除了单一传感器可能产生的误差与干扰,从而确保了检测结果的准确性与可靠性3

国外在酒精检测控制系统领域的技术相对较为先进。一些国家已经开发出更加智能化、高精度的酒精检测设备和技术。例如,瑞典、美国等国家在呼气检测技术、车载酒精检测系统等方面具有较高的技术水平。尤其是在非接触式检测技术方面,国外一些研究机构和企业正在研发非接触式酒精检测技术,如通过红外线检测驾驶员皮肤表面的酒精含量等,这种技术具有更高的便捷性和隐私保护性。美国政府还在2021年签署的基础设施法案中设定了明确的要求,即汽车制造商必须在2026年之前确保所有新生产的车辆均装配上防醉驾系统,因此可以看出国外酒精检测控制系统的市场应用相对较为广阔,除了交通执法领域外,还可以应用于酒厂、化工企业、食品加工厂等多个领域。

综上所述,国内外对酒精检测控制系统的开发情况呈现出多元化。随着政策法规的持续推动及技术的飞速发展,酒精检测控制系统将在愈发广泛的领域实现深入应用,为保障公共安全和人民生命财产安全发挥更大作用。而我国在技术升级方面还有继续研究的空间,可以用更成熟的技术应用到驾驶出行的安全维护或各个领域上。尽管存在技术挑战和实施方面的难题,但随着技术进步和国际合作的加深,未来这一领域有望取得更多突破。

1.3 本文结构安排

本次设计是基于单片机的防酒驾控制系统,通过本章深入了解该系统的背景和意义,介绍了该设计所采用的基本模块和传感器。具体内容将在后续章节中详细介绍:

第二章:内容主要讲述系统的总体设计,对于主要器件的选择方案;

第三章:内容重点讲述了主要模块的电路设计;

第四章:聚焦于软件程序的设计,以主程序为核心,并详细探讨其构成中各个模块的子程序设计;

第五章:对实物进行调试与测试,确保预期功能的实现;

第六章:对系统的基本功能、创作历程和实践心得进行总结,与对未来发展的展望。

第2章 总体设计方案

2.1 系统总体设计

本设计围绕STM32单片机,设计基于单片机的防酒驾控制系统,总体设计思路为:

MQ-3酒精气体传感器首先监测环境中酒精浓度,由电路将采集到的信息转换为模拟电压信号传递给单片机,单片机利用其内置的A/D转换模块,将这些模拟信号高效地转换为数字信号,单片机随后对转换后的数字信号进行深入的分析与处理,将其转化为具体的值并直观显示在OLED屏幕上,同时将酒精浓度值与阈值进行比较,对于超过阈值的情况进行警示并发送短信4。设计方案如图2-1所示。

图2-1 系统总体设计方案

2.2 系统硬件器件选择及介绍

2.2.1 单片机

方案一:使用AT89C51单片机。AT89C51单片机因其低功耗特性和能快速擦写存储器而被视为高性能的微处理器,但其存在的一定的局限性,如不支持在线程序更新、操作上的不便、相对较慢的响应速度以及外设接口比较少,所以更适用于中小型应用场合5

方案二:使用STM32F103C8T6单片机。STM32单片机显著区别于其他同类单片机,在于其极为丰富的内部资源。它不仅提供了卓越的计算性能和快速的指令执行能力,还具备多样化的低功耗工作模式,它能够确保能效与性能的平衡。此外,STM32拥有更大的Flash和RAM内存容量,足以应对更为复杂的任务处理需求。其外设接口不仅高速而且种类繁多,进一步扩展了其在各种应用场景中的灵活性和适应性6

综上,STM32F103C8T6单片机成为防酒驾控制系统的理想选择,主要归因于其高时钟频率与强大的处理能力,这为系统的高效运行奠定了坚实基础。其丰富的外设接口直接契合了本设计的需求,无需额外添加扩展芯片,简化了系统设计复杂度。尤为值得一提的是,它采用多种低功耗技术,能保持性能同时显著降低能耗,对于需持续运行的酒精检测系统而言至关重要,有效延长了设备的使用寿命。此外,与仅具备1个串口的51单片机相比,STM32F103C8T6提供了多达5个串口,完美满足本设计中四个串口通信的需求,进一步凸显了其在功能配置上的优势7。综上所述,STM32F103C8T6单片机以其全面的性能和灵活的接口配置,成为了本设计的最终选择。

2.2.2 MQ-3酒精传感器

各类酒精传感器的比较如表2-1所示。

表2-1 酒精传感器比较

传感器类型 电化学传感器 半导体传感器 红外光谱传感器 燃料电池型传感器
工作 原理 酒精与催化剂反应释放化学能,通过能量转换器转换为电流 当酒精气体与传感器接触时电阻值发生变化 利用酒精分子对特定波长红外线的吸收特性 白金作为电极,酒精和氧气在电极上发生氧化还原反应释放电荷形成电流
特点 灵敏度高、响应速度快、测量范围广 体积小、价格低廉、易于集成 稳定性好、抗干扰能力强、准确性高 功耗低、精度高、抗干扰能力强
优点 精确度高,适合作为执法依据 成本低,适合大规模应用 可直接作为执法依据,可靠性高 高精度检测,适用于高要求场合
缺点 成本较高,对环境温度和湿度有要求 抗干扰能力较弱,复杂环境中可能出现误报或漏报 成本较高,对环境温度和湿度有要求 制造难度大,成本高昂
应用 场景 交通执法、工业生产等高精度要求场合 一般定性检测、家用酒精检测仪等 高端执法设备、专业酒精检测等 警用酒精测试仪、专业检测设备等

根据常见的酒精传感器的比较,基于需要满足体积小、成本低、易集成等特点,本设计最终采用半导体传感器MQ-3。该传感器的工作机制核心在于其电导性能对空气中酒精浓度变化的敏感响应。随着环境中酒精浓度的增加,传感器的电导性相应增强,经过电路设计后能将其转化为电压信号,该模拟电压信号就可以通过单片机处理后可以得到直观的酒精浓度值8

2.2.3 GSM短信模块

各类GSM模块的比较如表2-2所示,根据本设计需要成本低、体积小、长时间运行和发送短信时间快等特点,选择使用的通信模块为SIM800A。

表2-2 各类GSM模块

模块型号 SIM800A SIM900 SIM7000
制造商 SIMCom SIMCom SIMCom
支持网络 GSM/GPRS 900/1800MHz GSM/GPRS 2G/3G/4G
接口支持 UART, USB, SIM卡槽 UART, SIM卡, 音频接口 多接口支持
成 本 较低 中等 较高
功耗特点 适合长时间运行 适合电源要求 严苛的场景 支持多种低功耗模式
其他特点 工业级设计,性能稳定,高性价比,适用于紧凑型产品 多频段支持,低功耗设计,强大的软件支持 全球漫游,LPWAN技术,高性能
2.2.4 显示模块

方案一:LCD1602显示模块,以其低功耗和易于控制的特性而著称,然而,它也存在着视角受限以及显示分辨率和容量相对较低的缺点。LCD1602的视角范围较为有限,影响从不同角度观看的清晰度,同时,其较低的显示分辨率限制了能够展现的细节丰富度,导致屏幕上能够同时显示的内容量相对较少9

方案二:OLED显示模块,OLED显示技术有超薄厚度、宽广视角、构造简单、制程便捷以及快速响应速度等特性,其物理尺寸可能紧凑,但OLED却能提供极高的分辨率,确保了画面细节的清晰呈现,但是存在使用寿命相对较短的缺点10。LCD与OLED的对比如表2-3所示。

表2-3 LCD与OLED的对比

显示模块 LCD OLED
显示技术 液晶显示技术 发光二极管(LED)显示技术
屏幕亮度 相对较低 较高,可达600~5000cd/m²,可调节
稳定性 稳定性较好,长时间使用基本无售后 稳定性受灯珠残次性和焊接质量影响
价格 相对较低 相对较高,但性价比也较高
能耗 较高(需背光灯补光) 较低

综合考虑下,本设计选用0.96寸OLED显示屏,因为需要满足系统丰富的显示需求,包括酒精浓度、设定阈值、地理位置的经纬度以及接收短信的号码等信息,且OLED显示屏视角近乎180度,确保了内容无论从哪个角度观看都能保持清晰且不失真。尤为重要的是,这款OLED屏幕仅对需要显示的信息区域进行点亮,而其余部分则保持熄灭状态,极大地提升了显示效率并显著降低了能耗。因此,选择OLED显示屏不仅满足了系统对多样化信息显示的需求,还在节能方面展现出了卓越的性能11

第3章 硬件设计

3.1 STM32最小单片机系统电路

STM32单片机最小系统电路指能够使单片机正常工作的基本电路。最小系统电路集成了电源、复位、时钟、启动配置等关键电路及程序下载调试接口,它们协同工作以确保单片机能够执行预定任务12。STM32F103最小系统板电路如图3-1所示:

图3-1 STM32F103最小系统板电路图

3.1.1 主控单片机介绍

STM32F103C8T6的通用输入输出端口共有37个,并由外部晶振电路、复位电路、电源电路和BOOT序列启动模式配置等主要的部分组成。BOOT序列模式主要包括有三个启动方式13。三个启动方式如表3-1所示。

表3-1 启动方式

BOOT0 BOOT1 MODE
0 X FLASH
1 1 SRAM
1 0 ISP

上表中我们最常用到的模式是从FLASH中启动,即BOOT0需为0,BOOT1X可以是0或1的启动方式。

3.1.2 单片机的复位电路

系统支持通过复位电路支持多种复位方式,首要的是上电复位,它在单片机初次接通电源时自动执行,确保复位引脚维持低电平状态以初始化单片机。其次是手动复位,允许用户在需要时通过按键操作来触发复位,在程序崩溃或系统更新时至关重要14。复位电路如图3-2所示。

图3-2 复位电路图

3.1.3 单片机的晶振电路

STM32单片机正常工作的基石在于其内部集成的晶振电路,该电路负责提供稳定的8MHz高速内部时钟信号,这是由RC振荡器产生的时钟信号,并在单片机初始化过程中,通过编程选择作为内核的主要时钟源。晶振电路如图3-3所示。

图3-3 晶振电路图

3.1.4 其他电路

STM32单片机需要稳定的电压来供电,这个电压通常是3.3V,而一般电源的输入电压为5V,因此设计了稳压电路,将外部提供的5V电源稳定地降低到3.3V,以传给单片机系统供电。其中滤波电容是用于滤除电源中的噪声,确保供给单片机的电压是干净和稳定的。稳压电路图如图3-4所示。

图3-4 稳压电路图

本设计选用SWD接口来进行程序下载和调试,因为SWD接口是一种简化的调试接口,具有接线少、方便使用的特点。并通过杜邦线和STLINK下载器将代码下载到stm32单片机进行程序的烧录调试。SWD烧录接口电路图如图3-5所示。

图3-5 SWD烧录接口电路图

本设计采用使用USB转DC线进行供电,USB转DC线体积小、重量轻,易于携带和存储,此外,还内置了过流保护机制,可以在电流过大时自动切断电源供应,防止电子设计作品因电流过大而损坏。电源模块包括一个3脚的电源座子和6脚的电源开关,电源座子连接外部电源插头,电源开关控制整个单片机电路的开关。电源接口电路如图3-6所示。

图3-6 电源接口电路图

3.2 酒精传感器模块的电路设计

本次设计中使用型号为MQ-3的酒精传感器,该传感器具备六个针状管脚,为了准确读取酒精气体信号,设有四个专用引脚负责信号采集,而另外两个引脚通过提供电流以加热传感器。MQ-3的管脚布局如图3-7所示。A脚与B脚作为信号读取的关键引脚,而用于加热电阻丝的是两个f引脚。

图3-7 MQ-3的管脚分布

传感器及信号处理电路如图3-8所示。电源模块为MQ-3传感器提供5V电压,因为酒精传感器内部的电路和元件在5V电压下能够稳定、高效地运行,确保传感器能够准确检测酒精浓度。传感器通过检测酒精浓度,其电导率随浓度升高而增大,输出电压随之增大,经电位器处理后,B1引脚输出信号至单片机进行解析15

图3-8 传感器及信号处理电路

3.3 GSM短信提醒电路设计

检测到酒精浓度超过阈值时,单片机通过PA10、PA9与模块的发送端和接收端相接,以控制SIM800模块向预设手机号发送警示短信。这里本设计使用5v的电源,因为GSM属于大电流的器件,若电流较小困难会导致发送短信失败。GSM短信提醒电路如图3-9所示。

图3-9 GSM短信提醒电路

3.4 GPS模块电路设计

本设计采用的是型号为VK2828U7的GPS模块,它利用内置的接收天线捕获卫星信号,随后经过一系列复杂的信号处理流程,包括变频、信号增强、滤波、相关性分析、以及再次混频等,实现精确追踪、锁定及测量视野内的卫星,基于所捕获的卫星位置数据和信号传播时间的精确计算,能够推算出系统所在的具体位置。GPS模块电路设计如图3-10所示。

图3-10 GPS模块电路设计

3.5 OLED显示电路设计

本设计采用的是四脚的OLED屏幕显示器,主要显示的是当前环境中酒精浓度、预设的酒精浓度阈值、接收短信的号码和系统当前的经纬度信息,此外,OLED通过SCL引脚传输串行时钟数据,通过SDA引脚传输串行数据。OLED显示模块的电路如图3-11所示。

图3-11 OLED显示模块

3.6 继电器电路设计

本设计采用的8050三极管,为应对继电器断开瞬间可能产生的反向电流,电路引入二极管以吸收这一瞬态的反向电流,确保电路的安全。为防止继电器因电流不稳定而过热损坏,电路中加入了电阻。当单片机将向三极管的基极JDQ引脚发送高电平信号,三极管进入导通状态,此时继电器开关会打向5脚,起到控制发动机强制熄火的作用。电路设计如图3-12所示。

图3-12 继电器控制电路设计

3.7 声光报警电路设计

声光报警电路由蜂鸣器加三极管驱动电路组成。考虑到单片机IO口的驱动能力有限,因此使用三极管,通过增强信号强度来确保蜂鸣器能够正常发声。为安全驱动并保护三极管免遭过流损坏,电路引入了上拉电阻,在晶体管导通时限流。当BEEP引脚输入高电平信号,三极管导通,LED灯亮起和蜂鸣器形成声光报警电路。电路设计如图3-13所示。

图3-13 声光报警电路

第4章 软件设计

4.1 Keil5软件开发环境

KEIL5提供了界面友好、使用方便的工作环境,其强大功能主要体现在仿真软件和调试程序方面。在开始开发之前,首先需要新建一个自定义命名的工程文件夹,并选择STM32F103C8T6单片机。相比于51单片机的开发要复杂一些,本设计的程序开发前还要先处理好STM32的标准库函数。在编写程序前,需要从STM32官网下载Src和Inc的压缩文件,要创建多个文件夹合理存放不同类型的必要文件,如将STM32启动文件、内核及外设寄存器描述文件置于start文件夹,库函数源文件则存放于library文件夹。软件开发环境如图4-1所示。

图4-1 软件Keil5开发环境

4.2 主程序设计

主程序旨在集成硬件实现酒精浓度的监测与响应。系统上电即初始化,通过按键设定阈值后,持续监测酒精浓度,并显示浓度、阈值、系统经纬度和接收短信号码,一旦浓度超过预设的阈值,立即触发警示,闭合继电器,并自动通过GSM发送警报短信。该主程序的流程图如图4-2所示。

图4-2 主程序流程图

4.3 子程序设计

4.3.1 酒精浓度采集程序设计

首先进行初始化配置,配置模拟输入引脚,单片机的模拟数字转换器设置成连续扫描模式,并选择数据通道。当酒精传感器采集到模拟的数据后,把模拟量传输给单片机把当前读取的模拟信息转换为数字量,根据标定和校准数据,将处理后的数字量转换为酒精浓度数值,随后在OLED屏幕上显示。数据采集的程序流程图如图4-3所示。

图4-3 数据采集程序流程图

4.3.2 GSM串口通信程序设计

首先进行系统初始化,配置引脚,初始化AT指令,随后装载接收短信号码,当检测到的酒精浓度值大于设定的阈值时,向预先设定的号码发送警示短信,包括检测到的酒精浓度和定位信息。GSM串口通信程序流程图如图4-4所示。其中C为当前检测的酒精浓度值。

图4-4 GSM串口通信程序流程图

4.3.3 GPS程序设计

首先进行系统初始化,等待GPS模块准备就绪,随后GPS获取卫星定位信息,系统通过RXD引脚将卫星数据传递给单片机处理,单片机接收这些原始数据后进行解析与计算,以提取当前的经纬度信息,最终将解析得到的经纬度数值转换为整数格式,并进行显示。GPS程序设计流程图如图4-5所示。

图4-5 GPS程序设计流程图

4.3.4 OLED屏幕显示模块程序设计

首先进行系统初始化,引脚工作模式为开漏输出,经过酒精传感器模块和GPS模块采集数据,将数据信息传输到单片机,单片机进行数据处理后得到可视化数值,最后在液晶显示当前数据。OLED屏幕显示模块的程序流程图如4-6所示。

图4-6 OLED显示模块程序流程图

4.3.5 报警模块程序设计

系统启动后,主循环持续监测酒精浓度。一旦发现酒精浓度超过预设阈值,立即触发蜂鸣器发出警报声,并同步点亮LED报警指示灯。报警模块程序流程如图4-7所示。

图4-7 报警模块设计程序流程图

4.3.6 按键设置程序设计

系统上电预热完成初始话后,才可以进入按键设置程序。本设计中有三个按键,当有按键按下,程序判断按下的是否为移位按键,判断为按下移位按键则进入接收警示短信的号码设置,反之,进入酒精浓度阈值的设置。按键设置流程图如图4-8所示。

图4-8 按键设置程序流程图

第5章 系统调试

5.1 系统硬件调试

硬件设计是一个作品实现的基础,只有硬件设计正确才能进入下一步的软件调试。本设计使用Altium Designer软件绘制电路原理图和PCB图。在调试过程中,对照原理图仔细检查PCB板的连线,确保没有错线、开路或短路;对照硬件清单检查确保所有必要的硬件组件均已焊接齐全且型号正确;检查PCB板是否有明显的物理损伤或制造缺陷;使用电压表等工具,测试在工作中各个组件的电压是否正常,排查是否有短路、断路、焊接不完全或者漏焊的现象。调试遇到的问题与使用解决方案如表5-1所示。

表5-1 调试问题与解决方案

存在的问题 解决方案
GPS模块无法定位 补全焊点,到空旷室外使用
酒精传感器输出信号不正常 开机上电预热2分钟,提高传感器的精度,减小误差

5.2 系统软件调试

Keil5作为一款功能强大的软件,极大地简化了程序调试过程。当需要对编写的程序进行测试时,首先点击编译按钮启动编译流程。随后,在程序下方的编译提示窗口中,可以查看到是否有错误或告警信息。若发现告警,意味着程序编写中存在错误,此时可以依据告警的提示来修改和完善程序代码。接下来利用ST-LINK下载器将编译好的程序烧录到硬件中。给硬件上电后仔细观察OLED屏幕是否能正确显示编写的信息,通过反复调试,直至OLED屏幕上的显示完全符合预期,这时系统软件部分的调试工作完成。

5.3 实物测试

完成系统硬件测试后,将程序下载到单片机内进行实物作品测试,验证该系统的各部分功能,确保系统能够正常运行。在测试前做准备工作:先按下总开关,使用USB转DC线连接5v电源,开机预热2分钟。

5.3.1 传感器测试

根据作品设计,这里对酒精气体传感器进行测试。使用本设计防酒驾控制系统和国标精准酒精测试仪同时靠近盛有酒精的容器盖,进行多次测试并记录数据。测试结果如表5-2所示。

表5-2 传感器测试结果

防酒驾控制系统(mg/100ml) 国标精准酒精测试仪(mg/100ml) 相对误差
1 73 74 1.3%
2 86 86 0
3 79 80 1.2%

根据测试结果,可以发现本设计测试得到的酒精浓度与国标精准酒精测试仪的测试结果相近,且相对误差小于百分之五,排除人为操作和自然天气等因素造成的误差,可以得出结论,实验测试的结果与设计预期一致,酒精传感器功能测试成功。其中一次的测试结果如图5-1所示。

图5-1 酒精传感器测试

5.3.2 GSM短信模块测试

根据作品设计,这里对GSM短信模块进行测试。主要测试当酒精浓度超标时,设置的手机号码能否正确接收到短信。将一张手机卡插入GSM模块中,再将GSM模块插回系统板上,将将酒精传感器靠近装有酒精的盖子,持续至OLED显示屏上的酒精浓度读数超出阈值。测试结果记录于表5-3。

表5-3 GSM短信测试模块

酒精浓度(mg/100ml) 阈值(mg/100ml) 是否发送短信
1 53 80
2 74 80
3 81 80
4 85 80

测试发现,刚开始GSM模块的信号指示灯会以约一秒一次的频率快速闪烁,等待一段时间后,发现GSM模块的信号指示灯的闪烁频率变成约三秒闪烁一次,在检测到酒精浓度超过阈值后30秒内,设置的手机号码收到警示短信,短信内容包括检测到的酒精浓度和定位。由此可以得出结论,实验测试结果与设计预期一致,GSM短信模块功能测试成功。GSM短信测试结果如图5-2所示,OLED显示结果如图5-3所示。

图5-2 GSM短信模块

图5-3 OLED显示

5.3.3 GPS模块测试

根据作品设计,这里对GPS模块进行测试。主要测试当酒精浓度超标时,GPS模块在OLED显示屏上显示的定位与卫星地图显示的定位信息是否吻合。将测试所得的系统定位信息输入卫星地图,并观察与实际系统所处位置是否一致。开机等待两分钟,将酒精传感器靠近盛有酒精的盖子,持续至OLED显示屏的酒精浓度读数超出阈值,进行多次测试,对比定位信息于表5-4。

表5-4 GPS模块测试

系统位置 OLED显示经度/纬度 卫星地图经度/纬度 是否与卫星地图 定位信息一致
贺州学院西校区 东北门 111.511765/ 24.415952 111.511761/ 24.415949
贺州学院西校区 西苑崇师楼 111.505814/ 24.411490 111.505827/ 24.411483
贺州学院西校区附属博雅实验幼儿园 111.508590/ 24.420946 111.508583/ 24.420950

测试发现,刚上电时,GPS模块的红色信号指示灯常亮,等待一段时间后,GPS模块上的绿色信号指示灯一约一秒一次的频率闪烁,OLED上显示系统的经纬度,对比发现,系统测试所得的经纬度与卫星地图中的经纬度吻合。由此可以得出结论,实验测试的结果与设计预期一致,GPS模块测试成功。系统在贺州学院西校区西苑崇师楼定位如图5-4所示。测试卫星地图定位如图5-5所示。系统实际定位如图5-6所示。

图5-4 GPS模块测试

图5-5 系统测试卫星地图定位

图5-6 系统实际卫星地图定位

5.3.4 报警电路、继电器测试

根据作品设计,这里对报警电路和继电器模块进行测试。主要测试当酒精浓度超标时,系统能否进行报警和关闭发动机。将酒精传感器靠近盛有酒精的盖子,直到OLED模块显示的酒精浓度超过阈值,将报警情况记录于表5-5。

表5-5 报警电路测试

阈值(mg/100ml) 酒精浓度(mg/100ml) 蜂鸣器是否报警 二极管是否发光
1 80 79
2 80 80
3 80 81

测试发现,OLED显示屏上显示的酒精浓度维持在阈值以下时,系统保持静默,蜂鸣器不启动报警,同时黄色指示灯保持熄灭状态。当浓度读数超越阈值,系统立即触发蜂鸣器报警,并点亮黄色指示灯作为警示,表示系统检测到酒精浓度超标。蓝色LED灯亮,表示继电器已模拟关闭发动机。由此可以得出结论,实验测试的结果与设计预期一致,测试成功。测试结果如图5-7所示。

图5-7 报警电路测试

5.4 本章小结

在本章对系统进行了全面的调试和测试,也通过调试发现一些问题并采取相应措施。在测试中对酒精传感器、GSM短信模块、GPS模块和报警电路进行了测试,实现了酒精浓度的实时监测,并对酒精浓度超过阈值的情况进行警示和显示系统当前定位的功能,最终达到了预期的目标。在调试中进行了系统软硬件的调试,我认识到细心的重要性,焊接和画图都需要非常细致,否则焊接不当或选错封装都容易导致实验的失败。本系统也存在不完善之处,由于成本和资源的考虑,本设计的GPS定位仅支持在空旷的地方使用,继电器模拟发动机关闭的模块设计简单。

第6章 总结

本设计是一款基于STM32的防酒驾控制系统,系统融合了酒精传感器、GSM短信模块以及GPS模块,实现了酒精浓度的实时监测、阈值判断、远程报警及位置追踪等功能。这些功能的协同作用,为有效预防酒后驾车的行为提供了强有力的技术支持。此外本设计的软、硬件的设计和调试都已完成,验证了系统在酒精浓度检测的准确性、报警机制的可靠性以及GSM与GPS通信的稳定性等功能,基本已达到了设计指标的要求。

在毕业设计的征途上,尤其是电路设计与程序设计方面存在许多复杂的难题。面对STM32单片机与其他外设或传感器之间的集成问题,还需要深入考虑协议兼容性、信号电平的匹配以及数据格式的规范等关键因素。为了克服这些障碍,需要广泛搜集并研读了大量相关文献资料,同时积极向老师请教,随后,基于这些学习与理解,才能够完成硬件电路的设计和相应程序的编写,以确保项目的顺利推进。

本设计在传统酒精检测的基础上,增加了系统定位和短信警示的功能,能够为车辆的安全驾驶提供多一层保障。但是本系统设计还不够完善,由于相关的知识比较匮乏、资金条件有限等原因,该系统还存在可以改进之处,如可以将继电器模块连接一个真实的小车完善系统。独立完成一个设计作品,不仅可以积累更为丰富的知识,还可以提升面对问题时的解决能力。经过对本系统深入的钻研与实践,可以对STM32单片机的架构、寄存器配置方法、中断管理机制以及定时器的灵活运用等方面,均取得更为深刻的理解,明白实践出真知的道理,理论知识是基础,但只有通过实践才能真正掌握和应用,在项目中遇到问题时,勇于通过实践来寻找解决方案,才能收获更多的经验。

未来,还可以考虑引入更先进的传感器技术,提高酒精检测的精度和灵敏度,优化系统的数据处理算法和通信协议,降低功耗,提高系统的整体性能。还可以探索将系统与其他智能交通系统进行集成和联动,实现更广泛的交通安全管理应用。总之,通过不断的技术革新和实践应用,还可以将系统打造得更加完善、更加高效,为构建安全、和谐的交通环境贡献更大的力量。

参考文献

何翔,童俊炜,张浩桐.基于单片机的汽车酒驾检测系统研究J.机电产品开发与创新,2024,37(03):83-86.

秋实.荔枝含酒精?J.儿童故事画报,2024,(18):20-23.

曾丽霞.车内酒精浓度检测与安全控制系统J.机械工程师,2021,(01):43-45.

罗怡,宁媛.酒精浓度在线检测仪设计J.智能计算机与应用,2022,12(12):218-220+225.

何翔,童俊炜,张浩桐.基于单片机的汽车酒驾检测系统研究J.机电产品开发与创新,2024,37(03):83-86.

董宏静,杨宁,李政坤.酒精含量检测仪检定装置的长期稳定性研究J.计量与测试技术,2024,51(04):103-105.

喜琍,郭雷.基于STC89C52RC单片机的酒驾报警器设计J.无线互联科技,2023,20(09):89-92.

铁争鸣.汽车防酒驾控制装置设计研究J.微型电脑应用,2020,36(05):120-123.

苏杰仁.字符型LCD1602显示分析与实现J.科技资讯,2022,20(22):9-12+160.

宋晓宇,高国伟,李世川,等.基于单片机控制的酒精浓度检测系统的设计J.传感器世界,2017,23(08):18-23.

郭新伟,李雅青,袁凯,等.基于STM32的智能防酒驾装置设计J.自动化应用,2020,(04):138-139+143. 1.

凯.警察酒精检测权的定位、运行规制及权利救济J.广西警察学院学报,2021,34(01):56-62.

张茜,朱庆宇,郑铸.基于STM32集成于方向盘的酒精检测系统J.数码世界2019,(07):131.

姜胜鑫.基于单片机的酒精检测防醉驾系统J.信息通信,2020,(03):131-132.

南东冉,刘淑荣,张坤,等.基于单片机控制的智能保驾酒精检测系统设计J.技术与市场,2023,30(04):112-114.

致 谢

大学时光转瞬即逝,在准备毕业设计的几个月里,我发现了自己还有很多的浅薄之处,在毕业设计的过程里深刻体会到研究设计的不易,在这个过程中接触到很多新的知识,也对曾经学习过的知识有了更深刻的理解和领悟,在此过程中我在不断地查找文献,不断学习新知识,我也在充实自己,收获颇多。

本次的毕业设计就是对大学以来的努力的一次验收,完成本次毕业设计作品和设计论文离不开老师们和同学们的帮助和支持,对于本次毕业设计论文的撰写,我最想要感谢的就是是刘宗强老师、黄丹老师和谢禹鑫老师,这篇毕业设计论文的完成离不开老师们的细心指导,无论是作品或是论文的完成他们都给予了我帮助和支持,老师们会及时接收并细心观察我的每一稿论文,发现有不足的地方都会耐心指导,让我能很快知道自己的不足之处并及时修改出来。在项目的每一个阶段,您都以专业的知识、严谨的态度和耐心的指导,为我指明了方向,解决了许多技术难题。您们的悉心教诲不仅让我在项目上取得了显著的进展,更在科研方法和学术态度上给予了我深远的影响。您的言传身教,将是我人生道路上宝贵的财富,师恩似海,学生将永生难忘,在此,我要向诸位老师深深地鞠上一躬!

同时,我还要感谢学校和学院为我们提供的良好学习环境和资源支持。从实验设备的配备到图书资料的提供,再到各种学术讲座和交流活动的组织,这些都为我们的项目研究奠定了坚实的基础。学校的培养让我有机会将理论知识与实际应用相结合,不断提升自己的专业素养和实践能力。没有他们的帮助和支持,也就没有现在的我。我再次向所有给予我帮助的人们表示最衷心的感谢!我将继续努力学习和工作,以更加优异的成绩回报你们的期望和信任。

附 录

附录一:电路原理图

附录二:PCB设计图

附录三:实物图

附录四:元器件清单

规格 名称 标号 数量
1000UF 电解电容 C4 1
IN4148/4007 二极管 D2 1
KEY1 按键 K1, K2, K3 3
S8050 三极管 Q3, Q4 2
1K 电阻 R5, R10 3
10K 电阻 R9, R10 2
10 K 电阻 R13 1
10K 电位器 RT1 1
POW 电源 U1 1
SWITCH 开关 U2 1
MQ-3 酒精传感器 U6 1
BELL 蜂鸣器 U8 1
OLED 液晶显示屏 U9 1
JDQ-5 继电器 U10 1
GPS VK2828U7 GPS定位 U21 1

附录五:设计主程序代码

#include "stm32f10x.h"

#include "OLED_I2C.h"

#include "led.h"

#include "delay.h"

#include "stmflash.h"

#include "usart1.h"

#include "usart3.h"

#include "key.h"

#include "adc.h"

#include "stdio.h"

#include "string.h"

#include "GPS.h"

#define STM32_RX1_BUF Usart1RecBuf

#define STM32_Rx1Counter RxCounter

#define STM32_RX1BUFF_SIZE USART1_RXBUFF_SIZE

#define STM32_RX3_BUF Usart3RecBuf

#define STM32_Rx3Counter Rx3Counter

#define STM32_RX3BUFF_SIZE USART3_RXBUFF_SIZE

#define FLASH_SAVE_ADDR ((u32)0x0800F000)

#define K_MG_MV 80/160

#define K_ZERO 15

#define GPS_STR_LEN 48

GPS_INFO GPS;

extern unsigned char rev_start;

extern unsigned char rev_stop;

extern unsigned char gps_flag;

u8 GPS_rx_flag = 0;

long ALValue;

u16 AValueMax=80;

u8 setn=0;

char PhoneNumber11;

char ConversionNum44;

u8 GpsInitOkFlag=0;

char display16;

void gsm_atcmd_send(char *at)

{

unsigned short waittry;

do

{

gsm_rev_start = 0;

gsm_rev_okflag = 0;

waittry = 0;

uart_send((unsigned char *)at,0xFF);

while(waittry ++ < 3000)/

{

if (gsm_rev_okflag == 1)

{

return;

}

DelayMs(1);

}

}

while(gsm_rev_okflag == 0);

}

void gsm_init(void)//gsm

{

gsm_atcmd_send("AT\r\n");

DelayMs(1000);

gsm_atcmd_send("AT+CSCS=\"UCS2\"\r\n");

DelayMs(1000);

gsm_atcmd_send("AT+CMGF=1\r\n");

DelayMs(1000);

gsm_atcmd_send("AT+CNMI=2,1\r\n");

DelayMs(1000);

gsm_atcmd_send("AT+CMGD=1,4\r\n");

DelayMs(1000);

gsm_atcmd_send("AT+CSMP=17,0,2,25\r\n");

DelayMs(1000);

}

void gsm_send_msg(const char*number,char * content)

{

u8 len;

unsigned char gsm_at_txbuf60;

memset(gsm_at_txbuf, 0, 60);

strncpy((char *)gsm_at_txbuf,"AT+CMGS=\"",9);

memcpy(gsm_at_txbuf + 9, number, 44);

len = strlen((char *)gsm_at_txbuf);

gsm_at_txbuflen = '"';

gsm_at_txbuflen + 1 = '\r';

gsm_at_txbuflen + 2 = '\n';

uart_send(gsm_at_txbuf,0xFF);

DelayMs(1000);

uart_send((unsigned char *)content,0xFF);

DelayMs(100);

printf("%c",0x1a);

DelayMs(10);

}

void PhoneNumTranscoding(void)

{

u8 i=0;

for(i=0;i<11;i++)/

{

ConversionNumi\*4+0 = '0';

ConversionNumi\*4+1 = '0';

ConversionNumi\*4+2 = '3';

ConversionNumi\*4+3 = PhoneNumberi;

}

}

void Transcoding(char *str1,char *str2)

{

u8 i=0,len;

char *buf = str1;

len = strlen(buf);

for(i=0; i < len; i++)

{

if(bufi!= ' ')

{

*str2++ = '0';

*str2++ = '0';

*str2++ = '3';

*str2++ = bufi;

}

}

*str2 = '\0';

}

void CheckNewMcu(void)

{

u8 comper_str6;

STMFLASH_Read(FLASH_SAVE_ADDR + 0x10,(u16*)comper_str,5);

comper_str5 = '\0';

if(strstr((char *)comper_str,"STM32") == NULL)

{

STMFLASH_Write(FLASH_SAVE_ADDR + 0x10,(u16*)"STM32",5);

DelayMs(50);

STMFLASH_Write(FLASH_SAVE_ADDR + 0x40,(u16*)"12345678910",11);

DelayMs(50);

}

STMFLASH_Read(FLASH_SAVE_ADDR + 0x40,(u16*)PhoneNumber,11);

PhoneNumTranscoding();

DelayMs(100);

}

void DisplayLongitudeAndLatitude(void)

{

char display11;

sprintf((char *)display,"%10.6f ",GPS.longitude_Degree);

OLED_ShowStr(40, 0, (u8*)display, 2);

sprintf((char *)display,"%10.6f ",GPS.latitude_Degree);

OLED_ShowStr(40, 2, (u8*)display, 2);

}

void DisplaySetValue(void)

{

u8 x,i;

x=2;

for(i=0;i<11;i++)

{

OLED_ShowChar((x++)*8,4,PhoneNumberi,2,(setn+1)-(1+i));

DelayMs(5);

}

}

void sim800_send(unsigned char *content)

{

u8 send_error = 0;

u16 send_count = 0;

gsm_rev_okflag = 0;

OLED_ShowStr(0,6," Send Sms... ",2);

gsm_send_msg(ConversionNum,(char *)content);

DelayMs(2000);

DelayMs(2000);

DelayMs(2000);

while(gsm_rev_okflag == 0)

{

if(send_count++ > 8000)

{

send_count = 0;

send_error = 1;

break;

}

DelayMs(1);

};

gsm_rev_okflag = 0;

if(send_error == 1)

OLED_ShowStr(0,6," Send Fail! ",2);

else

OLED_ShowStr(0,6," Send OK! ",2);

memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);

STM32_Rx1Counter = 0;

DelayMs(2000);

DelayMs(2000);

DelayMs(2000);

OLED_ShowStr(0,6," ",2);

sprintf((char *)display,"SET:%dmg/100ml ",AValueMax);

OLED_ShowStr(0,6,(unsigned char *)display,2);

}

void AddressTranscoding(char *str1,char *str2)

{

u8 i=0,len;

char *buf = str1;

len = strlen(buf);

for(i=0; i < 3; i++)

{

if(bufi!= ' ')

{

*str2++ = '0';

*str2++ = '0';

*str2++ = '3';

*str2++ = bufi;

}

}

*str2++ = '0';*str2++ = '0';

*str2++ = '2';*str2++ = 'E';

i++;

for(;i < len-1; i++)

{

*str2++ = '0';

*str2++ = '0';

*str2++ = '3';

*str2++ = bufi;

}

*str2 = '\0';

}

void ContentHandle(void)

{

char TXbuf400,databuf50;

char tempbuf50;

memset(TXbuf,0, 400);

memset(databuf,0,50);

strncpy(TXbuf,"91527CBE6D535EA68D856807FF01",28);

strcat(TXbuf,"91527CBE6D535EA6003A");

memset(databuf,0,50);

memset(tempbuf,0,50);

sprintf((char *)tempbuf,"%d ",(int)ALValue);

Transcoding(tempbuf,databuf);

strcat(TXbuf,databuf);

strcat(TXbuf,"006D0067002F003100300030006D006C");

if(GpsInitOkFlag==1)

{

strcat(TXbuf,"300283B753D652305B9A4F4DFF0C5B9A4F4D573057404E3A003A");

}

else

{

strcat(TXbuf,"3002672A83B753D652305B9A4F4DFF0C67008FD14E006B215B9A4F4D573057404E3A003A");

}

strcat(TXbuf,"7ECF5EA6");

memset(databuf,0,50);

memset(tempbuf,0,50);

sprintf((char *)tempbuf,"%10.6f ",GPS.longitude_Degree);

AddressTranscoding(tempbuf,databuf);

strcat(TXbuf,databuf);

strcat(TXbuf,"FF0C7EAC5EA6");

memset(databuf,0,50);

memset(tempbuf,0,50);

sprintf((char *)tempbuf,"%10.6f ",GPS.latitude_Degree);

AddressTranscoding(tempbuf,databuf);

strcat(TXbuf,databuf);

strcat(TXbuf,"3002");

sim800_send((unsigned char *)TXbuf);

}

int main(void)

{

char keynum = 0,i;

u8 error_num=0;

u16 count = 15;

u8 SendFlag=0;

u16 timeCount=0;

DelayInit();

GPS_rx_flag = 0;

BEEP_GPIO_Config();

I2C_Configuration();

CheckNewMcu();

OLED_Init();

KEY_Init();

DelayMs(200);

OLED_CLS();

OLED_ShowStr(0,2," GSM Init... ",2);

Usart1_Init(9600);

usart3_init(9600);

gsm_init();//gsm

OLED_CLS();

for(i=0;i<2;i++)OLED_ShowCN(i*16,0,i+16,0);

for(i=0;i<2;i++)OLED_ShowCN(i*16,2,i+18,0);

OLED_ShowStr(31,0,": ",2);

OLED_ShowStr(31,4,": ",2);

sprintf((char *)display,"SET:%dmg/100ml ",AValueMax);

OLED_ShowStr(0,6,(unsigned char *)display,2);

Adc_Init();

memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);

STM32_Rx1Counter = 0;

GPS_rx_flag = 1;

while(1)

{

ALValue = (long)500 * Get_Adc_Average(ADC_Channel_9,20)/ 4096;

ALValue = ALValue - K_ZERO;

if (ALValue < 0) ALValue = 0;

ALValue = ALValue * K_MG_MV;

keynum = KEY_Scan(1);

if(keynum == 1)

{

setn++;

if(setn > 11)

{

STMFLASH_Write(FLASH_SAVE_ADDR + 0x40,(u16*)PhoneNumber,11);

PhoneNumTranscoding();

setn=0;

OLED_CLS();//清屏

for(i=0;i<2;i++)OLED_ShowCN(i*16,0,i+16,0);

for(i=0;i<2;i++)OLED_ShowCN(i*16,2,i+18,0);

OLED_ShowStr(31,0,": ",2);

OLED_ShowStr(31,4,": ",2);

sprintf((char *)display,"SET:%dmg/100ml ",AValueMax);

OLED_ShowStr(0,6,(unsigned char *)display,2);

}

if(setn==1)

{

OLED_CLS();

for(i=0;i<8;i++)OLED_ShowCN(i*16,0,i+8,0);

}

if(setn!=0)

{

DisplaySetValue();

}

}

if(keynum == 2)

if(setn==0)

{

if(AValueMax<999)AValueMax++;

sprintf((char *)display,"SET:%dmg/100ml ",AValueMax);

OLED_ShowStr(0,6,(unsigned char *)display,2);

}

else

{

PhoneNumbersetn-1++;

if(PhoneNumbersetn-1>'9')PhoneNumbersetn-1='0';

DisplaySetValue();

}

}

if(keynum == 3)

{

if(setn==0)

{

if(AValueMax>0)AValueMax--;

sprintf((char *)display,"SET:%dmg/100ml ",AValueMax);

OLED_ShowStr(0,6,(unsigned char *)display,2);

}

else

{

PhoneNumbersetn-1--;

if(PhoneNumbersetn-1<'0')PhoneNumbersetn-1='9';

DisplaySetValue();

}

}

if(count++ >= 15 && setn==0)

{

count = 0;

if (rev_stop == 1 && timeCount++>=10)

{

timeCount = 0;

if (GPS_RMC_Parse(STM32_RX3_BUF, &GPS))

{

error_num = 0;

gps_flag = 0;

rev_stop = 0;

GpsInitOkFlag=1;

}

else

{

if (error_num++ >= 5)

{

error_num = 5;

GpsInitOkFlag = 0;

}

gps_flag = 0;

rev_stop = 0;

}

}

DisplayLongitudeAndLatitude();

sprintf((char *)display,"%dmg/100ml ",ALValue);

OLED_ShowStr(0,4,(unsigned char *)display,2);

if(ALValue>=AValueMax)

{

BEEP = 1;RELAY=1;

if(SendFlag==0)

{

SendFlag = 1;

ContentHandle();

}

}

else

{

BEEP = 0;RELAY=0;

SendFlag = 0;

}

}

}

}