12 基于STM32单片机的空气质量监测系统设计(STM32代码编写+手机APP+PCB设计+Proteus仿真)

系列文章目录



前言

本文设计出一款基于STM32单片机的空气质量监测系统。
主要功能如下:

1、STM32F103C8T6单片机作为主控制器。

2、DHT11温湿度传感器采集温湿度

3、监测一氧化碳浓度;监测甲醛浓度;监测PM2.5浓度;

4、阈值可以调节,超出阈值报警

5、温度超出阈值,打开风扇调温

6、OLED实时显示当前信息

7、通过ESP8266连接机智云APP,实现单片机-手机APP交互。


1 资料获取与演示视频

1.1 资料介绍

在这里插入图片描述

1.2 资料获取

完整资料获得链接:
咸鱼:【胜磊电子】基于STM32单片机的空气质量监测系统设计(STM32代码编写+手机APP+PCB设计+Proteus仿真)

淘宝:【胜磊电子】基于STM32单片机的空气质量监测系统设计(STM32代码编写+手机APP+PCB设计+Proteus仿真)

1.3 演示视频

哔哩哔哩:【胜磊电子】基于STM32单片机的空气质量监测系统设计(STM32代码编写+手机APP+PCB设计+Proteus仿真)


2 系统框架

2.1 系统框架

在这里插入图片描述

2.2 单片机整体框图

在这里插入图片描述


3 硬件

3.1 主控制器

主控制器选择STM32F103C8T6,在淘宝上买的,如下图所示:
在这里插入图片描述
STM32F103C8T6 是意法半导体(ST)推出的一款基于 ARM Cortex-M3 内核的 32 位微控制器,以下从其性能参数、功能特性、应用领域等方面进行介绍:

  1. 主频
    最高可达 72MHz,具备 1.25DMIPS/MHz 的运算能力,能够快速处理各种指令和任务。
    内核处理器:采用 ARM Cortex-M3 内核,具有高性能、低功耗的特点,支持 Thumb-2 指令集,能够高效地执行各种指令。

  2. 存储
    拥有 64KB 的 Flash 存储器,用于存储程序代码和常量数据;20KB 的 SRAM,用于存储运行时的变量和临时数据。

  3. 丰富的外设接口
    USART:集成了 3 个 USART(通用同步异步收发器)接口
    SPI:2 个 SPI(串行外设接口)接口
    I2C:2 个 I2C(Inter-Integrated Circuit)接口
    USB: 1 个 USB 2.0 全速接口
    定时器:包含 7 个定时器,其中包括 4 路 PWM 输出,可用于脉冲宽度调制、输入捕获、输出比较、正交编码器接口等功能,广泛应用于电机控制、脉冲信号生成等领域。
    ADC(模数转换器):内置 2 个 12 位 ADC,转换时间仅为 1μs,具有 10 个通道,可对多路模拟信号进行快速采样转换,适用于各种需要采集模拟信号的场景,如传感器数据采集等。

  4. 时钟系统
    内置 4-16MHz 的高速内部时钟(HSI)和 32KHz 的低速内部时钟(LSI),也可通过外部晶振提供更高精度的时钟源,通常包括一个 8MHz 的高速外部时钟(HSE)和一个 32.768KHz 的低速外部时钟(LSE),为芯片内部各个模块提供精确的时钟信号,确保它们能够同步工作。

  5. 其他功能
    集成了看门狗定时器、CRC 计算单元、RTC 实时时钟、SysTick 定时器、DMA(Direct Memory Access)控制器等,进一步增强了芯片的功能和可靠性。支持 JTAG(Joint Test Action Group)和 SWD(Single Wire Debug)调试接口,方便开发人员连接调试器进行程序调试和下载,提高开发效率。

3.2 显示屏

使用1.8寸显示屏,分辨率128*160。如图,
在这里插入图片描述
1.8寸彩屏,支持16BIT RGB 65K彩色显示,显示色彩丰富

128X160分辨率,显示清晰

采用SPI串行总线,只需几个IO即可点亮显示

带SD卡槽方便功能扩展

军工级工艺标准,长期稳定工作

3.3 WIFI模块

WIFI模块使用ESP8266,如图,

