STM32智能安防燃气监测系统:从原理图到仿真全套开源
2026/9/16 8:24:18 网站建设 项目流程

手上有 STM32 的朋友,大概率都想过一件事:能不能把手头的开发板变成一个真正能用的东西。这篇开源项目就是干这个的——用 STM32 做一套智能安防和燃气监测系统,代码、原理图、仿真全套放出,不是拿面包板飞几根线糊弄完事,而是一个从硬件选型到软件逻辑都认真设计过、可以直接打样复现的小系统。

先说说这套东西到底能做什么。它同时接入两路传感器:一路是燃气传感器,负责检测厨房或室内的可燃气体浓度;另一路是人体红外传感器,负责探测非法闯入。两路信号进 STM32 后,系统会根据阈值判断是否触发报警,报警方式包括蜂鸣器鸣叫、LED 指示,以及继电器输出——继电器可以接电磁阀切断燃气,也可以接声光报警器。另外还带 OLED 显示屏,实时显示燃气浓度和当前报警状态,两个按键可以调节报警阈值。整套系统麻雀虽小,五脏俱全,非常适合刚学完 STM32 基础、想做综合项目的人,也适合毕业设计参考。

这个项目做出来的成品,基本就是一个迷你的“燃气报警器+人体入侵检测”二合一设备。下面我把整个项目的设计思路、硬件原理图要点、软件代码逻辑、仿真验证方法全部拆开讲一遍,最后再聊几个我踩过的坑。

1. 项目概述与整体方案设计

1.1 这个项目到底要解决什么问题

我最初想做这个项目,是发现市面上家用的燃气报警器功能太单一:只会响,不会显示浓度,更没法跟安防联动。而智能安防摄像头又有隐私问题,不适合所有场景。于是我设想,能不能用一块 STM32 把这些需求统一起来——既能监测燃气泄漏,又能检测有没有人闯入,报警方式可以灵活扩展,成本还压得很低。

实际需求拆解下来有四条:

  • 实时采集燃气传感器的模拟电压信号,换算成浓度值或至少一个等级值。
  • 实时采集人体红外传感器的高低电平信号,识别是否有人出现在检测区域。
  • 当燃气浓度超过阈值或红外触发时,启动声光报警,并驱动继电器执行切断/联动动作。
  • 通过 OLED 显示当前浓度和系统状态,支持按键调整警戒阈值。

这四条需求指向的就是一个典型的多输入、多输出的嵌入式控制系统,用 STM32F103C8T6 这种入门级 MCU 完全够跑。选它还有一个原因:Flash 64KB、RAM 20KB,哪怕开了 HAL 库、加了 OLED 驱动和滤波算法,资源也绰绰有余,成本却只有几块钱。

1.2 系统架构与工作流程

整套系统的数据流是这样的:

传感器信号先进入 STM32 的 GPIO 或 ADC 引脚,MCU 内部跑一个循环任务,周期性读取传感器状态,经过软件滤波、阈值比较后得到系统状态——正常、警戒、报警三态。状态变化会驱动输出端:蜂鸣器、LED、继电器。OLED 和按键作为人机交互,负责显示和参数调整。

核心工作流程我用文字描述一下:

  1. 系统上电初始化:时钟、GPIO、ADC、I2C、定时器全部配置好。
  2. 启动后 OLED 显示初始界面,绿色 LED 点亮表示正常。
  3. 主循环里定时读取燃气浓度和红外状态。
  4. 燃气浓度低于阈值且红外未触发,系统保持正常态。
  5. 任一条件超标,系统进入报警态:红色 LED 快闪、蜂鸣器鸣叫、继电器吸合。
  6. 按键可以调整报警阈值(加或减),OLED 实时显示。

这个流程看起来不复杂,真正要处理的是可靠性问题——怎么防止误报、怎么让传感器读数稳定、怎么处理报警后的恢复。软件部分我会在第三章详细讲。

2. 硬件设计与原理图要点

