STM32 + MQ-5 可燃气体检测实验全解析
一、项目概述
本文将详细解析一个基于 STM32L431VCTx 微控制器和 MQ-5 可燃气体传感器的检测实验项目。该项目实现了可燃气体的实时检测功能,并通过 LCD 显示屏和串口两种方式输出检测结果,是物联网嵌入式开发中非常经典的传感器应用案例。
✨ 项目亮点
- 基于 STM32L4 系列低功耗微控制器
- MQ-5 可燃气体传感器数字量输出检测
- 240×320 TFT LCD 彩屏实时显示
- UART 串口数据输出,便于调试
- LED 状态指示,直观反馈系统运行状态
二、硬件架构
2.1 系统组成
整个系统由三大核心模块组成:主控单元、传感器单元和显示输出单元。
| 模块 | 器件型号 | 功能说明 |
|---|---|---|
| 主控单元 | STM32L431VCTx | ARM Cortex-M4 内核,80MHz 主频,低功耗 |
| 气体传感器 | MQ-5 | 可燃气体检测,数字量输出 |
| 显示模块 | 2.4寸 TFT LCD | 240×320 分辨率,SPI 接口 |
| 串口通信 | USART2 | 115200 波特率,调试数据输出 |
| 状态指示 | LED | 系统运行状态指示 |
2.2 MQ-5 传感器简介
MQ-5 是一款常用的可燃气体传感器,对液化气、甲烷、丙烷、氢气等可燃气体具有较高的灵敏度。传感器内部由气敏元件和比较电路组成,当检测到可燃气体浓度超过阈值时,数字输出引脚(DO)会输出低电平信号。
⚠️ 注意事项
- MQ-5 传感器需要预热 2-3 分钟才能稳定工作
- 传感器灵敏度可通过板载电位器进行调节
- 本实验使用数字量输出(DO),模拟量输出(AO)未使用
2.3 引脚连接
传感器与 STM32 的连接方式如下:
| MQ-5 引脚 | STM32 引脚 | 功能说明 |
|---|---|---|
| VCC | 5V | 电源正极 |
| GND | GND | 电源地 |
| DO(数字输出) | PD15 | 气体检测信号输入,上拉输入模式 |
三、软件架构
3.1 项目目录结构
项目采用标准的 STM32 HAL 库工程结构,核心代码组织如下:
ZHIoT_Sensor_Gas/
├── Src/ # 应用层源码
│ ├── main.c # 主程序入口
│ ├── gpio.c # GPIO 初始化
│ ├── spi.c # SPI 初始化(LCD用)
│ ├── usart.c # 串口初始化
│ └── stm32l4xx_it.c # 中断处理
├── Inc/ # 应用层头文件
├── Hardware/ # 硬件驱动层
│ ├── MQ_5/ # MQ-5 传感器驱动
│ │ ├── mq_5.c
│ │ └── mq_5.h
│ ├── LCD/ # LCD 显示屏驱动
│ │ ├── lcd.c
│ │ └── lcd.h
│ ├── GUI/ # 图形界面库
│ │ ├── GUI.c
│ │ └── GUI.h
│ ├── ICON/ # 图标资源
│ │ └── gas.h
│ └── HANDLE/ # 业务逻辑处理
│ ├── handle.c
│ └── handle.h
├── Drivers/ # HAL 库驱动
└── MDK-ARM/ # Keil 工程文件
3.2 主程序流程
系统主程序采用经典的初始化 + 超级循环(super loop)架构:
┌─────────────────────────┐
│ 系统启动 │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ HAL_Init() │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ SystemClock_Config() │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ 外设初始化 │
│ LCD / UART / GPIO / MQ5│
│ 串口打印欢迎信息 │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ while(1) 主循环 │
│ MQ5_Handle() 每秒检测 │
└───────────┬─────────────┘
│
└───────┐
│ 循环
▼
(回到循环开始)
四、核心代码解析
4.1 MQ-5 传感器驱动
MQ-5 传感器驱动代码非常简洁,主要包含初始化和状态读取两个函数:
// mq_5.h
#ifndef __MQ_5_H
#define __MQ_5_H
#include "stm32l4xx_hal.h"
// 外部函数声明
extern void MQ5_Init(void);
extern uint8_t MQ5_Read_State(void);
#endif
初始化函数配置 PD15 为上拉输入模式:
// mq_5.c
#define MQ5_Pin GPIO_PIN_15
#define MQ5_GPIO_Port GPIOD
void MQ5_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOD_CLK_ENABLE(); // 使能GPIOD时钟
GPIO_InitStruct.Pin = MQ5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉输入
HAL_GPIO_Init(MQ5_GPIO_Port, &GPIO_InitStruct);
}
💡 设计要点
使用上拉输入模式的原因:当传感器未检测到气体时,DO 引脚输出高电平;检测到气体时,DO 引脚输出低电平。上拉电阻确保引脚在悬空状态下有确定的电平。返回值 1 表示无可燃气体,0 表示检测到可燃气体。
4.2 主函数实现
主函数完成系统初始化后,进入主循环持续检测气体状态:
// main.c
int main(void)
{
HAL_Init(); // HAL 库初始化
SystemClock_Config(); // 系统时钟配置
LCD_Display_Init(); // LCD 屏幕初始化显示
gpio_module_open(LEDS); // LED GPIO 初始化
uart_open(uart2, 115200); // 串口2初始化,波特率115200
printf("\r\n 可燃气体检测实验 \r\n");
printf("------------------------------\r\n");
printf("实验开始:\r\n\r\n");
MQ5_Init(); // MQ-5 传感器初始化
printf("** 气体传感器初始化\r\n");
printf("** 读取气体传感器数据\r\n");
while(1)
{
MQ5_Handle(); // 气体检测处理函数
}
}
4.3 业务逻辑处理
MQ5_Handle() 函数是核心业务逻辑,每秒检测一次气体状态并更新显示:
// handle.c
void MQ5_Handle(void)
{
uint8_t mq5_detect = 0;
static uint8_t mq2_detect_rev = 3; // 状态变化标记
static uint32_t tickstart;
// 每秒检测一次(非阻塞延时)
if((HAL_GetTick() - tickstart) >= 1000)
{
tickstart = HAL_GetTick();
if(MQ5_Read_State() == 0) // 检测到可燃气体
{
LCD_draw_bmp(96, 120, 48, gImage_yanwu); // 显示报警图标
LCD_Fill(85, 178, 140, 194, WHITE); // 刷新背景
Show_Str(85, 178, BLUE, WHITE, "有可燃气体", 16, 1);
}
else if(MQ5_Read_State() == 1) // 无可燃气体
{
LCD_draw_bmp(96, 120, 48, gImage_yanwu_hui); // 显示灰色图标
LCD_Fill(85, 178, 140, 194, WHITE); // 刷新背景
Show_Str(85, 178, BLUE, WHITE, "无可燃气体", 16, 1);
}
mq5_detect = MQ5_Read_State();
// 状态变化时才输出串口信息,减少串口数据量
if((!mq5_detect) != mq2_detect_rev)
{
printf("** combustible gas detect:%d\r\n", !mq5_detect);
mq2_detect_rev = !mq5_detect;
}
led_toggle(LED1_PORT); // LED 闪烁,表示系统运行中
}
}
✅ 代码优化技巧
- 非阻塞延时:使用
HAL_GetTick()实现秒级定时,不阻塞主循环- 状态变化检测:只有当气体状态变化时才输出串口信息,避免冗余数据
- LED 心跳:LED 每秒翻转一次,直观指示系统运行状态
- 局部刷新:只刷新状态文本区域,提高显示效率
4.4 LCD 显示初始化
LCD 初始化界面采用蓝白配色,顶部和底部为蓝色标题栏:
// handle.c
void LCD_Display_Init(void)
{
LCD_Init(); // LCD 硬件初始化
LCD_Fill(0, lcddev.height-20, lcddev.width, lcddev.height, BLUE); // 底部蓝条
LCD_Fill(0, 0, lcddev.width, 20, BLUE); // 顶部蓝条
Gui_StrCenter(0, 2, BLUE, BLUE, " ", 16, 0); // 顶部占位
Gui_StrCenter(0, 40, BLUE, WHITE, "可燃气体检测实验", 24, 1); // 标题(居中)
Gui_StrCenter(0, lcddev.height-18, BLUE, BLUE, " ", 16, 0); // 底部占位
}
五、系统时钟配置
项目使用 STM32L4 的内部高速时钟(HSI)作为时钟源,通过 PLL 倍频到 80MHz 作为系统时钟。以下是关键的时钟配置参数:
| 时钟域 | 频率 | 说明 |
|---|---|---|
| HSI | 16 MHz | 内部高速时钟,PLL 输入源 |
| SYSCLK | 80 MHz | 系统时钟(PLL 输出:16 × 20 / 4 = 80MHz) |
| HCLK | 80 MHz | AHB 总线时钟,1 分频 |
| PCLK1 | 80 MHz | APB1 总线时钟,1 分频 |
| PCLK2 | 80 MHz | APB2 总线时钟,1 分频 |
| USART3 | 80 MHz | 串口3时钟源,来自 PCLK1 |
六、实验现象与调试
6.1 正常现象
- 上电后 LCD 显示"可燃气体检测实验"标题
- 传感器预热期间,显示"无可燃气体"
- LED1 每秒闪烁一次,表示系统正常运行
- 串口每秒输出一次检测结果(状态变化时)
6.2 测试方法
可以用以下方法测试传感器功能:
- 用打火机(不点火)释放少量丁烷气体靠近传感器
- 观察 LCD 是否从"无可燃气体"变为"有可燃气体"
- 观察串口是否输出检测状态变化
- 移开气源后,观察状态是否恢复正常
⚠️ 安全提示
测试时请注意通风,避免可燃气体积聚。不要使用高浓度可燃气体直接对着传感器喷射,以免损坏传感器或造成安全隐患。实验请在老师指导下进行。
6.3 常见问题排查
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| LCD 无显示 | SPI 接线错误 / LCD 初始化失败 | 检查 SPI 接线、确认 LCD 电源正常 |
| 传感器一直报警 | 阈值过低 / 传感器损坏 | 调节传感器板载电位器,提高阈值 |
| 传感器无反应 | 接线错误 / 预热不足 | 检查 DO 引脚接线,等待 2-3 分钟预热 |
| 串口无输出 | 波特率不匹配 / TX/RX 接反 | 确认 115200 波特率,检查串口接线 |
七、扩展与改进
7.1 功能扩展方向
基于现有框架,可以进一步扩展以下功能:
- 模拟量采集:使用 ADC 采集 MQ-5 的 AO 引脚,获取气体浓度数值
- 声光报警:添加蜂鸣器,检测到气体时发出报警声
- 继电器控制:气体超标时自动启动排气扇或关闭燃气阀门
- 数据记录:使用 Flash 或 SD 卡记录历史检测数据
- 物联网上传:通过 WiFi 或 NB-IoT 将数据上传到云平台
7.2 代码优化建议
- 引入实时操作系统(RTOS),实现多任务调度
- 增加传感器滤波算法,提高检测稳定性
- 添加低功耗模式,适合电池供电场景
- 实现看门狗功能,提高系统可靠性
八、总结
本项目通过 STM32L431VCTx 微控制器和 MQ-5 可燃气体传感器,实现了一个完整的可燃气体检测系统。项目涵盖了 GPIO 输入、SPI 显示、UART 串口通信等多个 STM32 基础外设的使用,是学习嵌入式开发和物联网传感器应用的绝佳实践案例。
通过本实验,我们不仅掌握了 MQ-5 气体传感器的工作原理和使用方法,还学习了如何设计一个完整的嵌入式应用——从硬件连接、驱动编写到业务逻辑实现。希望本文能为你的物联网学习之路提供一些参考和帮助。
标签: #STM32 #MQ-5 #气体传感器 #物联网 #嵌入式开发 #HAL库 #传感器实验
更多推荐


所有评论(0)