在这里插入图片描述
ESP01S 是一款基于乐鑫 ESP8266EX 芯片的低成本、低功耗 Wi-Fi 模块,专为物联网(IoT)和嵌入式系统设计。
以下是其详细介绍:

  1. 核心架构与性能
    处理器:采用 32 位 Tensilica L106 RISC 处理器,主频支持 80MHz 或 160MHz,集成 TCP/IP 协议栈,可直接运行用户程序。
    内存配置:
    闪存(Flash):提供 1MB 或 4MB 两种版本(具体型号差异),用于存储固件和用户代码。
    RAM:64KB,支持程序运行和数据缓存。
    通信协议:支持 802.11b/g/n 标准,数据传输速率最高 4Mbps,覆盖 2.4GHz 频段,支持 STA、AP、STA+AP 三种工作模式。

  2. 硬件资源与接口
    引脚定义:
    供电:3.0V~3.6V(推荐 3.3V),传输电流 170mA,接收电流 56mA。
    通信:UART 接口(TXD/RXD),支持 AT 指令交互,波特率默认 115200bps。
    GPIO:提供 2 个可编程引脚(GPIO0、GPIO2),可用于控制外设(如 LED、继电器)或传感器输入。
    其他:CH_PD(使能引脚,高电平有效)、RST(复位引脚)。
    扩展能力:
    PWM:部分引脚支持 PWM 输出,用于电机调速或灯光控制。
    I²C/SPI:需通过外部扩展芯片(如 PCF8574、MCP23017)实现。

  3. 低功耗特性
    工作模式:
    活跃模式:传输时电流约 170mA,接收时 56mA。
    睡眠模式:
    轻睡眠:电流约 10mA,保留网络连接。
    深度睡眠:电流低至 20μA,适用于电池供电设备。
    唤醒方式:支持定时唤醒、GPIO 触发唤醒或 UART 数据唤醒。

  4. 应用场景
    智能家居:通过 Wi-Fi 连接控制灯光、空调、门锁等设备。
    环境监测:采集温湿度、空气质量等数据并上传至云端。
    工业自动化:远程监控设备状态,实现无线数据传输。
    智能农业:监测土壤湿度、光照等参数,优化种植管理。

3.4 DHT11温湿度传感器

在这里插入图片描述
使用DHT11模块检测环境的温度和湿度。

DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC测温元件,并与一个高性能 8 位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。
DHT11 的技术参数如下:
⚫ 工作电压范围:3.3V-5.5V
⚫ 工作电流 :平均 0.5mA
⚫ 输出:单总线数字信号
⚫ 测量范围:湿度 20~90%RH,温度 0~50℃
⚫ 精度 :湿度±5%,温度±2℃
⚫ 分辨率 :湿度 1%,温度 1℃