2.1 核心器件选型

硬件选型是决定项目成败的第一步。我最终确定的器件清单如下:

  • 主控芯片:STM32F103C8T6,LQFP48 封装,72MHz,64KB Flash。
  • 燃气传感器:MQ-2(也可用 MQ-5,对不同气体灵敏度侧重不同,MQ-5 对天然气更敏感)。模拟输出,接 ADC 采样。
  • 人体红外传感器:HC-SR501,输出 3.3V 高电平触发,带灵敏度调节和延时调节旋钮。
  • 显示模块:0.96 寸 OLED,SSD1306 驱动,I2C 接口。
  • 报警输出:有源蜂鸣器模块(低电平触发),红色和绿色 LED 各一个。
  • 继电器模块:5V 单路继电器,用于联动外部设备。
  • 按键:两个轻触按键,用于阈值调节。
  • 供电:USB 5V 输入,板上用 AMS1117-3.3 稳压给 STM32 供电,传感器模块和蜂鸣器直接用 5V。

选型的时候我特别注意了两个点。第一,MQ-2 是模拟输出,它需要一个加热电阻预热,功耗相对大,所以供电要用 5V 且要做好电源滤波,否则 ADC 读数会跳动得很厉害。第二,HC-SR501 输出电平是 3.3V 还是 5V 要看具体模块,大多数模块标注 3.3V 到 5V 供电,输出高电平接近供电电压,所以如果 5V 供电,输出直接进 STM32 的 GPIO 会有风险,稳妥做法是加一个分压电阻或者用 3.3V 供电,我这个项目里直接用 3.3V 给 HC-SR501 供电,输出就是 3.3V 高电平,安全匹配 GPIO。

2.2 原理图设计要点

原理图我用立创 EDA 画的,画板之前先摸清楚每个模块的引脚定义。先说 MCU 最小系统部分:

  • 8MHz 晶振接 PD0、PD1,两个 22pF 负载电容。
  • BOOT0 接 10K 下拉电阻,BOOT1 接 10K 下拉电阻,保证从 Flash 启动。
  • NRST 上拉 10K 电阻,并联 100nF 电容到地。
  • VDDA、VSSA 脚分别接 3.3V 和地,VDDA 加一个 1uF 和一个 100nF 去耦电容。
  • 每个电源引脚旁边放一个 100nF 去耦电容,这是基本素养。

然后是功能模块的接线设计,我做了一个引脚分配表,方便照抄:

功能模块MCU引脚说明
MQ-2 模拟输出PA1 (ADC1_IN1)采集燃气浓度电压
HC-SR501 输出PB1红外检测信号,GPIO输入
有源蜂鸣器PB10低电平触发
红色LEDPB11报警指示
绿色LEDPB12正常指示
继电器PB13低电平吸合
按键1(阈值加)PA4内部上拉输入
按键2(阈值减)PA5内部上拉输入
OLED SCLPB6I2C1 时钟
OLED SDAPB7I2C1 数据
USART1 TX/RXPA9/PA10预留调试串口

需要重点说明的是继电器和蜂鸣器的驱动。虽然是模块化设计,模块本身带了驱动电路,但原理图里还是要预留跳线和续流措施。继电器模块内部一般有一个 NPN 三极管和一个续流二极管,但它的控制信号高电平触发或者低电平触发要看具体型号,我的模块是低电平触发,所以 STM32 引脚输出低电平时继电器吸合,这个逻辑要跟代码对齐,否则会出现“程序想让继电器断开结果它反而吸合”的诡异现象。

蜂鸣器我选了有源蜂鸣器模块,也是低电平触发。有源蜂鸣器内部带震荡源,只要给低电平就会响,不需要用定时器输出 PWM,省一路定时器资源。如果手上是无源蜂鸣器,驱动逻辑完全不同,得用 PWM 产生一定频率的方波才能响,这个差别踩坑率极高。

