目录
[六、实验效果 编辑](#六、实验效果 编辑)
一、前言
项目成品图片:

哔哩哔哩视频链接:
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的空气质量检测(机智云)系统
功能如下:
- STM32F103C8T6单片机作为主控芯片
- DHT11温湿度传感器检测空气温湿度信息
- MQ-7一氧化碳传感器检测一氧化碳含量
- 三合一VOC传感器检测甲醛浓度
- PM2.5传感器检测粉尘含量
- OLED显示屏实时显示温湿度、一氧化碳、甲醛和PM2.5信息
- 空气质量异常触发声光报警并开启风扇通风
- 按键可调节阈值范围
- WIFI连接机智云APP可远程查看空气质量信息数据
- 通过机智云连接手机APP,APP可查看环境信息数据和控制指令下发
2.主要器件
- STM32F103C8T6单片机
- OLED 屏幕
- DHT11温湿度传感器
- ESP8266(WIFI)模块
- 三合一VOC气体传感器
- PM2.5粉尘传感器
- MQ-7一氧化碳传感器
- 继电器
- 风扇模块
- 有源蜂鸣器
- LED灯
三、原理图设计

四、PCB硬件设计
PCB图


五、程序设计
cpp
#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "usart.h"
#include "delay.h"
#include "dht11.h"
#include "oled.h"
#include "key.h"
#include "Modules.h"
#include "TIM2.h"
#include "usart2.h"
#include "adcx.h"
#include "flash.h"
#include "fan.h"
#include "mq7.h"
#include "PM25.h"
#include "string.h"
#include "TIM3.h"
#include "gizwits_product.h"
#include "gizwits_protocol.h"
/****************异方辰电子工作室******************
STM32
* 项目 : STM32空气质量检测系统(机智云版)
* 版本 : V3.0
* 日期 : 2026.4.11
* MCU : STM32F103C8T6
* 接口 : 见代码
* IP账号 : 异方辰电子/辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
* 作者 : 辰哥
* 工作室 : 异方辰电子工作室
* 授权IP : 辰哥单片机设计、异方辰电子、YFC电子、异方辰系列
* 官方网站 : www.yfcdz.cn
**********************BEGIN***********************/
#define KEY_Long1 11
#define KEY_1 1
#define KEY_2 2
#define KEY_3 3
#define KEY_4 4
#define FLASH_START_ADDR 0x0801f000 //写入的起始地址
extern SensorModules sensorData;
extern SensorThresholdValue Sensorthreshold;
extern DriveModules driveData;
uint8_t mode = 1; //系统模式 1自动 2手动 3设置
u8 dakai;//串口3使用的传递变量
u8 Flag_dakai;//串口3接收标志位
extern uint8_t uart2_sendtime;
//系统静态变量
static uint8_t count_a = 1; //自动模式按键数
uint8_t count_m = 1; //手动模式按键数
static uint8_t count_s = 1; //设置模式按键数
uint8_t last_mode = 0;
int main(void)
{
SystemInit();
delay_init(72);
ADCx_Init();
LED_Init();
LED_On();
Key_Init();
FAN_Init();
OLED_Init();
DHT11_Init();
PM25_Init();
MQ7_Init();
BEEP_Init();
OLED_Clear();
USART1_Config();
USART2_Config();
USART3_Config();
TIM2_Init(72-1,1000-1);
TIM3_Int_Init(1000-1,72-1);
printf("Start \n");
// 读取阈值
Sensorthreshold.tempValue = FLASH_R(FLASH_START_ADDR);
Sensorthreshold.humiValue = FLASH_R(FLASH_START_ADDR + 2);
Sensorthreshold.COValue = FLASH_R(FLASH_START_ADDR + 4);
uint16_t ch2o_low = FLASH_R(FLASH_START_ADDR + 6);
uint16_t ch2o_high = FLASH_R(FLASH_START_ADDR + 8);
uint32_t ch2o_raw = ((uint32_t)ch2o_high << 16) | ch2o_low;
Sensorthreshold.CH2OValue = *(float*)&ch2o_raw;
Sensorthreshold.PM25Value = FLASH_R(FLASH_START_ADDR + 10);
// 默认值修正
if (Sensorthreshold.tempValue < 1 || Sensorthreshold.tempValue > 50)
Sensorthreshold.tempValue = 35;
if (Sensorthreshold.humiValue < 1 || Sensorthreshold.humiValue > 100)
Sensorthreshold.humiValue = 80;
if (Sensorthreshold.COValue < 100 || Sensorthreshold.COValue > 1000)
Sensorthreshold.COValue = 500;
if (Sensorthreshold.CH2OValue < 0.01f || Sensorthreshold.CH2OValue > 0.5f)
Sensorthreshold.CH2OValue = 0.25f;
if (Sensorthreshold.PM25Value < 10 || Sensorthreshold.PM25Value > 200)
Sensorthreshold.PM25Value = 100;
delay_ms(1000);
OLED_Clear();
userInit(); // 机智云用户初始化(数据点初始化等)
gizwitsInit(); // 机智云协议初始化(WiFi配网、数据通信初始化)
gizwitsSetMode(WIFI_AIRLINK_MODE); //默认一键配网
delay_ms(200);
printf("Start \n");
gizwitsHandle((dataPoint_t *)¤tDataPoint);
ScanGizwitsMode();
delay_ms(200);
while (1)
{
gizwitsHandle((dataPoint_t *)¤tDataPoint);
SensorScan(); //获取传感器数据
switch(mode)
{
case AUTO_MODE:
{
if(SetAuto() ==1 )
{
OLED_autoPage1(); //显示主页面1固定信息
SensorDataDisplay1(); //显示传感器1数据
}
AutoControl();
/*按键1按下时切换模式*/
if (KeyNum == KEY_1) //系统模式mode 1自动 2手动 3设置
{
KeyNum = 0;
mode = MANUAL_MODE;
count_m = 1;
driveData.BJ_Flag = 0;
driveData.Fan_Flag = 0;
OLED_Clear();
}
if (KeyNum == KEY_Long1)
{
KeyNum = 0;
mode = SETTINGS_MODE;
count_s = 1;
driveData.BJ_Flag = 0;
driveData.Fan_Flag = 0;
OLED_Clear();
}
Control_Manager();
break;
}
case MANUAL_MODE:
{
OLED_manualOption(SetManual());
ManualControl(SetManual());
OLED_manualPage1();
ManualSettingsDisplay1();
Control_Manager();
if (KeyNum == KEY_1) //系统模式mode 0手动 1自动(默认)
{
KeyNum = 0;
mode = AUTO_MODE;
count_a = 1;
driveData.BJ_Flag = 0;
driveData.Fan_Flag = 0;
OLED_Clear();
}
}
break;
case SETTINGS_MODE:
{
OLED_settingsOption(SetSelection()); //实现阈值设置页面的选择功能
ThresholdSettings(SetSelection()); //实现阈值调节功能
if (SetSelection() <= 4)
{
OLED_settingsPage1(); //显示阈值设置界面1固定信息
SettingsThresholdDisplay1(); //显示传感器阈值1数据
}
else //否则显示设置页面2
{
OLED_settingsPage2(); //显示阈值设置界面2固定信息
SettingsThresholdDisplay2(); //显示传感器阈值2数据
}
//判断是否退出阈值设置界面
if (KeyNum == KEY_1)
{
KeyNum = 0;
mode = AUTO_MODE; //跳转到主界面
count_a = 1;
OLED_Clear(); //清屏
// 将 float CH2OValue 拆成两个 u16
uint32_t ch2o_raw = *(uint32_t*)&Sensorthreshold.CH2OValue;
uint16_t ch2o_low = (uint16_t)(ch2o_raw & 0xFFFF);
uint16_t ch2o_high = (uint16_t)((ch2o_raw >> 16) & 0xFFFF);
// 写入 Flash(注意顺序:低16位在前,高16位在后)
FLASH_W(FLASH_START_ADDR,
Sensorthreshold.tempValue,
Sensorthreshold.humiValue,
Sensorthreshold.COValue,
ch2o_low, // 存到 add+6
ch2o_high, // 存到 add+8
Sensorthreshold.PM25Value); // 存到 add+10
}
break;
default: break;
}
}
userHandle();
}
}
六、实验效果 
七、包含内容
