文章目录
-
- [1. 项目概述](#1. 项目概述)
- [2. 系统设计与工作流程](#2. 系统设计与工作流程)
-
- [2.1 系统功能](#2.1 系统功能)
- [2.2 系统框图](#2.2 系统框图)
- [3. 硬件准备与连接](#3. 硬件准备与连接)
-
- [3.1 物料清单](#3.1 物料清单)
- [3.2 电路连接图](#3.2 电路连接图)
- [4. 软件开发环境搭建](#4. 软件开发环境搭建)
-
- [4.1 软件安装](#4.1 软件安装)
- [4.2 创建工程](#4.2 创建工程)
- [5. 代码实现 (基于标准外设库)](#5. 代码实现 (基于标准外设库))
-
- [5.1 HC-SR501人体红外传感器驱动](#5.1 HC-SR501人体红外传感器驱动)
- [5.2 DS18B20温度传感器驱动](#5.2 DS18B20温度传感器驱动)
- [5.3 SIM800A GSM模块驱动](#5.3 SIM800A GSM模块驱动)
- [5.4 主程序逻辑与报警控制](#5.4 主程序逻辑与报警控制)
- [5.5 延时函数实现](#5.5 延时函数实现)
- [6. 系统测试与调试](#6. 系统测试与调试)
-
- [6.1 硬件测试步骤](#6.1 硬件测试步骤)
- [6.2 软件调试技巧](#6.2 软件调试技巧)
- [6.3 常见问题排查](#6.3 常见问题排查)
- [7. 项目优化与扩展建议](#7. 项目优化与扩展建议)
-
- [7.1 功能扩展](#7.1 功能扩展)
- [7.2 可靠性提升](#7.2 可靠性提升)
- [7.3 产品化考虑](#7.3 产品化考虑)
- [8. 总结](#8. 总结)
1. 项目概述
随着汽车保有量的激增,儿童或宠物被误锁车内导致窒息的安全事故时有发生。本设计基于STM32F103单片机,开发一套低成本、高可靠性的车内防窒息报警系统。系统通过HC-SR501人体红外传感器 检测车内是否有人,当检测到人员滞留且车内温度超过安全阈值时,立即通过SIM800A GSM模块向预设手机号发送报警短信,提醒车主及时处理,从而避免悲剧发生。
本教程面向零基础的STM32初学者,将从硬件选型、电路连接、软件编程到系统测试,提供完整、可直接落地的详细步骤。所有代码均提供完整文件,可直接复制使用。
2. 系统设计与工作流程
2.1 系统功能
- 人体检测:使用HC-SR501红外传感器实时监测车内是否有人。
- 温度监测:使用DS18B20数字温度传感器监测车内温度。
- 智能判断:当同时满足"车内有人"且"温度超过设定阈值(如35℃)"时,判定为危险状态。
- 远程报警:危险状态下,通过SIM800A GSM模块自动发送中文报警短信至车主手机。
- 状态指示:通过LED和蜂鸣器进行本地声光报警。
2.2 系统框图
下图展示了系统的核心组成与数据流:
通信与执行模块
传感器模块
数字信号
单总线数据
UART串口
GPIO控制
GPIO控制
条件满足
电源供电
STM32F103C8T6
主控制器
HC-SR501
人体红外传感器
DS18B20
温度传感器
SIM800A GSM模块
LED指示灯
有源蜂鸣器
逻辑判断
触发报警
发送报警短信
启动声光报警
车主手机
3. 硬件准备与连接
3.1 物料清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控芯片 | STM32F103C8T6 (最小系统板) | 1 | 核心控制器,俗称"蓝 pill" |
| 人体红外传感器 | HC-SR501 | 1 | 检测人体移动 |
| 温度传感器 | DS18B20 | 1 | 测量车内温度,防水型更佳 |
| GSM模块 | SIM800A | 1 | 支持2G网络,用于发送短信 |
| 蜂鸣器 | 有源蜂鸣器 (低电平触发) | 1 | 报警提示音 |
| LED | 5mm 红色LED | 1 | 报警指示灯 |
| 电阻 | 220Ω、1kΩ、4.7kΩ | 若干 | 限流、上拉用 |
| SIM卡 | 移动/联通2G卡 | 1 | 需开通短信业务,关闭PIN码锁 |
| 电源 | 5V/2A 独立电源 | 1 | 为GSM模块单独供电 |
| 杜邦线 | 公对公、母对母 | 若干 | 连接电路 |
| 面包板 | 830孔 | 1 | 方便搭建原型 |
3.2 电路连接图
核心接线表 (请对照STM32F103C8T6最小系统板引脚)
| STM32引脚 | 连接对象 | 说明 |
|---|---|---|
| 3.3V | HC-SR501 VCC、DS18B20 VDD | 传感器供电 |
| GND | 所有模块的GND | 共地 |
| PA0 | HC-SR501 OUT | 人体检测信号输入 (高电平有效) |
| PB12 | DS18B20 DQ | 温度数据线 (需接4.7kΩ上拉到3.3V) |
| PA9 (USART1_TX) | SIM800A RX | 发送AT指令 |
| PA10 (USART1_RX) | SIM800A TX | 接收模块响应 |
| PA1 | LED阳极 (串联220Ω电阻) | 报警指示灯 |
| PA2 | 蜂鸣器信号端 (低电平触发) | 报警发声器 |
| 5V (外部电源) | SIM800A VCC | 重要:GSM模块必须单独供电 |
| GND (外部电源) | SIM800A GND | 与STM32共地 |
接线注意事项:
- 电平匹配:HC-SR501输出高电平为5V,而STM32 GPIO耐受5V,可直接连接。若担心长期使用,可在OUT脚串联1kΩ电阻到PA0。
- DS18B20上拉:必须在DQ线上接一个4.7kΩ的上拉电阻到3.3V,否则无法通信。
- GSM模块供电 :SIM800A工作电流峰值可达2A,切勿直接从STM32开发板的5V引脚取电,必须使用独立的5V/2A电源适配器,否则会导致STM32复位或GSM模块无法正常工作。
- 串口交叉:STM32的TX接GSM的RX,STM32的RX接GSM的TX。
4. 软件开发环境搭建
4.1 软件安装
- Keil MDK-ARM:用于编写、编译和调试代码。从官网下载并安装,同时安装STM32F1的Device Family Pack。
- STM32CubeMX:用于图形化配置引脚和生成初始化代码。从ST官网下载安装。
- 串口调试助手:如XCOM、SSCOM,用于调试GSM模块的AT指令。
4.2 创建工程
- 打开STM32CubeMX,新建工程,选择MCU型号
STM32F103C8Tx。 - 配置时钟 :在
RCC中,将HSE设置为Crystal/Ceramic Resonator。 - 配置引脚 :
PA0设置为GPIO_Input,模式为Pull-down(因为HC-SR501高电平有效,下拉避免悬空干扰)。PB12设置为GPIO_Output,初始输出高电平 (用于DS18B20通信)。PA1、PA2设置为GPIO_Output,推挽输出,初始输出高电平 (LED和蜂鸣器低电平触发)。PA9和PA10设置为USART1,模式为Asynchronous。
- 配置USART1 :波特率
9600,字长8 Bits,停止位1,无校验,无流控。 - 配置时钟树 :将HCLK设置为最大
72MHz。 - 生成代码 :在
Project Manager中设置工程名称、路径,选择MDK-ARM作为Toolchain,然后生成代码。
5. 代码实现 (基于标准外设库)
将生成的代码用Keil打开,我们将在Core/Src和Core/Inc目录下添加以下文件。
5.1 HC-SR501人体红外传感器驱动
创建文件:hcsr501.c 和 hcsr501.h
hcsr501.h 头文件:
c
#ifndef __HCSR501_H
#define __HCSR501_H
#include "stm32f1xx_hal.h"
// 人体检测引脚定义
#define PIR_GPIO_PORT GPIOA
#define PIR_GPIO_PIN GPIO_PIN_0
#define PIR_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
// 函数声明
void HCSR501_Init(void);
uint8_t HCSR501_Read(void);
#endif
hcsr501.c 源文件:
c
#include "hcsr501.h"
/**
* @brief 初始化HC-SR501人体红外传感器引脚
* @param None
* @retval None
*/
void HCSR501_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIOA时钟
PIR_GPIO_CLK_ENABLE();
// 配置PA0为上拉输入
GPIO_InitStruct.Pin = PIR_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN; // 下拉,默认低电平
HAL_GPIO_Init(PIR_GPIO_PORT, &GPIO_InitStruct);
}
/**
* @brief 读取人体检测状态
* @param None
* @retval 1: 检测到人体;0: 未检测到人体
*/
uint8_t HCSR501_Read(void)
{
// HC-SR501输出高电平表示检测到人体
return HAL_GPIO_ReadPin(PIR_GPIO_PORT, PIR_GPIO_PIN);
}
5.2 DS18B20温度传感器驱动
创建文件:ds18b20.c 和 ds18b20.h
ds18b20.h 头文件:
c
#ifndef __DS18B20_H
#define __DS18B20_H
#include "stm32f1xx_hal.h"
// DS18B20引脚定义
#define DS18B20_GPIO_PORT GPIOB
#define DS18B20_GPIO_PIN GPIO_PIN_12
#define DS18B20_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
// 函数声明
void DS18B20_Init(void);
void DS18B20_Start(void);
float DS18B20_GetTemp(void);
static void DS18B20_WriteByte(uint8_t data);
static uint8_t DS18B20_ReadByte(void);
static void DS18B20_SetPinOutput(void);
static void DS18B20_SetPinInput(void);
static uint8_t DS18B20_Reset(void);
#endif
ds18b20.c 源文件 (包含详细的单总线时序实现):
c
#include "ds18b20.h"
#include "delay.h" // 需要微秒级延时函数,下文提供
// 微秒级延时函数声明 (需根据系统时钟实现)
void Delay_us(uint32_t us);
/**
* @brief 初始化DS18B20的GPIO
*/
void DS18B20_Init(void)
{
DS18B20_GPIO_CLK_ENABLE();
// 初始状态设置为输出高电平
DS18B20_SetPinOutput();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);
}
/**
* @brief DS18B20复位脉冲
* @retval 1: 复位成功,检测到DS18B20存在脉冲;0: 复位失败
*/
static uint8_t DS18B20_Reset(void)
{
uint8_t presence = 0;
DS18B20_SetPinOutput();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);
Delay_us(480); // 保持低电平至少480us
DS18B20_SetPinInput();
Delay_us(60); // 等待15-60us后读取
if (!HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN))
{
presence = 1; // 检测到存在脉冲
}
Delay_us(420); // 等待存在脉冲结束
return presence;
}
/**
* @brief 向DS18B20写入一个字节
*/
static void DS18B20_WriteByte(uint8_t data)
{
for (uint8_t i = 0; i < 8; i++)
{
DS18B20_SetPinOutput();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);
Delay_us(1); // 拉低后等待1us
if (data & 0x01) // 写1
{
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);
}
// 写0则保持低电平
Delay_us(60); // 保持60us
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);
data >>= 1;
Delay_us(1); // 恢复时间
}
}
/**
* @brief 从DS18B20读取一个字节
*/
static uint8_t DS18B20_ReadByte(void)
{
uint8_t data = 0;
for (uint8_t i = 0; i < 8; i++)
{
data >>= 1;
DS18B20_SetPinOutput();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);
Delay_us(1); // 拉低至少1us
DS18B20_SetPinInput();
Delay_us(5); // 等待5us后读取
if (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN))
{
data |= 0x80; // 读到1
}
Delay_us(55); // 等待读时隙结束
}
return data;
}
/**
* @brief 启动温度转换
*/
void DS18B20_Start(void)
{
if (DS18B20_Reset())
{
DS18B20_WriteByte(0xCC); // 跳过ROM命令
DS18B20_WriteByte(0x44); // 启动温度转换命令
}
}
/**
* @brief 读取温度值
* @retval 温度值,单位:摄氏度
*/
float DS18B20_GetTemp(void)
{
uint8_t temp_l, temp_h;
int16_t temp;
float temperature;
if (DS18B20_Reset())
{
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0xBE); // 读暂存器
temp_l = DS18B20_ReadByte();
temp_h = DS18B20_ReadByte();
temp = (temp_h << 8) | temp_l;
temperature = temp / 16.0; // DS18B20精度为0.0625,除以16得到实际温度
return temperature;
}
return -99.9; // 读取失败
}
// GPIO模式切换辅助函数
static void DS18B20_SetPinOutput(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStruct);
}
static void DS18B20_SetPinInput(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStruct);
}
5.3 SIM800A GSM模块驱动
创建文件:sim800a.c 和 sim800a.h
sim800a.h 头文件:
c
#ifndef __SIM800A_H
#define __SIM800A_H
#include "stm32f1xx_hal.h"
// 使用USART1与SIM800A通信
extern UART_HandleTypeDef huart1;
// 函数声明
void SIM800A_Init(void);
void SIM800A_SendCmd(char *cmd);
uint8_t SIM800A_WaitForResponse(char *expected_resp, uint32_t timeout);
void SIM800A_SendSMS(char *phone_num, char *message);
#endif
sim800a.c 源文件:
c
#include "sim800a.h"
#include <string.h>
#include <stdio.h>
// 接收缓冲区
char gsm_rx_buffer[256];
uint16_t gsm_rx_index = 0;
/**
* @brief 初始化GSM模块 (发送AT指令测试)
*/
void SIM800A_Init(void)
{
HAL_Delay(3000); // 等待模块上电稳定
// 测试AT指令
SIM800A_SendCmd("AT\r\n");
if (SIM800A_WaitForResponse("OK", 2000))
{
// 设置短信文本模式
SIM800A_SendCmd("AT+CMGF=1\r\n");
SIM800A_WaitForResponse("OK", 1000);
// 设置短信提示方式 (直接存储到SIM卡)
SIM800A_SendCmd("AT+CNMI=2,1,0,0,0\r\n");
SIM800A_WaitForResponse("OK", 1000);
}
}
/**
* @brief 向GSM模块发送AT指令
* @param cmd: AT指令字符串
*/
void SIM800A_SendCmd(char *cmd)
{
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 1000);
}
/**
* @brief 等待GSM模块返回特定响应
* @param expected_resp: 期望的响应字符串 (如 "OK", "ERROR")
* @param timeout: 超时时间 (毫秒)
* @retval 1: 收到期望响应;0: 超时或收到错误
*/
uint8_t SIM800A_WaitForResponse(char *expected_resp, uint32_t timeout)
{
uint32_t start_tick = HAL_GetTick();
gsm_rx_index = 0;
memset(gsm_rx_buffer, 0, sizeof(gsm_rx_buffer));
while ((HAL_GetTick() - start_tick) < timeout)
{
// 检查是否有数据接收 (实际项目中应使用中断或DMA)
uint8_t ch;
if (HAL_UART_Receive(&huart1, &ch, 1, 10) == HAL_OK)
{
if (gsm_rx_index < sizeof(gsm_rx_buffer) - 1)
{
gsm_rx_buffer[gsm_rx_index++] = ch;
gsm_rx_buffer[gsm_rx_index] = '\0';
// 检查是否包含期望的响应
if (strstr(gsm_rx_buffer, expected_resp) != NULL)
{
return 1;
}
// 检查是否包含ERROR
if (strstr(gsm_rx_buffer, "ERROR") != NULL)
{
return 0;
}
}
}
}
return 0; // 超时
}
/**
* @brief 发送短信
* @param phone_num: 目标手机号码 (字符串,如 "13800138000")
* @param message: 短信内容 (支持中文,需注意编码)
*/
void SIM800A_SendSMS(char *phone_num, char *message)
{
char cmd[50];
// 1. 设置目标号码
sprintf(cmd, "AT+CMGS=\"%s\"\r\n", phone_num);
SIM800A_SendCmd(cmd);
HAL_Delay(500);
// 2. 发送短信内容 (中文短信)
HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), 1000);
HAL_Delay(100);
// 3. 发送结束符 Ctrl+Z (0x1A)
uint8_t ctrl_z = 0x1A;
HAL_UART_Transmit(&huart1, &ctrl_z, 1, 1000);
// 4. 等待发送完成
SIM800A_WaitForResponse("+CMGS:", 10000);
}
5.4 主程序逻辑与报警控制
修改文件:main.c
在main.c中添加以下代码:
c
/* 用户头文件 */
#include "hcsr501.h"
#include "ds18b20.h"
#include "sim800a.h"
#include <stdio.h>
#include <string.h>
/* 报警引脚定义 */
#define ALARM_LED_PIN GPIO_PIN_1
#define ALARM_LED_PORT GPIOA
#define ALARM_BUZZER_PIN GPIO_PIN_2
#define ALARM_BUZZER_PORT GPIOA
/* 温度阈值 (单位:摄氏度) */
#define TEMP_THRESHOLD 35.0
/* 状态标志 */
typedef enum
{
STATE_NORMAL = 0,
STATE_WARNING,
STATE_ALARM
} SystemState;
SystemState g_system_state = STATE_NORMAL;
uint8_t g_alarm_sent = 0; // 短信是否已发送标志
/* 函数声明 */
static void System_Init(void);
static void Alarm_Control(uint8_t on_off);
static void Check_Danger(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
// 用户外设初始化
System_Init();
// 主循环
while (1)
{
// 1. 检测危险状态
Check_Danger();
// 2. 根据状态控制报警
if (g_system_state == STATE_ALARM)
{
Alarm_Control(1); // 打开声光报警
// 首次进入报警状态,发送短信
if (g_alarm_sent == 0)
{
char sms_msg[100];
float current_temp = DS18B20_GetTemp();
sprintf(sms_msg, "【车内防窒息报警】检测到车内有人且温度过高(%.1f℃),请立即查看!", current_temp);
SIM800A_SendSMS("13800138000", sms_msg); // 替换为你的手机号
g_alarm_sent = 1; // 标记已发送
}
}
else
{
Alarm_Control(0); // 关闭报警
g_alarm_sent = 0; // 重置发送标志
}
HAL_Delay(1000); // 每秒检测一次
}
}
/**
* @brief 系统初始化
*/
static void System_Init(void)
{
// 初始化传感器
HCSR501_Init();
DS18B20_Init();
// 初始化GSM模块
SIM800A_Init();
// 初始化报警输出引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
// LED引脚
GPIO_InitStruct.Pin = ALARM_LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ALARM_LED_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(ALARM_LED_PORT, ALARM_LED_PIN, GPIO_PIN_SET); // 初始关闭
// 蜂鸣器引脚
GPIO_InitStruct.Pin = ALARM_BUZZER_PIN;
HAL_GPIO_Init(ALARM_BUZZER_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(ALARM_BUZZER_PORT, ALARM_BUZZER_PIN, GPIO_PIN_SET); // 初始关闭
}
/**
* @brief 报警控制
* @param on_off: 1-打开报警,0-关闭报警
*/
static void Alarm_Control(uint8_t on_off)
{
if (on_off)
{
// 声光报警 (LED闪烁,蜂鸣器间歇鸣响)
HAL_GPIO_TogglePin(ALARM_LED_PORT, ALARM_LED_PIN);
HAL_GPIO_WritePin(ALARM_BUZZER_PORT, ALARM_BUZZER_PIN, GPIO_PIN_RESET);
HAL_Delay(200);
HAL_GPIO_WritePin(ALARM_BUZZER_PORT, ALARM_BUZZER_PIN, GPIO_PIN_SET);
HAL_Delay(200);
}
else
{
// 关闭报警
HAL_GPIO_WritePin(ALARM_LED_PORT, ALARM_LED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(ALARM_BUZZER_PORT, ALARM_BUZZER_PIN, GPIO_PIN_SET);
}
}
/**
* @brief 检测危险状态
*/
static void Check_Danger(void)
{
static uint8_t human_detected = 0;
static float temperature = 0;
// 读取传感器数据
human_detected = HCSR501_Read();
DS18B20_Start(); // 启动温度转换
HAL_Delay(750); // 等待转换完成 (DS18B20最大转换时间750ms)
temperature = DS18B20_GetTemp();
// 判断逻辑
if (human_detected && (temperature > TEMP_THRESHOLD))
{
g_system_state = STATE_ALARM;
}
else if (human_detected)
{
g_system_state = STATE_WARNING; // 有人但温度正常
}
else
{
g_system_state = STATE_NORMAL;
}
}
5.5 延时函数实现
创建文件:delay.c 和 delay.h
delay.h 头文件:
c
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f1xx_hal.h"
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
#endif
delay.c 源文件:
c
#include "delay.h"
/**
* @brief 微秒级延时 (基于SysTick)
* @note 系统时钟72MHz时,SysTick每1us计数72次
*/
void Delay_us(uint32_t us)
{
uint32_t ticks;
uint32_t told, tnow, tcnt = 0;
uint32_t reload = SysTick->LOAD;
ticks = us * 72; // 72MHz下,1us需要72个时钟周期
told = SysTick->VAL;
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow;
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break;
}
}
}
}
/**
* @brief 毫秒级延时 (基于HAL_Delay)
*/
void Delay_ms(uint32_t ms)
{
HAL_Delay(ms);
}
6. 系统测试与调试
6.1 硬件测试步骤
- 单独测试GSM模块 :使用USB转TTL模块连接电脑,通过串口助手发送
AT指令,确认模块返回OK。 - 测试HC-SR501:用手在传感器前移动,用万用表测量OUT引脚电压,应有0V到3.3V/5V的跳变。
- 测试DS18B20:单独连接DS18B20到STM32,编写简单读取程序,确认能读取到环境温度。
- 整体连接:按接线表连接所有模块,特别注意GSM模块的独立供电。
6.2 软件调试技巧
-
串口调试 :在
main.c中添加串口打印,实时输出传感器状态和温度值。cchar debug_msg[50]; sprintf(debug_msg, "人体检测:%d, 温度:%.1f℃\r\n", human_detected, temperature); HAL_UART_Transmit(&huart1, (uint8_t*)debug_msg, strlen(debug_msg), 1000); -
模拟测试:暂时调低温度阈值(如设为25℃),用打火机或吹风机轻微加热DS18B20,观察是否触发报警。
-
GSM模块调试:先单独测试短信发送功能,确认能收到短信后再集成到主逻辑中。
6.3 常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| GSM模块无反应 | 供电不足 | 使用独立的5V/2A电源,检查电源线是否接触良好 |
| 无法发送短信 | SIM卡问题 | 确认SIM卡已开通短信业务,且关闭了PIN码锁 |
| HC-SR501一直输出高电平 | 传感器误触发 | 调整传感器上的两个电位器: 1. 灵敏度调节:逆时针减小 2. 延时调节:逆时针缩短 |
| DS18B20读取值为-99.9 | 通信失败 | 检查DQ线是否接了4.7kΩ上拉电阻,检查接线是否松动 |
| 报警不触发 | 阈值设置不当 | 根据实际环境调整TEMP_THRESHOLD宏定义的值 |
7. 项目优化与扩展建议
7.1 功能扩展
- 增加湿度监测:添加DHT11传感器,同时监测车内湿度。
- 多级报警:根据温度超过阈值的程度,实现分级报警(如短信、电话、APP推送)。
- 数据记录:添加SD卡模块,记录历史温湿度数据。
- 低功耗模式:车辆熄火后,系统进入休眠模式,定时唤醒检测,节省电瓶电量。
- GPS定位:添加GPS模块,在报警短信中附带车辆位置信息。
7.2 可靠性提升
- 防误报机制:要求人体信号持续检测超过30秒才触发报警,避免临时经过车辆触发。
- 看门狗:启用STM32的独立看门狗(IWDG),防止程序跑飞。
- 电源管理:增加电压检测电路,在电瓶电压过低时自动关机,防止车辆无法启动。
7.3 产品化考虑
- PCB设计:将电路集成到一块PCB上,提高稳定性和美观度。
- 外壳设计:3D打印或定制外壳,便于安装在车内隐蔽位置。
- 通信备份:在GSM信号弱的区域,可增加蓝牙模块,连接手机APP作为备用报警通道。
8. 总结
本教程详细介绍了基于STM32F103的车内防窒息系统的完整实现过程。从硬件选型、电路连接到软件编程,每一步都提供了可直接使用的代码和详细的解释。系统核心在于红外检测 与GSM报警的联动,能够在检测到人员滞留且温度过高时及时通知车主。
安全提示:本系统为辅助安全装置,不能完全替代驾驶员的注意力和责任心。任何时候都不应将儿童或宠物单独留在车内,即使安装了此类报警系统。