文章目录
- 前言
- 一、系统整体设计
-
- [1.1 功能需求](#1.1 功能需求)
- [1.2 硬件选型](#1.2 硬件选型)
- [1.3 系统架构流程图](#1.3 系统架构流程图)
- 二、硬件电路设计与接线
-
- [2.1 核心引脚分配(STM32F103C8T6)](#2.1 核心引脚分配(STM32F103C8T6))
- [2.2 硬件接线注意事项](#2.2 硬件接线注意事项)
- 三、开发环境搭建
-
- [3.1 环境配置步骤](#3.1 环境配置步骤)
- 四、完整代码实现(可直接编译落地)
-
- [4.1 系统通用配置文件](#4.1 系统通用配置文件)
- [4.2 串口调试驱动](#4.2 串口调试驱动)
- [4.3 DHT11温湿度传感器驱动](#4.3 DHT11温湿度传感器驱动)
- [4.4 智能衣柜主逻辑代码](#4.4 智能衣柜主逻辑代码)
- 五、代码深度解析与工程说明
-
- [5.1 核心逻辑解析](#5.1 核心逻辑解析)
- [5.2 零基础编译说明](#5.2 零基础编译说明)
- 六、故障排查与避坑方案
-
- [6.1 DHT11读取失败](#6.1 DHT11读取失败)
- [6.2 风扇/UV灯/LED不工作](#6.2 风扇/UV灯/LED不工作)
- [6.3 人体感应误触发/不触发](#6.3 人体感应误触发/不触发)
- [6.4 串口乱码](#6.4 串口乱码)
- 七、性能优化与工程升级方向
-
- [7.1 低功耗优化](#7.1 低功耗优化)
- [7.2 功能升级](#7.2 功能升级)
- [7.3 稳定性优化](#7.3 稳定性优化)
- 八、总结
前言
在潮湿环境下,衣柜内衣物极易受潮发霉、滋生细菌,传统除湿方式效率低且无法自动化控制。本文基于STM32F103C8T6 主控芯片,设计一套集温湿度实时监测、自动除湿、防霉杀菌、人体感应照明于一体的智能衣柜系统。
系统具备全自动化运行、低功耗、高可靠性、易部署等特点,零基础开发者可直接按照本文步骤完成硬件搭建、代码移植、调试与落地,所有代码均经过实测验证,无冗余、无报错,可直接编译运行。
一、系统整体设计
1.1 功能需求
- 温湿度采集:实时采集衣柜内部环境温湿度,判断潮湿/发霉风险
- 自动除湿:湿度超过阈值自动启动除湿风扇,达标后自动关闭
- 防霉杀菌:定时启动UV紫外线灯杀菌,抑制霉菌生长
- 人体感应照明:人体靠近衣柜自动点亮LED灯,离开后延时熄灭
- 状态指示:通过串口输出系统运行状态,方便调试与监控
1.2 硬件选型
| 模块名称 | 型号/规格 | 作用 |
|---|---|---|
| 主控芯片 | STM32F103C8T6 | 系统核心控制单元 |
| 温湿度传感器 | DHT11 | 采集环境温湿度数据 |
| 人体红外传感器 | HC-SR505 | 检测人体靠近信号 |
| 除湿执行模块 | 5V直流风扇 | 加速空气流通,实现除湿 |
| 防霉模块 | UV紫外线LED灯 | 杀菌防霉 |
| 照明模块 | 白光LED灯 | 衣柜照明 |
| 驱动模块 | S8050三极管+1K电阻 | 控制大功率外设 |
| 电源模块 | 5V/3.3V稳压电源 | 为整个系统供电 |
1.3 系统架构流程图
#mermaid-svg-p9GmI7HOnJVrYtmp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-p9GmI7HOnJVrYtmp .error-icon{fill:#552222;}#mermaid-svg-p9GmI7HOnJVrYtmp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-p9GmI7HOnJVrYtmp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-p9GmI7HOnJVrYtmp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-p9GmI7HOnJVrYtmp .marker.cross{stroke:#333333;}#mermaid-svg-p9GmI7HOnJVrYtmp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-p9GmI7HOnJVrYtmp p{margin:0;}#mermaid-svg-p9GmI7HOnJVrYtmp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster-label text{fill:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster-label span{color:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster-label span p{background-color:transparent;}#mermaid-svg-p9GmI7HOnJVrYtmp .label text,#mermaid-svg-p9GmI7HOnJVrYtmp span{fill:#333;color:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp .node rect,#mermaid-svg-p9GmI7HOnJVrYtmp .node circle,#mermaid-svg-p9GmI7HOnJVrYtmp .node ellipse,#mermaid-svg-p9GmI7HOnJVrYtmp .node polygon,#mermaid-svg-p9GmI7HOnJVrYtmp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-p9GmI7HOnJVrYtmp .rough-node .label text,#mermaid-svg-p9GmI7HOnJVrYtmp .node .label text,#mermaid-svg-p9GmI7HOnJVrYtmp .image-shape .label,#mermaid-svg-p9GmI7HOnJVrYtmp .icon-shape .label{text-anchor:middle;}#mermaid-svg-p9GmI7HOnJVrYtmp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-p9GmI7HOnJVrYtmp .rough-node .label,#mermaid-svg-p9GmI7HOnJVrYtmp .node .label,#mermaid-svg-p9GmI7HOnJVrYtmp .image-shape .label,#mermaid-svg-p9GmI7HOnJVrYtmp .icon-shape .label{text-align:center;}#mermaid-svg-p9GmI7HOnJVrYtmp .node.clickable{cursor:pointer;}#mermaid-svg-p9GmI7HOnJVrYtmp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-p9GmI7HOnJVrYtmp .arrowheadPath{fill:#333333;}#mermaid-svg-p9GmI7HOnJVrYtmp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-p9GmI7HOnJVrYtmp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-p9GmI7HOnJVrYtmp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p9GmI7HOnJVrYtmp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-p9GmI7HOnJVrYtmp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p9GmI7HOnJVrYtmp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster text{fill:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp .cluster span{color:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-p9GmI7HOnJVrYtmp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-p9GmI7HOnJVrYtmp rect.text{fill:none;stroke-width:0;}#mermaid-svg-p9GmI7HOnJVrYtmp .icon-shape,#mermaid-svg-p9GmI7HOnJVrYtmp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p9GmI7HOnJVrYtmp .icon-shape p,#mermaid-svg-p9GmI7HOnJVrYtmp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-p9GmI7HOnJVrYtmp .icon-shape .label rect,#mermaid-svg-p9GmI7HOnJVrYtmp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p9GmI7HOnJVrYtmp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-p9GmI7HOnJVrYtmp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-p9GmI7HOnJVrYtmp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 湿度超标
湿度正常
定时触发
检测到人体
无人体
STM32F103主控
DHT11温湿度采集
HC-SR505人体感应采集
数据解析与阈值判断
人体状态判断
启动除湿风扇
关闭除湿风扇
启动UV防霉灯
开启照明LED
关闭照明LED
系统状态串口输出
流程图解读 :
系统以STM32F103为核心,周期性采集温湿度与人体感应信号;温湿度模块判断除湿逻辑,人体感应模块控制照明逻辑,UV灯按固定周期工作实现防霉;所有执行状态通过串口实时上报,形成完整的闭环控制系统。
二、硬件电路设计与接线
2.1 核心引脚分配(STM32F103C8T6)
本系统所有GPIO均配置为推挽输出/上拉输入,无冲突、无复用,适合零基础开发。
| 外设模块 | STM32引脚 | 引脚模式 | 功能说明 |
|---|---|---|---|
| DHT11_DATA | PA0 | 通用推挽 | 温湿度数据通信引脚 |
| HC-SR505_OUT | PA1 | 上拉输入 | 人体感应信号输入 |
| 除湿风扇控制 | PB0 | 推挽输出 | 高电平启动风扇 |
| UV防霉灯控制 | PB1 | 推挽输出 | 高电平点亮UV灯 |
| 照明LED控制 | PB2 | 推挽输出 | 高电平点亮照明灯 |
2.2 硬件接线注意事项
- DHT11必须外接10K上拉电阻,保证数据传输稳定
- 风扇、UV灯属于大功率外设,必须通过S8050三极管驱动,不可直接接GPIO
- HC-SR505模块供电为5V,输出信号为3.3V,可直接连接STM32引脚
- 所有模块共地,避免电平干扰导致数据异常
三、开发环境搭建
本项目使用Keil5 MDK-ARM 开发环境,固件库采用STM32F10x_StdPeriph_Driver V3.5.0标准库,无HAL库依赖,移植性极强。
3.1 环境配置步骤
- 安装Keil5 MDK,添加STM32F103C8T6芯片支持包
- 新建工程,选择STM32F103C8芯片,加载标准库
- 配置工程:开启C99模式,设置晶振为8MHz
- 添加本文提供的所有代码文件,直接编译下载即可运行
四、完整代码实现(可直接编译落地)
所有代码均标注文件名、完整注释,零基础可直接复制使用。
4.1 系统通用配置文件
文件名:sys.h
c
#ifndef __SYS_H
#define __SYS_H
#include "stm32f10x.h"
// 函数声明
void RCC_Configuration(void); // 系统时钟配置
void GPIO_Configuration(void); // GPIO初始化配置
void Delay_ms(uint16_t ms); // 毫秒级延时
void Delay_us(uint32_t us); // 微秒级延时
#endif
文件名:sys.c
c
#include "sys.h"
/************************************************
函数名称:RCC_Configuration
函数功能:配置系统时钟,开启所有外设时钟
入口参数:无
返回值 :无
************************************************/
void RCC_Configuration(void)
{
// 开启GPIOA、GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
// 开启串口1时钟(用于调试输出)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
}
/************************************************
函数名称:GPIO_Configuration
函数功能:初始化所有GPIO引脚
入口参数:无
返回值 :无
************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// PA0 DHT11 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// PA1 HC-SR505 上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// PB0 PB1 PB2 推挽输出 控制风扇、UV灯、照明
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 默认关闭所有外设
GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);
}
/************************************************
函数名称:Delay_ms
函数功能:毫秒级延时(8MHz晶振)
入口参数:ms 延时毫秒数
返回值 :无
************************************************/
void Delay_ms(uint16_t ms)
{
uint16_t i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 1120; j++);
}
/************************************************
函数名称:Delay_us
函数功能:微秒级延时
入口参数:us 延时微秒数
返回值 :无
************************************************/
void Delay_us(uint32_t us)
{
uint32_t i;
for(i = 0; i < 8*us; i++);
}
4.2 串口调试驱动
文件名:usart.h
c
#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"
void USART1_Init(void); // 串口初始化
void USART1_Send_String(char *str); // 发送字符串
void USART1_Send_Num(uint16_t num); // 发送数字
#endif
文件名:usart.c
c
#include "usart.h"
#include "sys.h"
/************************************************
函数名称:USART1_Init
函数功能:初始化串口1 波特率9600
入口参数:无
返回值 :无
************************************************/
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// PA9 TX 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// PA10 RX 上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 串口配置
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/************************************************
函数名称:USART1_Send_String
函数功能:串口发送字符串
入口参数:str 字符串指针
返回值 :无
************************************************/
void USART1_Send_String(char *str)
{
while(*str)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, *str);
str++;
}
}
/************************************************
函数名称:USART1_Send_Num
函数功能:串口发送数字
入口参数:num 待发送数字
返回值 :无
************************************************/
void USART1_Send_Num(uint16_t num)
{
char buf[10];
sprintf(buf, "%d", num);
USART1_Send_String(buf);
}
4.3 DHT11温湿度传感器驱动
文件名:dht11.h
c
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
// 引脚定义
#define DHT11_PIN GPIO_Pin_0
#define DHT11_PORT GPIOA
// 函数声明
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi);
void DHT11_Input_Init(void);
void DHT11_Output_Init(void);
#endif
文件名:dht11.c
c
#include "dht11.h"
#include "sys.h"
/************************************************
函数名称:DHT11_Output_Init
函数功能:将DHT11引脚配置为推挽输出
************************************************/
void DHT11_Output_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}
/************************************************
函数名称:DHT11_Input_Init
函数功能:将DHT11引脚配置为上拉输入
************************************************/
void DHT11_Input_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}
/************************************************
函数名称:DHT11_Read_Data
函数功能:读取温湿度数据
入口参数:temp 温度指针,humi 湿度指针
返回值 :0 成功 1 失败
************************************************/
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5] = {0};
uint8_t i, j;
// 主机发送起始信号
DHT11_Output_Init();
GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
Delay_ms(20);
GPIO_SetBits(DHT11_PORT, DHT11_PIN);
Delay_us(30);
// 等待DHT11响应
DHT11_Input_Init();
if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 0)
{
// 等待低电平结束
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 0);
// 等待高电平结束
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1);
// 读取40位数据
for(j = 0; j < 5; j++)
{
for(i = 0; i < 8; i++)
{
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 0);
Delay_us(40);
if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1)
{
buf[j] |= (1 << (7 - i));
}
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1);
}
}
// 校验数据
if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4])
{
*humi = buf[0];
*temp = buf[2];
return 0;
}
}
return 1;
}
4.4 智能衣柜主逻辑代码
文件名:main.c
c
#include "sys.h"
#include "usart.h"
#include "dht11.h"
// 阈值定义
#define HUMI_MAX 60 // 湿度上限 超过启动除湿
#define UV_CYCLE 30000 // UV灯工作周期 30秒一次
#define LIGHT_DELAY 5000 // 照明延时5秒关闭
int main(void)
{
uint8_t temperature, humidity;
uint8_t read_flag;
uint32_t uv_timer = 0;
uint32_t light_timer = 0;
uint8_t human_state = 0;
// 系统初始化
RCC_Configuration();
GPIO_Configuration();
USART1_Init();
Delay_ms(1000);
USART1_Send_String("========智能衣柜系统启动========\r\n");
while(1)
{
// 1. 读取温湿度
read_flag = DHT11_Read_Data(&temperature, &humidity);
if(read_flag == 0)
{
// 串口打印数据
USART1_Send_String("温度:");
USART1_Send_Num(temperature);
USART1_Send_String("℃ 湿度:");
USART1_Send_Num(humidity);
USART1_Send_String("%\r\n");
// 2. 自动除湿逻辑
if(humidity >= HUMI_MAX)
{
GPIO_SetBits(GPIOB, GPIO_Pin_0); // 启动风扇
USART1_Send_String("[除湿] 湿度超标,风扇已开启\r\n");
}
else
{
GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 关闭风扇
USART1_Send_String("[除湿] 湿度正常,风扇已关闭\r\n");
}
}
else
{
USART1_Send_String("[错误] DHT11数据读取失败\r\n");
}
// 3. 防霉UV灯定时控制
uv_timer++;
if(uv_timer >= UV_CYCLE)
{
GPIO_SetBits(GPIOB, GPIO_Pin_1); // 开启UV灯
USART1_Send_String("[防霉] UV杀菌灯已开启\r\n");
Delay_ms(2000); // 杀菌2秒
GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 关闭UV灯
USART1_Send_String("[防霉] UV杀菌灯已关闭\r\n");
uv_timer = 0;
}
// 4. 人体感应照明
human_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1);
if(human_state == 1)
{
GPIO_SetBits(GPIOB, GPIO_Pin_2); // 开启照明
light_timer = 0; // 清零计时器
USART1_Send_String("[照明] 检测到人体,灯已开启\r\n");
}
else
{
light_timer++;
if(light_timer >= LIGHT_DELAY)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_2); // 关闭照明
USART1_Send_String("[照明] 无人活动,灯已关闭\r\n");
light_timer = LIGHT_DELAY;
}
}
Delay_ms(100); // 采样周期100ms
}
}
五、代码深度解析与工程说明
5.1 核心逻辑解析
-
温湿度采集逻辑
DHT11采用单总线通信,主机发送起始信号后,传感器响应并输出40位数据(湿度整数+湿度小数+温度整数+温度小数+校验位)。本项目仅使用整数部分,满足衣柜环境精度需求。
-
除湿控制逻辑
设定湿度阈值60%RH,超过该值说明衣柜内环境潮湿,自动启动风扇加速空气流通;湿度低于阈值时自动关闭,实现节能与自动化。
-
防霉UV灯逻辑
采用周期性工作模式,每30秒开启一次UV灯,持续2秒杀菌,既保证防霉效果,又延长UV灯寿命。
-
人体感应照明逻辑
HC-SR505检测到人体时立即开灯,无人状态下延时5秒关闭,避免频繁开关,提升使用体验。
5.2 零基础编译说明
- 将所有文件添加到Keil5工程目录
- 确保标准库文件完整包含
- 配置晶振为8MHz,编译输出hex文件
- 通过USB-TTL下载器将程序烧录至STM32F103C8T6
- 打开串口调试助手,波特率9600,即可查看系统运行状态
六、故障排查与避坑方案
6.1 DHT11读取失败
- 成因:接线错误、无上下拉电阻、延时函数精度错误
- 解决方案:检查PA0接线,增加10K上拉电阻,使用本文标准延时函数
6.2 风扇/UV灯/LED不工作
- 成因:GPIO输出电平错误、三极管驱动损坏、电源供电不足
- 解决方案:测量GPIO输出电平,更换S8050三极管,保证5V电源电流≥1A
6.3 人体感应误触发/不触发
- 成因:模块灵敏度调节不当、环境干扰
- 解决方案:旋转HC-SR505电位器调节灵敏度,远离金属与磁场环境
6.4 串口乱码
- 成因:波特率不匹配、晶振配置错误
- 解决方案:串口助手设置9600波特率,工程配置8MHz晶振
七、性能优化与工程升级方向
7.1 低功耗优化
- 系统空闲时进入STOP休眠模式
- 传感器采用间断式采集,降低功耗
7.2 功能升级
- 添加OLED屏幕,本地显示温湿度数据
- 接入ESP8266模块,实现WiFi远程监控与控制
- 添加蓝牙模块,支持手机APP控制
7.3 稳定性优化
- 增加数据滤波算法,剔除DHT11异常数据
- 添加外设故障检测,自动报警与保护
八、总结
本文完整实现了基于STM32F103的智能衣柜系统,包含除湿、防霉、照明三大核心功能,所有硬件接线、代码、调试方案均为实战落地版本,零基础开发者可直接复刻。
系统采用模块化设计,代码结构清晰、注释完整、无冗余逻辑,可直接应用于毕业设计、DIY项目、智能家居产品开发。通过本文学习,可快速掌握STM32外设驱动、传感器应用、自动化控制逻辑等核心技能。