DHT11 数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由 5Byte(40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。DHT11 的数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数
数据+8bit 温度小数数据+8bit 校验和。其中校验和数据为前四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。例如,某次从 DHT11 读到的数据如图所示:
在这里插入图片描述
由以上数据就可得到湿度和温度的值,计算方法:
湿度= byte4 . byte3=45.0 (%RH)
温度= byte2 . byte1=28.0 ( ℃)
校验= byte4+ byte3+ byte2+ byte1=73(=湿度+温度)(校验正确)
可以看出,DHT11 的数据格式是十分简单的,DHT11 和 MCU 的一次通信最大为 3ms 左右,
建议主机连续读取时间间隔不要小于 100ms。
在这里插入图片描述
首先主机发送开始信号,即:拉低数据线,保持 t1(至少 18ms)时间,然后拉高数据线 t2(20~40us)时间,然后读取 DHT11 的响应,正常的话,DHT11 会拉低数据线,保持 t3(40~50us)时间,作为响应信号,然后 DHT11 拉高数据线,保持 t4(40~50us)时间后,开始输出数据。
DHT11 输出数字‘0’的时序如图所示:
在这里插入图片描述
DHT11 输出数字‘1’的时序如图所示:
在这里插入图片描述
通过以上了解,我们就可以通过 STM32 来实现对 DHT11 的读取了。

3.5 一氧化碳传感器

在这里插入图片描述

  1. 工作原理
    MQ-7 传感器采用二氧化锡(SnO₂)半导体气敏材料,属于表面离子式 N 型半导体。在 200-300℃时,二氧化锡表面吸附空气中的氧,形成氧的负离子吸附,使半导体中的电子密度减少,电阻值增加。当与一氧化碳气体接触时,晶粒间界处的势垒发生变化,引起表面导电率的变化,一氧化碳浓度越大导电率越大,输出电阻越低,输出的模拟信号就越大。

  2. 主要参数
    工作电压:DC 5V。
    工作电流:150mA。
    检测气体:主要检测一氧化碳,也能检测天然气、甲烷等。
    检测浓度范围:一般为 10-10000ppm。
    输出类型:具有 AO 模拟信号输出和 DO 开关信号输出。DO 输出为 TTL 数字量 0 和 1(0.1V 和 5V),AO 输出在相对无污染时为 0.1-0.3V,高浓度时电压约 4V。

  3. 模块特点
    高灵敏度:能够检测低至 10ppm 的 CO 浓度。
    快速响应:可在几秒钟内响应气体浓度的变化。
    长寿命:可在多种环境条件下稳定工作,使用寿命长。
    低成本:相对其他类型的气体传感器,成本较低。
    易集成:输出为模拟信号,可通过 ADC 转换为数字信号,与微控制器系统容易集成。

  4. 典型应用
    家庭安全:用于家庭用气体泄漏报警器,检测室内一氧化碳浓度,防止中毒。
    工业安全:适用于工业用可燃气体报警器,监测工厂等场所的一氧化碳含量。
    便携式检测:可作为便携式一氧化碳气体检测器的核心部件,用于现场检测。

3.6 甲醛传感器

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.7 PM2.5传感器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


4 设计PCB

直接使用上述模块,线路非常杂乱,因此,我们需要自己设计一块PCB底板。开发工具使用立创EDA。

相关资料已经放在本文第一节。

4.1 安装下载立创EDA专业版

4.2 画原理图

4.3 摆放元器件,设计规则,泪滴,铺铜。

在这里插入图片描述

4.4 使用嘉立创下单助手进行下单,打板。

4.5 实物图

实物如图:
在这里插入图片描述


5 软件设计

5.1 编写STM32单片机代码

工程目录如图所示:
在这里插入图片描述

5.1.1 main.c

#include "board_config.h"

#include "module_config.h"

#include "lcd_app.h"

#include "sensor_app.h"

//网络协议层
#include "gizwits_product.h"

/************************************************
 串口驱动
 实验现象:LED1闪烁,按下按键,串口打印按键信息。
 
 淘宝店铺:https://shop475501589.taobao.com/?spm=pc_detail.29232929/evo365560b447259.shop_block.dshopinfo.5dd97dd6JvMuG3
 咸鱼店铺:https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.c17a3da6hy8k28&userId=3890583014
 哔哩哔哩:https://space.bilibili.com/482024430?spm_id_from=333.788.upinfo.detail.click
 作者:胜磊电子
************************************************/

/************************************* 宏定义 *******************************************************/


/*********************************** 局部函数 *******************************************************/
// 定时器3,定时1ms
void TIMER3_Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
    
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
	//初始化
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
    // 72MHz
	TIM_TimeBaseInitStruct.TIM_Period=10-1;
	TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM3, TIM_IT_Update);
	
	TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);

	
	NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);

	
	TIM_Cmd(TIM3,ENABLE);
}

//机智云初始化
void MyGizwistInit(void)
{
	TIMER3_Init();//1ms
//	Uart2_Init(9600);//gizPutData((uint8_t *)&aRxBuffer,1);
	userInit();//用户信息初始化,目前只是把结构体信息复位
	gizwitsInit();//机智云的初始化
}