OLED 模块的 I2C 上拉电阻通常已经在模块板上自带了,所以原理图里不需要再额外加,但如果你是自己做的 OLED 转接板,一定要在 SCL 和 SDA 上各接一个 4.7K 上拉电阻到 3.3V,否则 I2C 通信会不稳定。

电源部分是这套硬件最容易被忽视的地方。MQ-2 的加热丝启动瞬间电流比较大,实测可以到 150mA 以上,如果直接用 AMS1117 从 5V 转 3.3V,5V 会被拉低,导致 OLED 闪屏或者红外传感器误触发。我的解决方案是:5V 进来先经过一个 100uF 电解电容和 100nF 陶瓷电容滤波,再分出 5V 给 MQ-2、蜂鸣器、继电器;3.3V 由 AMS1117 单独供给 MCU、OLED 和红外传感器。这相当于把大功率负载和小信号负载在电源上彻底分离,实测 ADC 稳定性好了非常多。

2.3 PCB 布局与布线注意

如果你要打样 PCB,几个布局经验直接送给你们:

  • MQ-2 传感器附近不要放高热量器件,它会加热自身,周围温度场变化会导致读数漂移。
  • HC-SR501 的位置很关键,不要放在 PCB 边缘且朝外的方向,否则容易误触发,建议用排针引出,传感器本体用杜邦线外置安装。
  • 继电器是感性负载,在 PCB 上它所在的位置要远离 MCU 晶振和模拟信号走线,防止电磁干扰。
  • AD 采样走线要短,PA1 从 MQ-2 输出端过来越短越好,中间不要穿过继电器或蜂鸣器的驱动走线。

如果只是学习验证,不一定要打板,用面包板加杜邦线也能把所有模块搭起来,原理图的意义在于让你理清连接关系,仿真阶段也可以直接用原理图逻辑去验证。

3. 软件架构与代码实现

3.1 开发环境与工程初始化

软件部分我用的开发环境是 Keil MDK5 + STM32CubeMX。CubeMX 负责初始化时钟和引脚,Keil 里写业务逻辑。这套组合是现在 STM32 开发的主流姿势,HAL 库虽然啰嗦,但胜在可读性好、不容易把寄存器写错,适合开源项目让别人也看得懂。

CubeMX 里需要配置的内容:

  • RCC:外部高速时钟 HSE 接 8MHz 晶振。
  • ADC1:开启 IN1 通道,采样时间拉到最长(55.5 周期),开启连续转换模式。
  • I2C1:默认配置,速率 100KHz 即可。
  • GPIO:PB1 输入模式,PA4、PA5 输入模式(上拉),PB10、PB11、PB12、PB13 输出模式(推挽)。
  • USART1:115200-8-N-1,用于调试打印。

注意一个细节:按键用的 PA4 和 PA5 在 F103 上默认是 ADC 引脚,CubeMX 里要先复用成 GPIO 输入才能正常读取。很多人烧了程序发现按键没反应,八成是这里没设置对。

3.2 核心代码逻辑拆解

整体软件用一个简单的状态机来管理,我定义了一个枚举类型:

typedef enum { STATE_NORMAL = 0, STATE_ALERT } SystemState;

主循环里做四件事:读传感器、更新状态、驱动输出、刷新显示。

燃气浓度采集我用的 ADC 轮询读取,每 100ms 读一次,然后软件做中值滤波——连续读 5 次,去掉最大最小值取平均。为什么不用 DMA?因为这个项目对采样率要求不高,100ms 才读一次,轮询完全够用,DMA 反而增加代码复杂度。中值滤波对付 MQ-2 的随机毛刺非常有效,比单纯的平均滤波效果要好,因为 MQ-2 偶尔会出现一个尖峰脉冲,平均值会被尖峰拉高导致误报,中值滤波可以直接把这个尖峰丢弃。

ADC 读取代码大概是这个样子:

uint16_t readGasValue(void) { uint16_t value; HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); value = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return value; }

滤波部分:

uint16_t getFilteredGasValue(void) { uint16_t buf[5]; uint16_t temp; for (int i = 0; i < 5; i++) { buf[i] = readGasValue(); HAL_Delay(10); } // 冒泡排序,取中值 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4 - i; j++) { if (buf[j] > buf[j + 1]) { temp = buf[j]; buf[j] = buf[j + 1]; buf[j + 1] = temp; } } } return buf[2]; }

红外检测的逻辑更直白,直接读 PB1 的电平,但要注意 HC-SR501 模块的特性:人一进入检测范围输出高电平,人离开之后还会保持一段时间的输出延时,这个延时由模块上的旋钮调节,最短可以调到 3 秒左右。如果检测的是“闯入”而不是“有人存在”,建议把延时调到最小,然后软件里用一个 500ms 的消抖:

uint8_t readPirDetected(void) { uint8_t cnt = 0; for (int i = 0; i < 10; i++) { if (HAL_GPIO_ReadPin(PIR_GPIO_Port, PIR_Pin) == GPIO_PIN_SET) { cnt++; } HAL_Delay(50); } return (cnt >= 8) ? 1 : 0; }

这个函数的作用是连续读 10 次,10 次里至少 8 次是高电平才算检测到人,有效过滤瞬时尖峰干扰。

状态机更新逻辑:

void updateSystemState(void) { uint16_t gas = getFilteredGasValue(); uint8_t pir = readPirDetected(); if (state == STATE_NORMAL) { if (gas > alarmThreshold || pir) { state = STATE_ALERT; HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_RESET); } } else { // STATE_ALERT if (gas <= alarmThreshold && !pir) { // 延时确认,防止抖动导致的报警状态来回切换 HAL_Delay(5000); if (gas <= alarmThreshold && !pir) { state = STATE_NORMAL; HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_SET); } } } }

我特别加了 5 秒延时确认再退出报警态,防止传感器数据抖动导致蜂鸣器响一下停一下的奇葩现象。

报警输出部分我单独封装了一个函数,方便扩展:

void setAlertOutputs(uint8_t enable) { GPIO_PinState pinState = enable ? GPIO_PIN_RESET : GPIO_PIN_SET; HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, pinState); HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, pinState); HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, pinState); HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, enable ? GPIO_PIN_SET : GPIO_PIN_RESET); }

注意我这里全是 GPIO_PIN_RESET 才生效,因为前面说了蜂鸣器和继电器都是低电平触发,红色 LED 我接的是低电平点亮方式。每个输出用哪个电平触发,必须跟原理图对应,这是最容易出 bug 的地方。

3.3 OLED 显示与按键处理

OLED 我用的是 SSD1306 标准驱动,网上驱动代码很多,我选了一个支持中文取模的库,这样 OLED 上可以直接显示“燃气浓度”和“系统状态”中文。显示刷新频率不用太高,500ms 刷一次就够了,刷太频 OLED 会有闪烁感,还占用主循环时间。

按键处理用的是带消抖的轮询方式,每 20ms 扫描一次,按下列表:

void scanKeys(void) { if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) { HAL_Delay(20); if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) { alarmThreshold += 50; if (alarmThreshold > 4095) alarmThreshold = 4095; printf("Threshold inc: %d\r\n", alarmThreshold); } } // KEY2 逻辑类似,阈值减 }

阈值用的是 ADC 原始值,0 到 4095 对应 0 到 3.3V 的模拟输入。我没有把 ADC 原始值换算成具体的 ppm(百万分比浓度)气体浓度,原因很简单:MQ-2 这类半导体传感器的输出特性和气体浓度的对应关系非常不平滑,精度有限,强行换算出来的 ppm 数字没有实用意义,反而容易误导人。做产品级燃气报警器必须用催化燃烧式或电化学式传感器,MQ-2 定位就是低成本学习验证。

所以我在 OLED 上显示的是 ADC 原始值和一个百分比进度条,用百分比直观表示当前的浓度相对阈值高了多少,这个信息对日常使用已经足够了。

