基于STM32的智能温控风扇系统:从硬件选型到软件实现的完整开源项目
在智能家居和物联网应用蓬勃发展的今天,一个低成本、高集成度的本地温控解决方案具有重要的实践价值。本文深入解析一个以STM32单片机为核心的智能温控风扇系统开源项目,涵盖其设计思路、硬件架构、软件流程及扩展潜力,为嵌入式开发者、电子爱好者及创客提供一个完整的参考实现。
一、项目背景与设计目标:解决传统温控方案的痛点
当前温控风扇市场存在明显的两极分化。一方面,高端商用系统功能齐全但价格昂贵、部署复杂,难以进入普通家庭、宿舍或小型商铺;另一方面,基础款风扇功能单一,缺乏智能响应与数据联动能力。本项目旨在填补这一市场空白,设计一个兼具高性价比、智能化与良好扩展性的解决方案。
核心设计目标包括:实现环境温度的精准监测与自动响应;支持手动、自动、定时等多种工作模式;集成本地显示与远程控制(如Wi-Fi);具备异常状态提醒功能。通过模块化设计,系统为后续功能升级(如接入更复杂的云平台或与其他智能设备联动)预留了充足空间。
二、系统核心硬件架构与模块选型
本系统的硬件核心是意法半导体的STM32F103C8T6微控制器,它基于ARM Cortex-M3内核,具有丰富的外设和较高的性价比,非常适合此类控制应用。
围绕主控,系统集成了多个功能模块,构成了完整的感知-决策-执行链条:
- 感知层:DHT11温湿度传感器负责采集环境数据;SR501红外人体感应模块检测区域内是否有人,实现“人在送风”的节能逻辑。
- 决策与交互层:OLED显示屏用于实时显示所有关键参数;独立按键用于模式切换与参数设置;声光报警模块用于状态提示。
- 执行层:TB6612电机驱动模块负责驱动风扇电机,实现多档位无级或有级调速。
- 通信层:Wi-Fi模块(如ESP8266)使得系统能够接入局域网,实现手机APP远程监控与控制。
这种清晰的模块化划分,不仅降低了调试难度,也使得开发者可以轻松替换或升级某一模块(例如,将DHT11更换为更精确的DS18B20或SHT30)。
[AFFILIATE_SLOT_1]三、软件设计流程与核心逻辑
系统的软件设计采用了经典的前后台(超级循环)架构,逻辑清晰,易于理解和维护。主程序流程图清晰地展示了整个系统的运行脉络:

如上图所示,系统上电初始化后,便进入主循环。循环内依次执行:传感器数据采集、按键扫描与处理、工作模式逻辑判断、电机控制输出、显示刷新以及通信处理等任务。这种轮询方式保证了各功能模块都能得到及时响应。
工作模式是系统的逻辑核心:
- 自动模式:系统比较当前温度与设定阈值,并结合人体感应结果,自动控制风扇启停与档位。
- 手动模式:用户通过按键直接控制风扇档位,适用于有明确需求的场景。
- 定时模式:设置风扇运行时长,倒计时结束后自动关闭,兼顾便利与节能。
主函数代码框架展示了如何组织这些逻辑,其清晰的结构对于学习嵌入式开发有很好的示范作用。
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
Motor_Init();
DHT11_Init();
MatrixKey_Init();
Red_Init();
Timer_Init();
Serial_Init();
BEEP_GPIO_Config();
OLED_ShowChinese(0,0,"温度");
OLED_ShowChinese(16*4,0,"湿度");
OLED_ShowChinese(0,16,"模式");
OLED_ShowChinese(16*4,16,"档数");
OLED_ShowNum(16*2,16,Key_M,1,OLED_8X16);
OLED_ShowNum(16*6,16,dang,1,OLED_8X16);
OLED_ShowChinese(0,16*2,"速度:");
OLED_ShowSignedNum(16*3,16*2,Speed,3,OLED_8X16);
OLED_ShowChinese(0,16*3,"倒计时:");
OLED_ShowNum(16*4,16*3,Time,2,OLED_8X16);
OLED_Update();
GPIO_SetBits(GPIOB, GPIO_Pin_0);
GPIO_SetBits(GPIOB, GPIO_Pin_1);
Delay_ms(100);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
GPIO_ResetBits(GPIOB, GPIO_Pin_1);
while (1)
{
DHT11_Read_Data(&TH,&RH);//获取当前温湿度
OLED_ShowNum(16*2,0,TH,2,OLED_8X16);
OLED_ShowNum(16*6,0,RH,2,OLED_8X16);
OLED_Update();
if(Timedemo == 1)
{
if(RED_Data == 1) //如果有人
{
OLED_ShowString(16*6,16*2,"Hi! ",OLED_8X16);
if(temperature < TH) //实际温度高于设置阈值
{
Speed = (TH-temperature)*20; //每高一度速度+20
if(Speed > 100)
{
Speed = 100;
}
}
else Speed = 0;
}
else
{
OLED_ShowString(16*6,16*2,"Bey!",OLED_8X16);
Speed = 0;
}
OLED_ShowSignedNum(16*3,16*2,Speed,3,OLED_8X16);
OLED_Update();
Motor_SetSpeed(Speed);
}
Delay_ms(500);
}
}
uint16_t count;
uint8_t yy;
void TIM1_UP_IRQHandler(void) //每1毫秒进一次中断
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET)
{
count++;
if(count == 1000)
{
count = 0;
if(Time_demo == 0 && Time > 0) //进入倒计时模式
{
Time--;
if(Time == 0) //倒计时结束
{
Timedemo = 0; //关闭自动挡
Speed = 0; //速度置0
dang = 0; //去除记录
Time_1 = 0;
Time_10 = 0;
Motor_SetSpeed(0);
OLED_ShowSignedNum(16*3,16*2,Speed,3,OLED_8X16);
OLED_ShowNum(16*6,16*1,dang,1,OLED_8X16);
}
OLED_ShowNum(16*4,16*3,Time,2,OLED_8X16);
OLED_Update();
}
}
if(count%20 == 0) //获取按键值
{
RED_Data = Red_Rdata(); //检测是否有人
if(RxData) //
{
KeyNum = RxData-'0';//
RxData = 0;
// OLED_ShowNum(16*6,16*3,KeyNum,2,OLED_8X16);
// OLED_Update();
}
else
{
KeyNum = Key_LoopY();
}
if(KeyNum) //如果按键按下
{
if(KeyNum == 3) //切换模式键 Key_M = 1:手动,Key_M = 2:自动
{
Num = 1; //手动自动模式
Key_M += 1;
if(Key_M > 2){Key_M = 1;}
OLED_ShowNum(16*2,16,Key_M,1,OLED_8X16);
OLED_Update();
}
if(Num == 1) //手动自动模式
{
if(Key_M == 1) //模式1手动挡模式
{
Timedemo = 0;
OLED_ClearArea(16*3,16,16*8,16);
OLED_ShowChinese(16*4,16,"档数");
if (KeyNum == 1) //减档
{
dang--;
if(dang < 0)
{
dang = 5;
}
}
if (KeyNum == 2) //加档
{
dang++;
if(dang > 5)
{
dang = 0;
}
}
Speed = dang*20;
OLED_ShowString(16*6,16*2," ",OLED_8X16);
OLED_ShowNum(16*6,16*1,dang,1,OLED_8X16);
OLED_ShowSignedNum(16*3,16*2,Speed,3,OLED_8X16);
OLED_Update();
Motor_SetSpeed(Speed);
}
if(Key_M == 2)
{
Timedemo = 1;
dang = 0;
OLED_ClearArea(16*3,16,16*8,16);
OLED_ShowChinese(16*4,16,"阈值");
if (KeyNum == 1) //温度阈值--
{
temperature--;
if(temperature < 16)
{
temperature = 16;
}
}
if (KeyNum == 2) //温度阈值++
{
temperature++;
if(temperature > 40)
{
temperature = 40;
}
}
OLED_ShowNum(16*6,16*1,temperature,2,OLED_8X16);
OLED_Update();
}
}
if(KeyNum == 4) //切换倒计时模式
{
Num = 2;
Time_demo++;
if(Time_demo == 2) //Time_demo=2相当于确定键
{
Num = 1;
Time_demo = 0;
OLED_ShowString(16*5+8,16*3," ",OLED_8X16);
OLED_Update();
}
}
if(Num == 2)
{
if(Time_demo == 1) //输入需要倒计时的时间
{
if(KeyNum == 1)
{
Time_10++;
if(Time_10 > 9)
{
Time_10 = 0;
}
}
if(KeyNum == 2)
{
Time_1++;
if(Time_1 > 9)
{
Time_1 = 0;
}
}
Time = Time_10*10 + Time_1;
OLED_ShowNum(16*4,16*3,Time,2,OLED_8X16);
OLED_ShowString(16*5+8,16*3,"<-",OLED_8X16);
OLED_Update();
}
}
}
}
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
四、实物成果与关键细节展示
项目的成功最终体现在稳定运行的实物上。以下视频和图片展示了系统的实际工作状态:
演示视频链接:https://www.bilibili.com/video/BV1tHWgzHEws/
从实物图中可以看到,所有模块通过杜邦线有序连接,OLED屏幕清晰地显示着温度、湿度、模式、档位等信息。PCB设计图则反映了将原理图转化为可生产电路的关键一步,合理的布局布线是系统稳定性的基础。


五、项目总结与扩展思考
本项目完整地演示了一个典型嵌入式系统产品的开发流程:从需求分析、硬件选型、电路设计、PCB绘制,到软件编程、调试和最终实现。它不仅是一个可用的温控风扇方案,更是一个优秀的STM32学习与实践平台。
扩展方向:此系统的架构具有很强的可扩展性。开发者可以尝试:
- 增加更多传感器,如PM2.5或CO2传感器,打造空气质量管理系统。
- 将Wi-Fi模块升级为蓝牙,或同时集成多种通信方式。
- 开发更精美的手机APP或微信小程序进行控制。
- 将控制逻辑移植到其他平台,例如用Python在树莓派上实现更复杂的算法,或用JavaScript构建Node.js后端服务进行数据记录与分析。对于追求性能的联网应用,Go语言也是后端开发的优秀选择。而原始的嵌入式C代码,其思想与C++或Java在面向对象设计上也有相通之处。
项目的全部资料,包括原理图、PCB文件、源代码等均已开源,为学习和二次开发提供了极大便利。
[AFFILIATE_SLOT_2]
总而言之,这个STM32智能温控风扇项目巧妙地平衡了成本、功能与复杂性,是入门物联网和嵌入式开发的绝佳案例。通过复现和改进该项目,开发者能够深入理解传感器应用、电机控制、人机交互及无线通信等关键技术,为开发更复杂的智能硬件产品打下坚实基础。
浙公网安备 33010602011771号