/*
************************************************************
*	函数名称:	main
*
*	函数功能:	
*
*	入口参数:	无
*
*	返回参数:	0
*
*	说明:
************************************************************
*/
int main(void)
{
	unsigned short timeCount = 0;	//发送间隔变量
	
	// 初始化所有外设
    BOARD_InitAll();
	
	// 初始化模块
	MODULE_InitAll();

	//APP初始化
	MyGizwistInit();
    
	gizwitsSetMode(WIFI_AIRLINK_MODE);
	DelayMs(2000);
	
/* 1、显示不变量 */
	LCD_Display_Init();
	
    while (1) {
/* 2、系统轮询 */			
		LCD_StatusPOLL();
		
		// MQTT 数据发送
		if(++timeCount >= 200)									//发送间隔5s
		{
/* 3、得到传感器数据 */	
			Sensor_GetValueAll();
			
			timeCount = 0;
			
			// 闪烁LED1
			LED_Toggle(&BOARD_LED2);
		}

/* 4、更新传感器数据 */			
		LCD_Refresh_Data();

/* 5、报警检测 */
		Sensor_AlarmDetection();
		
/* 6、APP */
		userHandle();										// 数据上行
        gizwitsHandle((dataPoint_t *)&currentDataPoint);	// 将报文,发送到APP
		
        DelayMs(10);
    }
}

5.1.2 board_config.c

#include "board_config.h"

/************************************************
 淘宝店铺:https://shop475501589.taobao.com/?spm=pc_detail.29232929/evo365560b447259.shop_block.dshopinfo.5dd97dd6JvMuG3
 咸鱼店铺:https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.c17a3da6hy8k28&userId=3890583014
 哔哩哔哩:https://space.bilibili.com/482024430?spm_id_from=333.788.upinfo.detail.click
 作者:胜磊电子
************************************************/

/**
 * @file    board_config.c
 * @brief   开发板外设配置与初始化
 * @details 本文件实现了开发板上所有外设的配置与初始化函数,
 *          包括LED、蜂鸣器、按键、SPI、USART等模块的初始化。
 */

/************************************* 变量定义 *******************************************************/

/** 
 * @brief 开发板LED对象定义
 * @details 定义了开发板上三个LED的控制结构体
 */
LED_TypeDef BOARD_LED1; /**< 开发板LED1对象 (PB0) */
LED_TypeDef BOARD_LED2; /**< 开发板LED2对象 (PB1) */


/** 
 * @brief 开发板蜂鸣器对象定义
 * @details 定义了开发板上蜂鸣器的控制结构体
 */
Beep_TypeDef BOARD_BEEP; /**< 开发板蜂鸣器对象 (PB8) */

/** 
 * @brief SPI2接口配置结构体
 * @details 配置SPI2接口的参数,包括GPIO引脚、通信模式、时钟参数等
 */
SPI_ConfigTypeDef BOARD_SPI2 = {
    // 配置SPI接口
    .SPIx = SPI2,                 /**< SPI外设选择:SPI2 */
    .GPIOx = GPIOB,               /**< SPI2使用的GPIO端口:GPIOB */
    .SCK_Pin = GPIO_Pin_13,       /**< SCK引脚:PB13 */
    .MISO_Pin = GPIO_Pin_14,      /**< MISO引脚:PB14 */
    .MOSI_Pin = GPIO_Pin_15,      /**< MOSI引脚:PB15 */
    .RCC_APBxPeriph_SPI = RCC_APB1Periph_SPI2,  /**< SPI2时钟使能:APB1总线 */
    .RCC_APBxPeriph_GPIO = RCC_APB2Periph_GPIOB, /**< GPIO时钟使能:APB2总线 */
    
    // 配置SPI初始化结构体
    .SPI_InitStruct = {
        .SPI_Direction = SPI_Direction_2Lines_FullDuplex, /**< 双线全双工模式 */
        .SPI_Mode = SPI_Mode_Master,                      /**< 主模式 */
        .SPI_DataSize = SPI_DataSize_8b,                  /**< 8位数据格式 */
        .SPI_CPOL = SPI_CPOL_Low,                         /**< 时钟极性:空闲低电平 */
        .SPI_CPHA = SPI_CPHA_1Edge,                       /**< 时钟相位:第一个边沿采样 */
        .SPI_NSS = SPI_NSS_Soft,                          /**< 软件片选控制 */
        .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, /**< 波特率预分频:2分频 */
        .SPI_FirstBit = SPI_FirstBit_MSB,                 /**< 高位先行 */
        .SPI_CRCPolynomial = 7                            /**< CRC多项式:7 */
    }
};