4. 仿真验证与调试方法

4.1 Proteus 仿真方案

Proteus 仿真是这次开源的一大亮点,因为它能让没有硬件的朋友也能把整个系统跑起来。

Proteus 中搭建仿真工程,关键步骤有三个。

第一,从元件库里找 STM32F103C8T6,新版 Proteus 8.15 及以上内置了这款芯片的仿真模型。放置后双击设置晶振频率为 8MHz,加载编译好的 hex 文件。hex 文件在 Keil 的输出目录下,后缀是 .hex,如果你的 Keil 没有生成 hex,需要在 Options for Target -> Output 里勾选 Create HEX File。

第二,仿真电路里 MQ-2 没有现成模型,用电位器代替。电位器的高端接 3.3V,低端接地,中间抽头接 PA1。万用表测量抽头电压来模拟不同的气体浓度——电位器往高拧就是模拟浓度升高,往低拧就是浓度降低。

第三,HC-SR501 模型同样没有,用一个按钮替代。按钮一端接 3.3V,另一端接 PB1,按下按钮就相当于红外检测到人,松开就相当于没人。

这样一来,Proteus 仿真的逻辑就完整了:电位器调电压模拟燃气浓度变化,按钮按下去模拟人体入侵,OLED 显示浓度数值,LED 和蜂鸣器按状态切换。

这里有个很实用的经验:Proteus 里 STM32 的 ADC 采用的是理想模型,读到的电压值非常稳定,不会像真实 MQ-2 那样有噪声,所以在 Proteus 里要验证中值滤波算法的话,要么在电位器输出端并联一个小正弦信号源,要么直接跳过滤波验证,把重点放在状态机的切换逻辑是否正确上。仿真最大的价值就是验证逻辑,而不是验证模拟特性。

4.2 Wokwi 在线仿真

如果你不想装 Proteus,可以试试 Wokwi,这是一个完全在浏览器里跑的嵌入式仿真平台,支持 STM32F103C8T6 仿真,也支持 OLED 显示模块。它的好处是打开网页就能用,不需要安装任何软件,适合快速验证代码逻辑。

Wokwi 里要注意的是元件库同样没有 MQ-2 模型,解决办法跟 Proteus 一样,用电位器替代,也可以用一个滑动变阻器组件,在线拖动改变输出电压。Wokwi 的 OLED 支持 I2C,用起来比 Proteus 里更顺手,接线也直观。

我个人建议的流程是:先 Wokwi 快速验证核心代码逻辑有没有明显问题,再 Proteus 做详细的外设配合仿真,最后上实物板子。两级仿真可以把大部分逻辑 bug 挡在硬件之外。

4.3 从仿真到实物迁移的坑

仿真跑通之后,移植到实物板子通常还会遇到几个常见的差异,这里提前打个预防针。

仿真里 ADC 数值稳定,实物上 MQ-2 的电压会有 ±30 甚至更大的波动,所以中值滤波一定要留好,而且 MQ-2 上电前 3 分钟数据不能直接用,需要预热。我代码里做了一个简单处理:上电后 OLED 显示“预热中”,主循环里丢弃前 200 次采样结果,只做显示不判断报警,这样用户不会因为预热期的异常高值而疯狂误报。

仿真里 HC-SR501 的按钮是按一下就高电平,松开就低电平,实物上 HC-SR501 高电平会持续一段时间。如果模块的延时旋钮拧到最大,高电平能持续好几分钟,这在设计报警逻辑时要特别留意。我用 10 次连续采样、8 次以上高电平才判定有人的算法,就是为了兼容这种延时特性。

仿真里 OLED 的 I2C 速度随便跑,实物上如果杜邦线过长,I2C 信号容易受干扰,解决办法是降低 I2C 速率到 50KHz 或者把杜邦线剪短控制在 10cm 以内。

5. 常见问题与避坑实录

5.1 烧录、下载与启动问题

