基于STM32的智能车载酒驾检测与定位报警系统设计
项目开发背景
酒驾已成为全球范围内引发恶性交通事故的主要原因之一,对道路交通安全构成严重威胁。每年因酒驾导致的伤亡事故触目惊心,不仅造成巨大的经济损失,更给无数家庭带来无法弥补的创伤。传统的执法手段如路检抽查存在滞后性和覆盖盲区,难以实现全天候、全方位的有效监控。因此,开发一种集成于车辆内部、能在驾驶行为发生前主动干预并实时预警的智能系统,具有迫切的社会需求和重要的现实意义。
现有的酒精锁等设备功能较为单一,主要侧重于点火阻断,缺乏实时定位、远程报警及数据追溯能力。随着物联网技术的快速发展,结合高精度定位、高速无线通信和云平台技术,构建一个集酒精检测、主动控制、实时定位、远程报警及数据管理于一体的综合性解决方案成为可能。这种系统不仅能从源头阻止酒驾行为,还能在违规发生时迅速通知相关人员并精准定位车辆位置,为紧急救援和执法取证提供关键支持。
本项目旨在设计并实现基于STM32微控制器的智能车载酒驾检测与定位报警系统。通过集成高灵敏度MQ3酒精传感器、ATGM336H GPS定位模块、Air724UG 4G通信模块以及OLED显示屏等硬件,构建一个低功耗、高可靠性的嵌入式终端。系统不仅能在启动前进行酒精浓度判断并控制继电器禁止超标车辆点火,还能在行驶中持续监测,一旦发现酒驾即触发蜂鸣器报警,同时通过4G模块将定位信息及检测数据实时上传至华为云物联网平台,并自动发送预警短信至预设家属联系人。配合本地OLED状态显示及Qt开发的上位机软件,形成“端-云-管”协同的完整酒驾防控体系,符合智慧交通与汽车电子安全的发展趋势,对提升道路交通安全水平具有积极意义。
设计实现的功能
(1)启动前酒精浓度检测:通过MQ3酒精传感器采集模拟信号,STM32进行ADC转换处理
(2)超标禁止点火:酒精浓度超标时,STM32控制继电器断开点火电路
(3)蜂鸣器报警:检测超标时触发有源蜂鸣器发出警报
(4)短信报警:通过4G模块内置AT指令向家属手机发送酒驾报警短信
(5)GPS定位:通过ATGM336H-5N模块实时获取车辆经纬度信息
(6)云平台数据上传:通过4G模块以MQTT协议将酒精浓度及定位数据上传至华为云
(7)状态信息显示:在OLED屏实时显示酒精浓度、GPS定位、网络状态及系统告警信息
项目硬件模块组成
(1)STM32F103C8T6主控芯片
(2)MQ3酒精传感器(模拟信号采集)
(3)ATGM336H-5N GPS模块
(4)Air724UG 4G模块
(5)0.96寸SPI OLED显示屏
(6)高电平触发有源蜂鸣器
(7)继电器(模拟发动机点火电路)
(8)车载12V转5V稳压模块
设计意义
设计意义:
该智能车载酒驾检测与定位报警系统通过集成酒精检测、定位与远程通信功能,有效提升道路交通安全水平。系统在车辆启动前强制进行酒精浓度检测,一旦检测值超标即禁止点火,从源头阻止酒驾行为,显著降低因酒驾引发的交通事故风险,保障驾驶员及公众的生命安全。
当检测到酒驾行为时,系统自动通过4G模块向预设家属手机号发送报警短信,同时结合GPS模块提供实时位置信息,确保家属能快速获取驾驶员状态和精确位置,便于及时干预或求助,增强紧急情况下的响应效率。此外,通过MQTT协议将酒精浓度数据与位置信息上传至华为云平台,为交通管理部门提供长期监管依据,助力酒驾行为的追溯与数据分析。
本地OLED显示屏实时显示酒精浓度、车辆状态及定位信息,为驾驶员提供直观的操作反馈,增强人机交互的便捷性。继电器控制点火电路的设计以非侵入式方式实现车辆控制,确保安全性的同时避免破坏原车结构。整体系统采用车载电源供电,硬件选型兼顾稳定性与成本,对推动智能交通安全技术的普及具有实际应用价值。
设计思路
设计思路:
本系统以STM32F103C8T6微控制器为核心,通过集成多模块实现车载酒驾检测与报警功能。系统启动时,首先通过MQ3酒精传感器采集模拟信号,经STM32内置ADC转换后计算酒精浓度值。若浓度超过预设阈值,STM32立即触发高电平驱动有源蜂鸣器报警,并通过控制继电器保持断开状态以禁止车辆点火;同时OLED屏实时显示“酒精超标,禁止启动”警示信息。
当车辆行驶中检测到酒精浓度超标时,STM32通过UART串口向Air724UG 4G模块发送AT指令,启动短信报警功能,将预设的报警信息发送至家属手机。同时,ATGM336H GPS模块实时获取经纬度定位数据,STM32将酒精浓度、位置信息及时间戳通过4G模块以MQTT协议上传至华为云物联网平台,实现数据云端存储。
OLED显示屏作为本地人机交互界面,采用SPI通信协议动态展示系统状态,包括酒精浓度实时数值、GPS定位状态、网络连接情况及车辆点火控制状态。继电器模块直接连接车辆点火电路,STM32通过GPIO输出高低电平控制其通断,实现发动机的物理启停管理。
系统供电采用车载12V转5V稳压模块,确保各硬件单元稳定工作。上位机软件基于Qt5开发,通过订阅MQTT主题获取云端数据,提供实时酒精浓度监测、历史记录查询及车辆位置轨迹显示功能,形成完整的本地-云端协同监控体系。所有功能均围绕实际行车安全场景设计,确保检测、阻断、报警、定位的闭环控制逻辑。
框架图
系统框架图
+------------------------------------------------------------------------------------------------+
| 车载12V电源 |
| | |
| v |
| +--------------+ |
| | 12V转5V稳压模块 | |
| +--------------+ |
| | |
| v |
| +============================================================================================+ |
| | STM32F103C8T6 主控 | |
| | +------------------+ +------------------+ +------------------+ +----------------+ | |
| | | 酒精检测模块 |<--->| ADC采集 | | 控制逻辑 |<--->| SPI接口 | | |
| | | MQ3传感器 | | (处理模拟信号) | | (酒精超标决策) | | (OLED显示) | | |
| | +------------------+ +------------------+ +---------+--------+ +--------+-------+ | |
| | | | | | |
| | +------------------+ | | v | |
| | | 定位模块 |<---------+----------------------------+ +----------------+ | |
| | | ATGM336H GPS |<--->| UART1接口 | | OLED显示屏 | | |
| | | (经纬度数据) | | (解析NMEA协议) | | 0.96寸SPI | | |
| | +------------------+ +------------------+ +----------------+ | |
| | | | |
| | +------------------+ | | |
| | | 通信模块 |<---------+-------------------------------------------------------+ | |
| | | Air724UG 4G |<--->| UART2接口 | | |
| | | (MQTT/短信) | | (AT指令控制) | | |
| | +------------------+ +---------+--------+ | |
| | | | |
| | +------------------+ | | |
| | | 报警控制模块 |<-------------+----------------+ | |
| | | 继电器(点火控制) | | | | |
| | | 蜂鸣器 |<-------------+ | | |
| | +------------------+ +------------------+ | | |
| | | GPIO控制 |<-----+ | |
| | | (高电平触发设备) | | |
| | +------------------+ | |
| +============================================================================================+ |
| | |
| v |
| +-------------------+ |
| | 华为云物联网平台 | |
| | (MQTT数据上传) | |
| +-------------------+ |
| | |
| v |
| +---------------------+ +------------------+ +------------------+ |
| | 家属手机 |<----| 短信报警 | | Qt5上位机软件 | |
| | (接收报警短信) | | (4G模块触发) |<----| (酒驾检测/历史数据) | |
| +---------------------+ +------------------+ +------------------+ |
+------------------------------------------------------------------------------------------------+
关键流程说明
-
酒精检测与点火控制
- MQ3传感器 → ADC采集 → 控制逻辑判断
- 超标:触发蜂鸣器 + 继电器断开(禁止点火)
- 正常:继电器闭合(允许点火)
-
酒驾报警与定位
- 行驶中检测超标 → GPS获取位置 → 4G模块发送短信至家属
- 同步上传酒精数据+位置至华为云(MQTT协议)
-
状态显示
- OLED实时显示:酒精浓度、GPS状态、点火状态、网络连接
-
云平台与上位机
- 华为云存储历史数据
- Qt5上位机实现数据可视化与查询
系统总体设计
系统总体设计
本系统以STM32F103C8T6微控制器为核心,构建车载酒驾检测与报警平台。系统启动时,首先通过MQ3酒精传感器采集模拟信号,经STM32内置ADC转换为数字量。若酒精浓度超过预设阈值,STM32立即触发有源蜂鸣器报警,并通过继电器切断模拟点火电路,强制禁止车辆启动。
当车辆行驶中检测到酒精浓度超标时,系统自动启动紧急处理流程。STM32通过串口控制ATGM336H-5N GPS模块获取实时经纬度定位数据,同时驱动Air724UG 4G模块执行两项关键操作:一是通过内置AT指令向预设家属手机号发送含定位信息的报警短信;二是基于MQTT协议将酒精浓度、定位坐标及报警状态上传至华为云物联网平台,实现远程数据监控。
本地交互由0.96寸SPI OLED显示屏实时呈现,动态显示酒精浓度数值、GPS定位状态、4G网络连接状态及系统报警信息。车载12V转5V稳压模块为全系统供电,确保各硬件稳定运行。上位机端采用Qt5开发的C++软件,提供云平台数据可视化界面,支持实时酒驾报警提示及历史检测记录查询功能。
系统功能总结
功能描述 | 实现方式/硬件模块 |
---|---|
启动前酒精检测与点火控制 | MQ3酒精传感器 + STM32 ADC采集 + 继电器控制电路 |
酒驾报警短信通知家属 | Air724UG 4G模块 + AT指令发送短信 |
车辆实时定位 | ATGM336H-5N GPS模块 |
检测数据上传云平台 | Air724UG 4G模块 + MQTT协议接入华为云 |
本地状态信息显示 | 0.96寸SPI OLED显示屏 |
超标声光报警 | 高电平触发有源蜂鸣器 |
远程数据监控与历史查询 | Qt5开发的上位机软件(C++) |
车载电源管理 | 12V转5V稳压模块供电系统 |
设计的各个功能模块描述
主控模块:采用STM32F103C8T6微控制器作为系统核心,协调所有外设模块的运行,处理传感器数据、执行逻辑判断并控制输出动作,确保各功能协同工作。
酒精浓度检测模块:通过MQ3酒精传感器实时采集车内酒精浓度模拟信号,经STM32内置ADC转换为数字值。若启动前检测值超标,系统触发安全锁止;行驶中持续监测,超标时立即报警。
定位与通信模块:集成ATGM336H-5N GPS模块获取车辆实时经纬度信息。Air724UG 4G模块通过串口与STM32通信,实现双重功能:一是通过MQTT协议将酒精浓度、定位数据上传至华为云平台;二是酒驾时调用内置AT指令发送含定位信息的报警短信至预设家属号码。
显示与报警模块:0.96寸SPI OLED屏本地显示关键状态(如酒精浓度值、GPS定位状态、4G连接状态)。检测超标时,STM32输出高电平驱动有源蜂鸣器鸣响报警,同时通过继电器切断点火电路。
点火控制模块:STM32通过继电器控制发动机点火电路通断。启动前若酒精浓度超标,继电器保持断开状态禁止点火;正常时闭合继电器允许启动。继电器控制逻辑与酒精检测结果严格绑定。
供电模块:车载12V电源经稳压模块转换为5V,为STM32、传感器、GPS、4G模块等提供稳定工作电压,确保系统在车载环境下可靠运行。
数据交互模块:4G模块将酒精浓度、定位信息及报警事件通过MQTT协议上传至华为云物联网平台,支持上位机软件远程监控。Qt5开发的上位机界面可实时查看酒驾检测数据及历史记录,实现云端数据可视化分析。
上位机代码设计
上位机软件设计(基于Qt5)
#include <QMainWindow>
#include <QtCharts>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDateTime>
#include <QMessageBox>
// 主窗口类定义
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onRealTimeDataReceived(QJsonObject data);
void onHistoryQuery();
void onAlarmReceived(QString msg);
private:
// 初始化UI
void setupUI();
// 初始化数据库
void initDatabase();
// 初始化MQTT连接
void initMQTT();
// UI组件
QLabel *alcoholValue;
QLabel *gpsLocation;
QLabel *carStatus;
QLabel *lastUpdate;
QPushButton *historyBtn;
QTextEdit *alarmLog;
QTableView *historyTable;
QChartView *chartView;
// 数据库
QSqlDatabase db;
QSqlTableModel *model;
// MQTT客户端
QMqttClient *mqttClient;
};
// 主窗口实现
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
setupUI();
initDatabase();
initMQTT();
}
void MainWindow::setupUI() {
// 主布局
QWidget *centralWidget = new QWidget;
QGridLayout *layout = new QGridLayout;
// 实时数据显示区
QGroupBox *realtimeGroup = new QGroupBox("实时状态");
QFormLayout *formLayout = new QFormLayout;
alcoholValue = new QLabel("0.00 mg/L");
gpsLocation = new QLabel("N/A");
carStatus = new QLabel("正常");
lastUpdate = new QLabel("--:--:--");
formLayout->addRow("酒精浓度:", alcoholValue);
formLayout->addRow("GPS位置:", gpsLocation);
formLayout->addRow("车辆状态:", carStatus);
formLayout->addRow("更新时间:", lastUpdate);
realtimeGroup->setLayout(formLayout);
// 报警日志
QGroupBox *alarmGroup = new QGroupBox("报警记录");
alarmLog = new QTextEdit;
alarmLog->setReadOnly(true);
QVBoxLayout *alarmLayout = new QVBoxLayout;
alarmLayout->addWidget(alarmLog);
alarmGroup->setLayout(alarmLayout);
// 历史查询按钮
historyBtn = new QPushButton("查询历史数据");
connect(historyBtn, &QPushButton::clicked, this, &MainWindow::onHistoryQuery);
// 图表显示
chartView = new QChartView;
chartView->setMinimumSize(400, 300);
// 历史数据表格
historyTable = new QTableView;
// 布局组装
layout->addWidget(realtimeGroup, 0, 0);
layout->addWidget(alarmGroup, 1, 0);
layout->addWidget(historyBtn, 2, 0);
layout->addWidget(chartView, 0, 1, 2, 1);
layout->addWidget(historyTable, 3, 0, 1, 2);
centralWidget->setLayout(layout);
setCentralWidget(centralWidget);
setWindowTitle("车载酒驾监测系统");
resize(1000, 700);
}
void MainWindow::initDatabase() {
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("alcohol_data.db");
if (!db.open()) {
QMessageBox::critical(this, "数据库错误", "无法打开数据库");
return;
}
// 创建数据表
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS records ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,"
"alcohol REAL,"
"longitude REAL,"
"latitude REAL,"
"status INTEGER)");
}
void MainWindow::initMQTT() {
mqttClient = new QMqttClient(this);
mqttClient->setHostname("华为云地址");
mqttClient->setPort(1883);
mqttClient->setClientId("CarMonitoringSystem");
mqttClient->setUsername("用户名");
mqttClient->setPassword("密码");
connect(mqttClient, &QMqttClient::connected, [this]() {
mqttClient->subscribe("car/alcohol/data");
mqttClient->subscribe("car/alarm/events");
});
connect(mqttClient, &QMqttClient::messageReceived, [this](const QByteArray &msg, const QMqttTopicName &topic) {
QJsonDocument doc = QJsonDocument::fromJson(msg);
if (topic.name() == "car/alcohol/data") {
onRealTimeDataReceived(doc.object());
} else if (topic.name() == "car/alarm/events") {
onAlarmReceived(QString::fromUtf8(msg));
}
});
mqttClient->connectToHost();
}
void MainWindow::onRealTimeDataReceived(QJsonObject data) {
// 更新UI
alcoholValue->setText(QString::number(data["alcohol"].toDouble(), 'f', 2) + " mg/L");
gpsLocation->setText(QString("经度: %1, 纬度: %2")
.arg(data["lng"].toDouble())
.arg(data["lat"].toDouble()));
carStatus->setText(data["ignition"].toBool() ? "运行中" : "已熄火");
lastUpdate->setText(QDateTime::currentDateTime().toString("hh:mm:ss"));
// 存储到数据库
QSqlQuery query;
query.prepare("INSERT INTO records (alcohol, longitude, latitude, status) "
"VALUES (?, ?, ?, ?)");
query.addBindValue(data["alcohol"].toDouble());
query.addBindValue(data["lng"].toDouble());
query.addBindValue(data["lat"].toDouble());
query.addBindValue(data["ignition"].toInt());
query.exec();
}
void MainWindow::onAlarmReceived(QString msg) {
QString logEntry = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ") + msg;
alarmLog->append(logEntry);
// 弹出报警对话框
QMessageBox::critical(this, "酒驾报警", "检测到酒精超标!\n" + msg);
}
void MainWindow::onHistoryQuery() {
// 创建图表
QLineSeries *series = new QLineSeries;
QSqlQuery query("SELECT timestamp, alcohol FROM records ORDER BY timestamp");
while (query.next()) {
series->append(query.value(0).toDateTime().toMSecsSinceEpoch(),
query.value(1).toDouble());
}
QChart *chart = new QChart();
chart->addSeries(series);
chart->setTitle("酒精浓度历史趋势");
// X轴时间格式
QDateTimeAxis *axisX = new QDateTimeAxis;
axisX->setFormat("MM-dd hh:mm");
axisX->setTitleText("时间");
chart->addAxis(axisX, Qt::AlignBottom);
series->attachAxis(axisX);
// Y轴数值范围
QValueAxis *axisY = new QValueAxis;
axisY->setLabelFormat("%.2f");
axisY->setTitleText("浓度(mg/L)");
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);
chartView->setChart(chart);
// 显示表格数据
model = new QSqlTableModel(this, db);
model->setTable("records");
model->setHeaderData(0, Qt::Horizontal, "ID");
model->setHeaderData(1, Qt::Horizontal, "时间");
model->setHeaderData(2, Qt::Horizontal, "浓度");
model->setHeaderData(3, Qt::Horizontal, "经度");
model->setHeaderData(4, Qt::Horizontal, "纬度");
model->setHeaderData(5, Qt::Horizontal, "状态");
model->select();
historyTable->setModel(model);
historyTable->resizeColumnsToContents();
}
// 程序入口
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow mainWin;
mainWin.show();
return app.exec();
}
#include "main.moc"
项目结构说明
-
数据库设计
- SQLite数据库
alcohol_data.db
- 数据表
records
包含字段:- 时间戳(timestamp)
- 酒精浓度(alcohol)
- GPS经度(longitude)
- GPS纬度(latitude)
- 车辆状态(status)
- SQLite数据库
-
通信协议
- MQTT主题:
car/alcohol/data
:实时数据(JSON格式)car/alarm/events
:报警事件(文本)
- MQTT主题:
-
UI界面模块
- 实时数据显示区:酒精浓度/GPS位置/车辆状态
- 报警日志区:滚动显示历史报警
- 历史数据查询:
- 折线图展示酒精浓度变化趋势
- 表格展示详细历史记录
-
数据处理流程
Parse error on line 2: ...>>上位机: MQTT实时数据(JSON上位机->>数据库: 存储记录上位机 -----------------------^ Expecting 'TXT', got 'NEWLINE'
功能特点
- 实时监控:动态更新酒精浓度和车辆位置
- 报警管理:自动记录酒驾事件并弹窗警示
- 历史分析:支持时间范围查询和图表可视化
- 云端集成:通过MQTT对接华为云物联网平台
- 数据持久化:SQLite本地存储确保数据安全
注意:实际部署需配置华为云连接参数,包括:
- MQTT服务器地址
- 端口号
- 用户名/密码
- 设备证书信息
模块代码设计
以下为基于STM32F103C8T6的完整设备端模块代码设计(寄存器开发方式):
#include "stm32f10x.h"
// 硬件引脚定义
#define MQ3_ADC_PIN GPIO_Pin_0 // PA0 (ADC1)
#define BUZZER_PIN GPIO_Pin_5 // PB5
#define RELAY_PIN GPIO_Pin_6 // PB6
#define OLED_CS_PIN GPIO_Pin_4 // PA4
#define OLED_DC_PIN GPIO_Pin_5 // PA5 (重映射)
#define OLED_RST_PIN GPIO_Pin_6 // PA6
// 酒精浓度阈值 (单位: mg/L)
#define ALCOHOL_THRESHOLD 0.2
// 全局变量
volatile uint16_t adc_value = 0;
char gps_buffer[128] = {0};
uint8_t gps_index = 0;
// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void ADC1_Configuration(void);
void USART1_Configuration(void);
void USART2_Configuration(void);
void SPI1_Configuration(void);
void TIM2_Configuration(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowString(uint8_t x, uint8_t y, char *str);
void Send_SMS(char *phone, char *message);
void MQTT_Publish(char *data);
float Read_Alcohol(void);
void Parse_GPS(void);
int main(void) {
// 系统初始化
RCC_Configuration();
GPIO_Configuration();
ADC1_Configuration();
USART1_Configuration(); // 4G模块
USART2_Configuration(); // GPS模块
SPI1_Configuration();
TIM2_Configuration();
OLED_Init();
// 酒精检测前状态
OLED_Clear();
OLED_ShowString(0, 0, "Alcohol Test...");
float alcohol = Read_Alcohol();
// 酒精检测逻辑
if (alcohol > ALCOHOL_THRESHOLD) {
GPIO_SetBits(GPIOB, BUZZER_PIN); // 蜂鸣器报警
OLED_ShowString(0, 2, "ALCOHOL HIGH!");
OLED_ShowString(0, 4, "Start DENIED");
while(1); // 死循环阻止启动
} else {
GPIO_SetBits(GPIOB, RELAY_PIN); // 继电器吸合(点火)
OLED_ShowString(0, 2, "Start ALLOWED");
}
// 主循环
while (1) {
// 持续酒精检测
alcohol = Read_Alcohol();
if (alcohol > ALCOHOL_THRESHOLD) {
GPIO_SetBits(GPIOB, BUZZER_PIN);
Send_SMS("13800138000", "WARNING: Drunk Driving Detected!");
Parse_GPS();
char msg[50];
sprintf(msg, "Alcohol:%.2f Lat:%s Lon:%s", alcohol, lat, lon);
MQTT_Publish(msg);
OLED_ShowString(0, 4, "ALERT SENT!");
}
// OLED显示刷新
char disp_buf[20];
sprintf(disp_buf, "Alc: %.3f mg/L", alcohol);
OLED_ShowString(0, 0, disp_buf);
// 延时1秒
TIM2->CNT = 0;
while (TIM2->CNT < 1000);
}
}
// 时钟配置
void RCC_Configuration(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN |
RCC_APB2ENR_USART1EN | RCC_APB2ENR_SPI1EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_TIM2EN;
// ADC时钟分频(12MHz)
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;
}
// GPIO配置
void GPIO_Configuration(void) {
// 蜂鸣器&继电器(推挽输出)
GPIOB->CRL &= ~(0xFF << 20);
GPIOB->CRL |= (0x03 << 20) | (0x03 << 24); // PB5,PB6
// ADC引脚(模拟输入)
GPIOA->CRL &= ~0x0F; // PA0
// OLED控制引脚
GPIOA->CRL &= ~(0xFF << 16);
GPIOA->CRL |= (0x03 << 16) | (0x03 << 20) | (0x03 << 24); // PA4,PA5,PA6
}
// ADC1配置
void ADC1_Configuration(void) {
ADC1->CR2 = ADC_CR2_ADON; // 开启ADC
// 通道0采样时间239.5周期
ADC1->SMPR2 = (0x07 << 0);
// 单次转换模式
ADC1->SQR1 = 0;
ADC1->SQR3 = 0; // 通道0
// 校准
ADC1->CR2 |= ADC_CR2_RSTCAL;
while (ADC1->CR2 & ADC_CR2_RSTCAL);
ADC1->CR2 |= ADC_CR2_CAL;
while (ADC1->CR2 & ADC_CR2_CAL);
}
// USART1配置(4G模块)
void USART1_Configuration(void) {
// PA9(TX)复用推挽输出, PA10(RX)浮空输入
GPIOA->CRH &= ~(0xFF << 4);
GPIOA->CRH |= (0x0B << 4) | (0x04 << 8);
USART1->BRR = 72000000 / 115200; // 波特率115200
USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
// USART2配置(GPS模块)
void USART2_Configuration(void) {
// PA2(TX), PA3(RX)
GPIOA->CRL &= ~(0xFF << 8);
GPIOA->CRL |= (0x0B << 8) | (0x04 << 12);
USART2->BRR = 72000000 / 9600; // 波特率9600
USART2->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
// SPI1配置(OLED)
void SPI1_Configuration(void) {
// PA5(SCK), PA7(MOSI)
GPIOA->CRL &= ~(0xF0 << 20 | 0xF0 << 28);
GPIOA->CRL |= (0x0B << 20) | (0x0B << 28);
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_0 | SPI_CR1_SPE;
SPI1->CR2 = 0;
}
// 定时器2配置(延时用)
void TIM2_Configuration(void) {
TIM2->PSC = 72 - 1; // 1MHz计数
TIM2->ARR = 0xFFFF;
TIM2->CR1 = TIM_CR1_CEN;
}
// 酒精浓度读取
float Read_Alcohol(void) {
ADC1->CR2 |= ADC_CR2_ADON;
while (!(ADC1->SR & ADC_SR_EOC));
uint16_t raw = ADC1->DR;
// 转换公式: V = raw/4096*3.3V
// MQ3灵敏度: 0.05-4mg/L (需校准)
return (raw / 4096.0) * 0.8; // 示例转换系数
}
// GPS数据解析
void Parse_GPS(void) {
char *ptr = strstr(gps_buffer, "$GPRMC");
if (ptr) {
char *token = strtok(ptr, ",");
int field = 0;
char lat[10], lon[10];
while (token != NULL) {
switch (field++) {
case 3: strncpy(lat, token, 9); break; // 纬度
case 5: strncpy(lon, token, 9); break; // 经度
}
token = strtok(NULL, ",");
}
}
}
// 发送短信
void Send_SMS(char *phone, char *message) {
USART_SendString(USART1, "AT+CMGF=1\r\n"); // 文本模式
Delay(100);
USART_SendString(USART1, "AT+CMGS=\"");
USART_SendString(USART1, phone);
USART_SendString(USART1, "\"\r\n");
Delay(100);
USART_SendString(USART1, message);
USART_SendData(USART1, 0x1A); // Ctrl+Z发送
}
// MQTT数据上传
void MQTT_Publish(char *data) {
char cmd[50];
sprintf(cmd, "AT+MQTTPUB=0,\"alcohol/data\",\"%s\",0,0\r\n", data);
USART_SendString(USART1, cmd);
}
// OLED显示函数(简略实现)
void OLED_WriteCmd(uint8_t cmd) {
GPIO_ResetBits(GPIOA, OLED_DC_PIN); // DC=0命令
SPI1->DR = cmd;
while (!(SPI1->SR & SPI_SR_TXE));
}
void OLED_ShowString(uint8_t x, uint8_t y, char *str) {
// 实现字符显示逻辑
}
// USART中断处理(GPS数据接收)
void USART2_IRQHandler(void) {
if (USART2->SR & USART_SR_RXNE) {
char ch = USART2->DR;
if (ch == '\n' || gps_index >= 127) {
gps_buffer[gps_index] = '\0';
Parse_GPS();
gps_index = 0;
} else {
gps_buffer[gps_index++] = ch;
}
}
}
代码说明:
-
酒精检测模块:
- 使用ADC1采集MQ3模拟信号(PA0)
Read_Alcohol()
函数实现浓度计算(需根据传感器特性校准)
-
点火控制:
- 继电器控制引脚PB6,高电平点火
- 酒精超标时进入死循环阻止启动
-
定位报警系统:
- GPS数据通过USART2接收(PA2/PA3)
- 中断解析GPRMC语句获取经纬度
- 酒驾时通过4G模块发送报警短信
-
4G通信:
- USART1连接Air724UG模块(PA9/PA10)
- 实现AT指令控制(MQTT上传/SMS发送)
-
人机交互:
- SPI驱动OLED显示实时状态(PA4-PA7)
- 蜂鸣器报警提示(PB5)
-
安全机制:
- 启动前强制酒精检测
- 行驶中持续监控酒精浓度
- 双重报警(本地蜂鸣器+远程短信)
项目核心代码
#include "stm32f10x.h"
#include "adc.h"
#include "usart.h"
#include "spi.h"
#include "gps.h"
#include "mqtt.h"
#include "oled.h"
#include "delay.h"
// 引脚定义
#define BUZZER_PIN GPIO_Pin_12 // PB12
#define RELAY_PIN GPIO_Pin_13 // PB13
#define ALCOHOL_THRESHOLD 200 // 酒精浓度阈值 (单位: mg/L)
// 全局变量
volatile uint8_t alcohol_over = 0;
char gps_data[64] = {0};
char phone_num[15] = "+8613912345678"; // 家属电话号码
int main(void) {
// 系统初始化
SystemInit();
Delay_Init();
ADC1_Init(); // 酒精传感器ADC初始化
USART1_Init(115200); // 4G模块
USART2_Init(9600); // GPS模块
SPI1_Init(); // OLED
OLED_Init();
GPS_Init();
MQTT_Init(); // 华为云初始化
// GPIO初始化 - 蜂鸣器和继电器
RCC->APB2ENR |= RCC_APB2Periph_GPIOB;
GPIOB->CRH &= 0xFF0FFFFF;
GPIOB->CRH |= 0x00330000; // PB12/PB13推挽输出
GPIOB->ODR &= ~(RELAY_PIN | BUZZER_PIN); // 初始低电平
OLED_Clear();
OLED_ShowString(0, 0, "System Init...", 16);
Delay_Ms(1000);
// 主循环
while(1) {
// 1. 酒精检测
uint16_t alcohol_val = Get_Alcohol_Value();
OLED_ShowString(0, 2, "Alcohol:", 16);
OLED_ShowNum(72, 2, alcohol_val, 4, 16);
// 2. 点火前检测
if(alcohol_val > ALCOHOL_THRESHOLD) {
GPIOB->ODR &= ~RELAY_PIN; // 断开继电器(禁止点火)
GPIOB->ODR |= BUZZER_PIN; // 蜂鸣器报警
alcohol_over = 1;
OLED_ShowString(0, 4, "Status: DRUNK!", 16);
// 首次超标发送短信
static uint8_t first_alert = 1;
if(first_alert) {
GPS_GetData(gps_data); // 获取GPS位置
Send_Alert_SMS(phone_num, gps_data); // 发送报警短信
MQTT_Publish(alcohol_val, gps_data); // 上传云平台
first_alert = 0;
}
} else {
GPIOB->ODR |= RELAY_PIN; // 闭合继电器(允许点火)
GPIOB->ODR &= ~BUZZER_PIN; // 关闭蜂鸣器
alcohol_over = 0;
OLED_ShowString(0, 4, "Status: NORMAL ", 16);
}
// 3. 实时定位显示
if(GPS_Update()) {
GPS_GetData(gps_data);
OLED_ShowString(0, 6, gps_data, 16);
}
// 4. 数据上传云平台(每10秒)
static uint32_t upload_timer = 0;
if(HAL_GetTick() - upload_timer > 10000) {
MQTT_Publish(alcohol_val, gps_data);
upload_timer = HAL_GetTick();
}
Delay_Ms(500); // 检测周期500ms
}
}
// 酒精浓度获取函数
uint16_t Get_Alcohol_Value(void) {
ADC1->CR2 |= ADC_CR2_ADON; // 启动ADC转换
while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成
return ADC1->DR; // 返回ADC值
}
// 短信发送函数
void Send_Alert_SMS(char* num, char* loc) {
USART1_SendString("AT+CMGF=1\r\n"); // 设置文本模式
Delay_Ms(200);
USART1_SendString("AT+CMGS=\"");
USART1_SendString(num);
USART1_SendString("\"\r\n");
Delay_Ms(200);
USART1_SendString("WARNING! Drunk Driving at:");
USART1_SendString(loc);
USART1_SendByte(0x1A); // Ctrl+Z发送
}
代码说明:
-
系统初始化
- 配置时钟系统、延时函数
- 初始化ADC(酒精传感器)、USART1(4G)、USART2(GPS)、SPI(OLED)
- 设置蜂鸣器(PB12)和继电器(PB13)为输出模式
-
酒精检测
- 通过ADC连续采集MQ3传感器数据
- 超过阈值(200mg/L)时触发保护机制:
- 断开继电器禁止点火
- 启动蜂鸣器报警
- OLED显示"DRUNK!"状态
-
报警联动
- 首次检测超标时:
- 通过4G模块发送AT指令提交报警短信
- 将酒精浓度+GPS位置通过MQTT上传华为云
- 短信内容包含实时GPS位置信息
- 首次检测超标时:
-
定位功能
- 持续解析GPS模块(NMEA协议)数据
- 实时在OLED显示经纬度信息
-
状态显示
- OLED分区域显示:
- 酒精浓度实时数值
- 系统状态(正常/酒驾)
- 当前GPS位置信息
- OLED分区域显示:
-
数据上报
- 每10秒上传一次酒精浓度和位置到云平台
- 使用华为云IoTDA标准的MQTT协议
硬件操作关键点:
- 继电器高电平吸合=允许点火
- 蜂鸣器高电平触发报警
- GPS数据通过USART2接收
- 4G通信通过USART1发送AT指令
- OLED通过SPI接口刷新显示
总结
总结
本设计基于STM32F103C8T6主控芯片,构建了一套完整的智能车载酒驾检测与定位报警系统。系统通过MQ3酒精传感器实时采集驾驶员酒精浓度数据,若启动前检测超标,立即触发蜂鸣器报警并控制继电器切断点火电路,从源头杜绝酒驾行为。定位功能由ATGM336H GPS模块实现,可精准获取车辆位置信息;同时通过Air724UG 4G模块将酒精浓度、位置等关键数据实时上传至华为云物联网平台,并利用其短信功能自动向家属发送酒驾告警信息。
本地交互采用0.96寸SPI OLED显示屏,直观展示酒精浓度阈值、点火状态、GPS坐标等核心参数。供电系统通过车载12V转5V稳压模块保障设备稳定运行。上位机端基于Qt5开发酒驾监控界面,支持云平台数据解析与历史记录回溯,形成"端-云-管"协同的闭环解决方案。
该系统深度融合硬件检测、云端通信与软件管理,在主动预防酒驾、实时定位追踪、远程告警联动等方面具有显著优势,为道路交通安全提供了创新性技术保障。设计兼顾功能完备性与工程实用性,具备良好的社会推广价值。
- 点赞
- 收藏
- 关注作者
评论(0)