/** 
 * @brief 开发板按键配置数组
 * @details 定义了开发板上4个按键的配置参数,包括GPIO、中断设置等
 */
Key_InitTypeDef BOARD_KEYS[] = {
    {
        RCC_APB2Periph_GPIOA,     /**< GPIO时钟使能:GPIOA */
        GPIOA,                    /**< GPIO端口:GPIOA */
        GPIO_Pin_0,               /**< 引脚:PA0 */
        GPIO_PortSourceGPIOA,     /**< 端口源:GPIOA */
        GPIO_PinSource0,          /**< 引脚源:Pin0 */
        EXTI_Line0,               /**< 外部中断线:Line0 */
        EXTI0_IRQn,               /**< 中断号:EXTI0_IRQn */
        2,                        /**< 抢占优先级:2 */
        1,                        /**< 子优先级:1 */
        EXTI_Trigger_Rising,      /**< 触发方式:上升沿触发 */
        GPIO_Mode_IPD             /**< GPIO模式:下拉输入 */
    },
    {
        RCC_APB2Periph_GPIOC,     /**< GPIO时钟使能:GPIOC */
        GPIOC,                    /**< GPIO端口:GPIOC */
        GPIO_Pin_13,               /**< 引脚:PC5 */
        GPIO_PortSourceGPIOC,     /**< 端口源:GPIOC */
        GPIO_PinSource13,          /**< 引脚源:Pin5 */
        EXTI_Line13,               /**< 外部中断线:Line5 */
        EXTI15_10_IRQn,             /**< 中断号:EXTI9_5_IRQn */
        2,                        /**< 抢占优先级:2 */
        2,                        /**< 子优先级:2 */
        EXTI_Trigger_Falling,     /**< 触发方式:下降沿触发 */
        GPIO_Mode_IPU             /**< GPIO模式:上拉输入 */
    },
    {
        RCC_APB2Periph_GPIOC,     /**< GPIO时钟使能:GPIOC */
        GPIOC,                    /**< GPIO端口:GPIOC */
        GPIO_Pin_14,               /**< 引脚:PC6 */
        GPIO_PortSourceGPIOC,     /**< 端口源:GPIOC */
        GPIO_PinSource14,          /**< 引脚源:Pin6 */
        EXTI_Line14,               /**< 外部中断线:Line6 */
        EXTI15_10_IRQn,             /**< 中断号:EXTI9_5_IRQn */
        2,                        /**< 抢占优先级:2 */
        2,                        /**< 子优先级:2 */
        EXTI_Trigger_Falling,     /**< 触发方式:下降沿触发 */
        GPIO_Mode_IPU             /**< GPIO模式:上拉输入 */
    },
    {
        RCC_APB2Periph_GPIOC,     /**< GPIO时钟使能:GPIOC */
        GPIOC,                    /**< GPIO端口:GPIOC */
        GPIO_Pin_15,               /**< 引脚:PC7 */
        GPIO_PortSourceGPIOC,     /**< 端口源:GPIOC */
        GPIO_PinSource15,          /**< 引脚源:Pin7 */
        EXTI_Line15,               /**< 外部中断线:Line7 */
        EXTI15_10_IRQn,             /**< 中断号:EXTI9_5_IRQn */
        2,                        /**< 抢占优先级:2 */
        2,                        /**< 子优先级:2 */
        EXTI_Trigger_Falling,     /**< 触发方式:下降沿触发 */
        GPIO_Mode_IPU             /**< GPIO模式:上拉输入 */
    }
};

/** 
 * @brief 按键数量常量
 * @details 计算并存储按键配置数组的元素个数
 */
const uint8_t BOARD_KEYS_NUM = sizeof(BOARD_KEYS) / sizeof(BOARD_KEYS[0]);

ADC_ConfigTypeDef adc_config = {
	.GPIOx = GPIOA,
	.GPIO_Clock = RCC_APB2Periph_GPIOA,
	.GPIO_Pins = GPIO_Pin_4,
	.Channel_Num = 1,
	.Channels = {ADC_Channel_4},
	.ADCx = ADC1,
	.ADC_Clock = RCC_APB2Periph_ADC1,
	.ADC_Prescaler = RCC_PCLK2_Div6  // 72MHz/6=12MHz
};