这个项目在开发过程中遇到过三个高频问题,每个都值得单独拿出来说,因为实在是太常踩了。

第一个,Keil 能编译但下载失败。绝大多数是因为 BOOT0 没有接地。STM32F103 的 BOOT0 拉高会进入系统存储器启动模式,这时候程序不是从 Flash 启动的,烧录虽然能成功但你看到的程序跑不起来。解决办法很简单,检查 BOOT0 引脚是否接近地,如果是跳线帽方式就确保跳线帽在 0 档。

第二个,下载工具选择问题。我用的是 ST-Link V2,在 Keil 里选择 ST-Link Debugger 后需要设置 Flash Download 里的 Reset and Run 选项,否则程序下载后不会自动运行,要手动按一下复位键才跑起来。很多新手说“下载成功后板子没反应”,十有八九是卡在这里。

第三个,ADC 读到 0 或者最大值。这种情况检查两个地方,一是 MQ-2 模块上电后加热丝有没有发热,没有发热说明 5V 没到位;二是 PA1 有没有被 CubeMX 配置成别的复用功能,有时候芯片默认的 JTAG 引脚和你要用的引脚冲突引起配置异常。我特意避开了 PA13、PA14、PA15 和 PB3、PB4 这些默认调试引脚,把它们留给调试器,顺带也避免下载后程序被调试功能锁死的风险。

5.2 传感器数据异常排查

MQ-2 的读数如果不正常,按这个顺序排查:先测模块供电,再测输出引脚电压,然后看 ADC 配置,最后检查共地。MQ-2 模块的模拟输出和 STM32 必须共地,否则读到的电压完全随机。模块如果没共地,ADC 值会从 4095 到 0 之间乱跳。

HC-SR501 的误触发是个老大难。我试过在室内灯光附近放置,晚上开灯时它就开始抽风报警。排查到最后发现是模块灵敏度调节旋钮拧太高了,把检测距离调近到 3 米左右,误触发概率大幅下降。另外红外传感器安装时不要正对窗户、空调出风口这些温度变化剧烈的地方,否则热气流扰动都会被识别成人。

OLED 不显示,优先查 I2C 地址。市面上 SSD1306 模块的 I2C 地址有两个可能:0x3C 或者 0x3D。我改用了一个自动地址扫描的初始化函数,上电后自动探测是哪个地址,实测能解决一半的 OLED 问题。另一半是供电不足,OLED 的 I2C 总线如果被 MQ-2 加热丝瞬间拉低电压,屏幕会闪或者直接不亮,处理办法还是前面说的电源分离。

5.3 误报、漏报与阈值设置

报警阈值的设定直接影响使用体验。阈值太低,家里烧个菜油烟大一点就疯狂报警;阈值太高,真漏气了又报警不灵。

我实测下来的经验是:先把 MQ-2 在正常空气环境中预热 5 分钟,记录一个稳定基线值,比如 500 左右。然后阈值设定为基线的 2 到 3 倍,也就是 1000 到 1500 这个区间。开发板默认阈值我写的是 1200,用户可以通过按键在 700 到 3000 之间调整。

还有一个细节:燃气报警器一般有“第一次报警锁定”的设计,意思是浓度超过阈值触发报警后,即使浓度降下来了也要手动复位,防止用户在外出时家里燃气泄漏,报警器响了一会儿浓度下降就自己停了,人回家后根本不知道发生过泄漏。我的代码里做了一个软开关,默认启用锁定逻辑——要退出报警状态,要么浓度降到阈值以下同时按住某个键 3 秒,要么断电重启。这个设计在产品逻辑上是重要的安全兜底,仿真和实物我都验证过。

红外报警的策反逻辑则相反,我在报警锁定的同时,红外触发一次只报警一小段时间,比如 10 秒后自动恢复正常监控,这样家里人来回走动不至于让报警器一直叫。两类报警的恢复策略不同,这是我从实际使用场景里抠出来的细节。

6. 开源工程应包含的全部内容