/************************************* 局部初始化函数 *******************************************************/

/**
 * @brief 初始化开发板LED
 * @details 配置开发板上LED的GPIO引脚,使其可以被控制
 * @return 无
 */
static void BOARD_InitLEDs(void) {
    // 初始化LED1 (PB0)
    LED_Init(&BOARD_LED1, GPIOB, GPIO_Pin_0);
    
    // 初始化LED2 (PB1)
    LED_Init(&BOARD_LED2, GPIOB, GPIO_Pin_1);
}

/**
 * @brief 初始化开发板蜂鸣器
 * @details 配置开发板上蜂鸣器的GPIO引脚,使其可以被控制
 * @return 无
 */
static void BOARD_InitBeep(void) {
    // 初始化蜂鸣器 (PB8)
    Beep_Init(&BOARD_BEEP, GPIOB, GPIO_Pin_8);
}

/**
 * @brief 初始化延时模块
 * @details 配置系统延时功能,选择指定的定时器作为延时基准
 * @param timer 选择的定时器编号 (如1代表TIM2)
 * @return 无
 */
static void BOARD_InitDelay(uint8_t timer) {
    // 初始化延时模块,选择TIM2作为定时器
    Delay_Init(timer);
}

/**
 * @brief 初始化开发板USART
 * @details 配置开发板上的USART1和USART2串口,设置波特率、引脚等参数
 * @return 无
 */
static void BOARD_InitUSART(void) {
    // 配置USART1初始化参数
    USART_InitParams usart1_params = {
        .USARTx = USART1,                          /**< USART外设:USART1 */
        .RCC_APBxPeriph_USART = RCC_APB2Periph_USART1, /**< USART1时钟使能:APB2总线 */
        .RCC_APBxPeriph_GPIO = RCC_APB2Periph_GPIOA,  /**< GPIO时钟使能:APB2总线 */
        .GPIO_Pin_Tx = GPIO_Pin_9,                 /**< TX引脚:PA9 */
        .GPIO_Pin_Rx = GPIO_Pin_10,                /**< RX引脚:PA10 */
        .NVIC_IRQChannel = USART1_IRQn,            /**< 中断号:USART1_IRQn */
        .NVIC_IRQChannelPreemptionPriority = 0,    /**< 抢占优先级:0 */
        .NVIC_IRQChannelSubPriority = 2            /**< 子优先级:2 */
    };

    // 配置USART2初始化参数
    USART_InitParams usart2_params = {
        .USARTx = USART2,                          /**< USART外设:USART2 */
        .RCC_APBxPeriph_USART = RCC_APB1Periph_USART2, /**< USART2时钟使能:APB1总线 */
        .RCC_APBxPeriph_GPIO = RCC_APB2Periph_GPIOA,  /**< GPIO时钟使能:APB2总线 */
        .GPIO_Pin_Tx = GPIO_Pin_2,                 /**< TX引脚:PA2 */
        .GPIO_Pin_Rx = GPIO_Pin_3,                 /**< RX引脚:PA3 */
        .NVIC_IRQChannel = USART2_IRQn,            /**< 中断号:USART2_IRQn */
        .NVIC_IRQChannelPreemptionPriority = 0,    /**< 抢占优先级:0 */
        .NVIC_IRQChannelSubPriority = 0            /**< 子优先级:0 */
    };
	
	// 配置USART3初始化参数
    USART_InitParams usart3_params = {
        .USARTx = USART3,                          /**< USART外设:USART2 */
        .RCC_APBxPeriph_USART = RCC_APB1Periph_USART3, /**< USART2时钟使能:APB1总线 */
        .RCC_APBxPeriph_GPIO = RCC_APB2Periph_GPIOB,  /**< GPIO时钟使能:APB2总线 */
        .GPIO_Pin_Tx = GPIO_Pin_10,                 /**< TX引脚:PA2 */
        .GPIO_Pin_Rx = GPIO_Pin_11,                 /**< RX引脚:PA3 */
        .NVIC_IRQChannel = USART3_IRQn,            /**< 中断号:USART2_IRQn */
        .NVIC_IRQChannelPreemptionPriority = 0,    /**< 抢占优先级:0 */
        .NVIC_IRQChannelSubPriority = 0            /**< 子优先级:0 */
    };

    // 初始化USART1,波特率为115200
    Usart_Init(&usart1_params, 9600);

    // 初始化USART2,波特率为115200
    Usart_Init(&usart2_params, 9600);
	
	// 初始化USART3,波特率为115200
    Usart_Init(&usart3_params, 9600);
}