6.1 代码工程目录组织

开源工程直接打包在 GitHub 仓库里,整个目录结构我花了不少心思,因为我知道一个开源项目能不能被别人顺利跑起来,目录清不清楚占了很大因素。

工程目录组织如下:

STM32-Smart-Security-Gas/ ├── Hardware/ │ ├── Schematic/ # 原理图源文件(立创EDA可编辑) │ ├── PCB/ # PCB源文件 │ └── Datasheets/ # 关键器件数据手册 ├── Software/ │ ├── Core/ # 启动文件、系统主文件 │ ├── Drivers/ # HAL库驱动 │ ├── App/ # 业务逻辑代码(状态机、传感器、显示) │ └── MDK-ARM/ # Keil工程文件 ├── Simulation/ │ ├── Proteus/ # Proteus仿真工程 │ └── Wokwi/ # Wokwi在线仿真配置 ├── Docs/ │ ├── README.md # 项目说明、接线表、操作指南 │ └── BOM.md # 物料清单 └── LICENSE # MIT开源协议

代码按照 App、Drivers、Core 分层组织,业务逻辑集中在 App 目录下,这样别人拿到的第一眼就知道哪些代码是需要关注的核心逻辑,哪些是库文件不用动。

6.2 文档与 BOM 清单

BOM 表的整理对复现太关键了。我把所有器件列成清单,包含型号、封装、数量、参考购买链接和大概价格。整机物料成本我算过,不包含打板和 ST-Link 的话,大概 35 到 50 元人民币,核心器件就那几样,价格都很便宜。

器件型号/规格数量参考价(元)
MCUSTM32F103C8T618
燃气传感器MQ-2模块18
红外人体传感器HC-SR50115
OLED显示屏0.96寸 I2C SSD1306112
有源蜂鸣器低电平触发模块12
继电器模块5V单路低电平触发15
LED红色/绿色 0805各241
按键6x6x5轻触21
稳压芯片AMS1117-3.311
晶振8MHz 无源10.5
电阻电容0805 若干若干2
排针排母若干若干3

README 里我写了完整的接线对照表、开发环境搭建步骤、从零到下载固件的全流程,以及常见问题索引。开源项目最常见的死法不是代码有问题,而是文档不够直观,别人拿过去第一步接线就接错了,后面全白搭。

6.3 让开源项目更容易被复现的细节

最后分享几个让开源项目真正“能复现”的经验,也是我做这个仓库时反复打磨的地方。

第一,固件下载方式要给两种。除了用 ST-Link 下载,我额外做了一个串口下载的说明,因为很多初学者手头只有 USB 转 TTL 模块,没有 ST-Link。STM32F103 支持串口 ISP 下载,把 BOOT0 拉高、BOOT1 拉低,用 FlyMcu 软件就能通过串口烧录,这一步操作引导写清楚了,项目受众一下子大很多。

第二,原理图要给可编辑源文件而不是只给 PDF。我用立创 EDA 画的工程直接导出了源文件压缩包,别人拿到后可以直接在线打开、改线路、生成自己的版本。仅仅放一个 PDF 原理图,表面上看起来规范,实际上把动手改板的路堵死了,开源的意义少了一半。

第三,仿真工程要和实际代码一一对应。Proteus 仿真工程里的引脚连接、传感器替代模型、阈值初始值,都必须跟实物的默认状态一致,否则会出现“仿真能跑动、实物跑不动”的经典翻车。我在发布前特意做了一次从仓库克隆到仿真运行再到实物的全流程测试,确保新手照着仓库里的步骤走能顺利跑通。

这个项目我后续还在考虑给它加一个 WiFi 远程报警模块,用 ESP8266 把报警信息推送到手机,不过那就要再加一版硬件,得等有余力再折腾了。如果你照着做出来,遇到任何问题都可以给我留言或者直接提 issue,我一般在几天内会回复。把代码调通的那一刻,你会觉得前面烧掉的那些时间和元件,全都值了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询