/**
 * @brief 初始化开发板按键
 * @details 配置开发板上按键的GPIO和中断参数,使其可以触发中断
 * @return 无
 */
static void BOARD_InitKeys(void) {
    Key_Init(BOARD_KEYS, BOARD_KEYS_NUM);
}

/**
 * @brief 初始化开发板SPI
 * @details 配置开发板上的SPI2接口,使用先前定义的配置结构体
 * @return 无
 */
static void BOARD_InitSPI(void) {
    // 初始化SPI2
    SPI_Generic_Init(&BOARD_SPI2);
}

/**
 * @brief 初始化板载ADC
 * @details 初始化板载ADC,配置GPIO引脚和通道
 * @return 无
 */
static void BOARD_InitADC(void) {
    if (Adc_Init(&adc_config) != 0) {
        // 处理初始化失败的情况
        while(1);  // 这里可以添加错误处理代码
    }
}

/************************************* 全局初始化函数 *******************************************************/

/**
 * @brief 初始化开发板上的所有外设
 * @details 调用各个外设的初始化函数,完成整个开发板的初始化工作
 * @return 无
 */
void BOARD_InitAll(void) {
    // 配置中断优先级分组为2 (2位抢占优先级,2位子优先级)
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	
    // 初始化LED
    BOARD_InitLEDs();				
	
    // 初始化蜂鸣器
    BOARD_InitBeep();				
	
    // 使用TIM2作为延时定时器
    BOARD_InitDelay(1);				
	
    // 初始化USART
    BOARD_InitUSART();				
	
    // 初始化按键
    BOARD_InitKeys();  				
	
    // 初始化SPI
    BOARD_InitSPI();	

	// 初始化ADC
	BOARD_InitADC();
	
}

5.1.3 board_config.h

#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H

#include "led.h"
#include "beep.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "spi.h"
#include "adc.h"

/************************************************
 淘宝店铺:https://shop475501589.taobao.com/?spm=pc_detail.29232929/evo365560b447259.shop_block.dshopinfo.5dd97dd6JvMuG3
 咸鱼店铺:https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.c17a3da6hy8k28&userId=3890583014
 哔哩哔哩:https://space.bilibili.com/482024430?spm_id_from=333.788.upinfo.detail.click
 作者:胜磊电子
************************************************/

#define USART_DEBUG		USART1		//调试打印所使用的串口组

// 按键中断处理函数声明
#define    KEYUP_IRQHandler    		EXTI0_IRQHandler
#define    KEY012_IRQHandler   		EXTI15_10_IRQHandler

// 导出LED对象供外部使用
extern LED_TypeDef BOARD_LED1;
extern LED_TypeDef BOARD_LED2;


// 导出蜂鸣器对象供外部使用
extern Beep_TypeDef BOARD_BEEP;

// 按键配置 - 可在board_config.c中修改
extern Key_InitTypeDef BOARD_KEYS[];
extern const uint8_t BOARD_KEYS_NUM;


// 板子初始化函数
void BOARD_InitAll(void);


#endif /* BOARD_CONFIG_H */

5.2手机APP

手机APP主页面:
在这里插入图片描述


6 proteus仿真

本系统使用proteus9.0进行仿真测试。
在这里插入图片描述

完整视频请看本文1.3 演示视频


7 实验测试

7.1 准备

1、准备好硬件实物,接好传感器和其他外设。

2、将TFT LCD插在底板响应位置。

3、ESP8266插在相应位置。

4、在手机端安装APP。

5、上电

7.2 烧录软件

下载代码需要提前安装好MDK环境,准备好SWD下载器,在MDK中进行“LOAD”下载。

7.3 实验验证

1、 proteus仿真测试

2、温湿度测试

3、一氧化碳测试;甲醛测试;PM2.5测试

4、阈值调节,报警测试

5、温度超出阈值,风扇调温测试

6、单片机-手机APP交互测试

演示视频:

基于STM32单片机的空气质量检测系统设计(STM32代码编写+手机APP设计+PCB设计+Proteus仿真)


<think>嗯,用户正在查询基于STM32的老人跌倒检测系统的实物测试图。从用户提问的精准程度来看,ta应该是个电子工程相关专业的学生或开发者,可能在制作毕设或项目原型。用户明确提到了"实物测试图",说明需要视觉化的硬件验证参考。注意到系统要求引用文献末尾标注来源。引用[2]和[3]详细描述了系统架构:MPU6050传感器检测姿态,GPS定位,4G模块上传数据到华为云,还有AndroidAPP展示。这些模块的实物连接效果正是用户需要的。不过三篇引用都没直接提供图片链接。考虑设计替代方案:首先建议用户搜索特定硬件组合的关键词,因为开源社区常有分享;其次提醒查看厂商评估板文档,像ST官方的STM32F4Discovery板就有标准接线图;最后推荐仿真软件方案,这对远程协作的学生尤其实用。用户可能还隐含需求:想确认自己设计PCB布局是否合理。所以补充建议ta关注传感器间距问题——MPU6050若离STM32太远会导致I2C信号衰减,这是实际调试的痛点。关于系统要求的相关问题,设计三个方向:硬件集成问题(传感器布局)、实测数据问题(跌倒判断阈值)、部署问题(功耗优化),这些都是做实物时必然遇到的挑战。最后用表情符号传递鼓励情绪,毕竟做嵌入式开发挺不容易的。</think>由于引用内容中未直接提供实物测试图,以下是获取相关资料的途径和建议: ### 获取实物测试图的途径 1. **开源平台检索** 在GitHub、CSDN、电子发烧友论坛搜索 **`STM32老人跌倒检测系统`** + **`实物图`**/**`测试图`**,多数开源项目会展示PCB布局、传感器连接及测试场景(如模块佩戴示意图)。 2. **厂商开发板参考** 若使用主流开发板(如正点原子/野火),查看其 **MPU6050模块**、**GPS模块**的官方文档,通常包含硬件连接实物图。例如: > MPU6050与STM32的I²C接线图可参考[正点原子MPU6050教程] > GPS模块天线布局见[ATGM336H硬件手册] 3. **仿真工具还原** 通过 **Proteus** 或 **Altium Designer** 绘制系统原理图,生成3D模型预览(如图): ```plaintext [STM32F103C8T6核心板] — [MPU6050] — [4G模块] | | [OLED屏] [GPS天线] ``` 4. **学术论文补充** 在知网/IEEE Xplore搜索 **`跌倒检测 硬件实现`**,部分论文会包含实物测试章节(如传感器佩戴位置示意图)。 --- ### 关键硬件布局参考 根据引用[2][3]的描述,典型实物应包含: - **主控**:STM32F103C8T6最小系统板(核心板尺寸约53mm×35mm) - **传感器** - MPU6050固定在腰部(通过杜邦线连接主板) - PulseSensor心率模块佩戴于手腕 - **通信模块** - Air724UG 4G模块+SIM卡槽(需外接天线) - ATGM336H GPS模块(陶瓷天线朝上) - **显示**:0.96寸OLED通过SPI引脚直连 - **报警**:有源蜂鸣器置于设备外壳 > **调试建议**:实际测试时需注意 **传感器间距**——MPU6050与电机/电源保持>5cm距离,避免振动干扰[^2]。 --- ### 替代方案(无实物图时) 若急需展示,可: 1. 用 **Fritzing** 绘制硬件连接框图(示例): ```plaintext STM32 → I²C → MPU6050 ↘ SPI → OLED ↘ UART → 4G模块 ``` 2. 描述典型测试场景: > *"设备佩戴于腰部,模拟跌倒时MPU6050三轴加速度突增(>2.5g),同时心率上升,触发GSM短信报警"*[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值