这次我们来看一个基于 STM32 的智能绿色风扇设计与实现项目项目编号 mcu-1173定位是单片机毕业设计。所谓“智能绿色”核心不是单纯做一个能转的风扇而是让风扇根据环境温度、人员存在、用户设定三个维度自动工作有人时按温度自动调速没人时定时关闭温度未达到阈值时保持低转速整体上减少无效运行和电量浪费。主控使用 STM32外围涉及温度采集、人体感应、PWM 电机调速、OLED 显示和按键交互覆盖了 GPIO、定时器、ADC、单总线通信、I2C 显示等 STM32 开发中的高频知识点。这种方案放在毕业设计里既能展示嵌入式系统设计能力也容易迁移到智能家居控制类题目上。本文会从需求设计、硬件选型、驱动接线、软件框架、功能验证到常见排错完整拆一遍帮你确认为什么要做、怎么做、做到什么程度可以验收。内容面向准备做 STM32 单片机毕业设计、课程设计和智能小项目的读者如果你正在选型或已经画好板子开始写代码这篇可以直接收藏备用。下面先把整个项目的核心能力整理出来随后分别展开硬件、代码和测试方法。为避免瞎编参数所有涉及型号、接口和引脚的内容都按常见的 STM32 毕业设计方案来组织具体型号和 PCB 接线需要以你手头的开发板或原理图为准。这里的价值在于给你一套完整可执行的实现框架而不是照抄某个固定图纸。1. 项目核心能力概览从功能和工程约束的角度这个智能绿色风扇项目可以先用一张表格快速看清楚项目项说明项目名称基于 STM32 的智能绿色风扇设计与实现项目类型单片机毕业设计 / 嵌入式系统应用设计主控方案以 STM32F103 系列为典型如 STM32F103C8T6开发方式寄存器 / 标准外设库 / STM32 HAL 库均可推荐 HAL 或标准库工程主要功能温度检测、人体感应、自动调速、手动调速、OLED 显示、阈值设定核心执行器5V/12V 直流风扇模块用 PWM 调压或电机驱动板控制输入模块DS18B20 温度传感器、HC-SR501 人体红外感应、独立按键显示模块0.96 寸 I2C OLEDSSD1306节能控制无人强制延时关闭温度区间映射 PWM 占空比工作模式手动模式、自动模式、节能模式供电方式建议使用 USB 5V 或低压直流电源如需控制市电风扇须按强电规范设计适用场景教室、宿舍、办公工位、家用桌面风扇智能化改装、智能家居课程设计平台兼容Keil MDK、STM32CubeMX、IAR也可以配合 VSCode EIDE这里需要明确一点如果毕业设计只要求“能转、能调速、能测温度”这个题目并不算难。真正能拉分的点是“绿色节能”有没有落到控制策略上有没有数据或逻辑支撑。比如同样 35 度环境普通风扇一直全速转而智能风扇在有人且温度刚超过阈值时只给中低占空比人离开后延时 30 秒停止这种细节就是答辩时可以展开讲的亮点。所以整篇文章不只是给接线图还会给一套可解释的控制决策表。2. 系统功能设计与绿色节能策略2.1 功能需求先按毕业设计常用写法把需求拆成功能模块温度采集模块负责感知环境温度。DS18B20 是单总线数字温度传感器测温范围常见为 -55℃ 到 125℃在 10 位精度下分辨率可以到 0.25℃ 左右12 位时更高一些。对风扇控制来说不需要小数点后几位也够用。它的优点是只占用一根 IO 口线接线简单代码上需要处理单总线时序。人体存在检测模块负责判断风扇前方是否有人。HC-SR501 是热释电红外传感器模块输出数字电平检测到人体活动时输出高电平没人时保持低电平。它的缺点是只对“移动的人体”敏感如果人长时间静止模块输出可能会恢复低电平。所以实际控制逻辑里不能把“无人”判断做成瞬时值一般要加“连续无人超过 N 秒才关风扇”的延时策略这个后面代码部分会体现。按键输入模块用来切换手动/自动模式、调整温度阈值。常见的毕业设计会安排 3 个或 4 个独立按键。这个项目我建议至少保留 3 个模式键、温度阈值加、温度阈值减。如果还想增加“定时关闭”“风速循环”功能可以再加键但按键多了会占用 IO逻辑复杂度也会上升第一次做不建议超过 4 个。执行机构是直流风扇。为了安全毕业设计演示建议用 5V 或 12V 的直流风扇通过三极管/MOS 管或 L9110S 驱动板接到 STM32 的 PWM 输出脚。使用时必须注意不是所有直流风扇在 10% 占空比下都能启动电机存在“启动死区”。如果占空比太低风扇可能发出嗡嗡声但不转反而显得不智能。一个常用办法是启动时先给高占空比比如 80%运行 300ms然后回落到目标占空比这个细节能做到程序里答辩时解释起来也很加分。显示模块用 OLED 显示当前模式、温度、设定阈值和 PWM 占空比。OLED 刷屏不能太频繁否则主循环会被 I2C 通信占用大量时间一般 200ms 到 500ms 刷新一次即可。2.2 绿色节能控制决策绿色节能的核心是控制决策表。这里以“温度阈值”和“人体存在”两个输入为例给出一套典型的控制逻辑运行状态 / 条件风扇动作说明无人在场延时计时未到保持当前风速或按设定延时运行防止误关无人在场延时计时结束关闭风扇进入待机避免无人空转有人在且当前温度低于低温阈值风扇停止或最低档环境不热则不吹有人在且温度处于低温阈值与高温阈值之间PWM 占空比按线性或分段映射中低速运行有人在且温度高于高温阈值风扇全速或达到限定高速快速散热手动模式用户按键选择档位忽略温度满足个体需求节能模式无人立即延时关闭有人时限制最高转速最低能耗演示这套表的价值在于它可以让风扇避免“检测到人就开始转、没检测到人立刻停”的抖动问题同时也能让“绿色”这两个字有具体的控制逻辑支撑。自动模式还应该加入迟滞区间。比如设定 28℃ 是打开阈值那么风扇应该在温度升高到 28℃ 时启动但关闭时不是马上低于 28℃ 就停而是低于 26℃ 或无人延时一段时间才停。这样做的好处是防止传感器温度在阈值附近波动时风扇频繁启停对电机寿命和体验都有帮助。2.3 指示灯与提示功能建议项目里增加一个简单状态指示灯或蜂鸣器用于提示模式切换。OC 输出或普通推挽输出 LED 即可。OLED 已经能显示文字但用户看风扇时不一定盯着屏幕所以 RGB LED 三色灯可以更直观红色表示手动高速、蓝色表示自动中速、绿色表示节能待机或风扇关闭。这个小设计会让整个装置看起来更完整也能作为作品展示时的加分点。蜂鸣器如果不是必须可以不接如果接声音要小只做按键和阈值越限提示不要做成持续报警。3. 硬件选型与接线说明3.1 典型器件清单因为毕业设计要以稳定可靠为主器件尽量选淘宝或实验室容易买到的模块以下是一套典型配置器件型号/规格用途主控板STM32F103C8T6 最小系统板控制和数据处理下载器ST-Link V2 或 USB 转 TTL程序下载和串口打印温度传感器DS18B20 防水探头或 TO-92 封装环境温度采集人体感应模块HC-SR501 热释电红外模块人体存在检测显示模块0.96 寸 OLED SSD1306 I2C参数显示风扇5V/12V 直流风扇尺寸按外壳选执行机构驱动方式L9110S 驱动板或 NPN MOS 驱动电路风扇供电与 PWM按键轻触按键 4 个模式切换和阈值设定电源USB 5V / 充电宝 / 稳压模块系统供电指示灯LED 限流电阻模式指示如果非要做 220V 市电风扇的智能插座改造那就需要继电器、隔离电源和强电安全设计不建议在课程设计或毕业设计演示中直接触碰 220V安全隐患很大。文章后面所有接线和控制方案默认都是低压直流风扇。3.2 引脚分配示例下面给出一个常见分配表不代表唯一正确接法因为不同开发板丝印和重映射不一样实际调试时要看原理图。推荐先选好能避开 JTAG/SWD 冲突的引脚再在 CubeMX 里重新映射。模块STM32 引脚建议说明DS18B20 数据PA0开漏输出或普通 GPIO需 4.7k 上拉HC-SR501 OUTPA1输入模式建议内部上拉OLED SCLPB6I2C1 时钟OLED SDAPB7I2C1 数据风扇 PWMPA8TIM1_CH1或 PB0/TIM3_CH3按键 K1PB0模式切换按键 K2PB1阈值加按键 K3PA4阈值减按键 K4PA5手动风速档位循环LED 状态PC13 或 PA6接限流电阻作为通用提醒STM32F103C8T6 的 PB3、PB4、PA13、PA14、PA15 默认和调试下载功能相关如果要用这些引脚必须在 Keil 或 CubeMX 里做重映射和关闭 SWD 复用否则下载一次程序后可能无法再次连接。所以上面示例里尽量避开 PA13/PA14优先使用普通 IO。3.3 电路连接注意事项DS18B20 的数据线要接一个 4.7kΩ 左右的上拉电阻到 3.3V 或 5V。很多成品模块已经集成上拉直接用模块即可。HC-SR501 模块供电一般用 5V输出高电平是 3.3V 还是 5V 取决于模块设计如果输出 5V接入 STM32 GPIO 时要注意电平兼容性稳妥做法是加电阻分压或使用 3.3V 版本模块。OLED 模块 I2C 需要共地SDA/SCL 不要接反。L9110S 驱动板有两路输入只接一路时风扇方向固定PWM 信号加到 IN1 或 IN2另一路接低或接地。由于不同模块的输入端极性设计不完全一样接好以后先在手动模式测试正转再上代码。4. 软件工程搭建与关键代码实现4.1 开发环境准备这套设计可以用 Keil MDK 或者 STM32CubeIDE。毕业设计答辩通常要求给出代码截图和工程结构所以工程目录建议按模块拆开Project/ ├── Core/ │ ├── Inc/ │ └── Src/ ├── Drivers/ ├── Hardware/ │ ├── ds18b20.c/h │ ├── oled.c/h │ └── motor.c/h ├── App/ │ ├── fan_control.c/h │ └── key_scan.c/h └── Docs/如果用 CubeMX先选芯片型号配置时钟树、GPIO、TIM PWM、I2C、USART 等外设然后生成工程。DS18B20 的单总线时序建议不要依赖 HAL 的延时函数太多因为不同优化等级下延时会变化更可靠的做法是用 DWT 或 SysTick 微秒延时函数。对于刚起步的人来说如果不想折腾时序也可以把 DS18B20 换成 AHT20、DHT11 等更简单的传感器或者用 STM32 内部 ADC 读 NTC 热敏电阻。但毕业设计里 DS18B20 更常见代码资料也最多。4.2 主循环状态框架主循环不要全部堆在 main.c 里。这里给出一个功能性框架int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIMx_Init(); MX_I2C1_Init(); OLED_Init(); DS18B20_Init(); Motor_Init(); Key_Init(); uint32_t tick_display 0; uint32_t tick_sensor 0; uint32_t tick_scan 0; while (1) { // 5ms 按键扫描 if (HAL_GetTick() - tick_scan 5) { tick_scan HAL_GetTick(); Key_Scan(); } // 500ms 采样一次温度避免频繁读单总线卡住主循环 if (HAL_GetTick() - tick_sensor 500) { tick_sensor HAL_GetTick(); Temperature_Refresh(); } // 200ms 刷新一次 OLED if (HAL_GetTick() - tick_display 200) { tick_display HAL_GetTick(); Display_Refresh(); } // 根据当前模式执行自动或手动控制 Fan_Task(); } }注意DS18B20 单总线温度转换最长时间在 750ms 左右如果每 500ms 读一次有可能上一次转换还没完成就开始下一次读取。实际代码要区分“发起转换”和“读取结果”两个阶段建议采样周期设在 1s 以上。上面示例只是展示工程组织不是可直接复制的完整驱动。4.3 DS18B20 温度读取示例这里给出一个常用的 DS18B20 驱动示例片段里面用到的是“延时微秒”函数需要你自己实现或移植uint8_t DS18B20_ReadTemp(float *temp) { uint8_t low 0, high 0; int16_t raw 0; if (!DS18B20_Reset()) return 1; // 总线异常 DS18B20_WriteByte(0xCC); // 跳过 ROM DS18B20_WriteByte(0x44); // 启动温度转换 HAL_Delay(10); if (!DS18B20_Reset()) return 2; DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0xBE); // 读取暂存器 low DS18B20_ReadByte(); high DS18B20_ReadByte(); raw (high 8) | low; *temp raw * 0.0625f; return 0; }这个代码把转换等待时间简化成了固定延时实际 DS18B20 在 12 位分辨率下的最大转换时间是 750ms因此更好的方式是在第一次进入循环时发送启动转换命令然后经过 750ms 后再读取读取完成后再立刻启动下一次转换用“流水线”方式避免主循环长时间阻塞。如果觉得解释起来麻烦直接设置 9 位或 10 位分辨率可以缩短转换时间。这也是答辩时老师可能问的问题。4.4 风扇 PWM 控制与占空比映射风扇 PWM 控制最关键的是占空比映射。假设最高温度和用户设定的阈值相关可以做成线性映射也可以做分段映射。下面给出一段相对完整的风扇控制代码#define FAN_STOP 0 #define FAN_LOW 25 #define FAN_MID 55 #define FAN_HIGH 85 void Motor_SetDuty(uint16_t duty) { // duty 范围 0~100对应 CCR 定时器重载值 __HAL_TIM_SET_COMPARE(htimx, TIM_CHANNEL_1, duty); } void Fan_AutoControl(float temperature, uint8_t human) { static uint8_t last_duty FAN_STOP; uint8_t target_duty FAN_STOP; if (!human) { target_duty FAN_STOP; } else if (temperature auto_temp_low) { target_duty FAN_STOP; } else if (temperature auto_temp_high) { target_duty FAN_HIGH; } else { // 温度区间内线性映射 uint16_t step (uint16_t)((FAN_HIGH - FAN_LOW) * 100 / 512); uint16_t dt (uint16_t)((temperature - auto_temp_low) * 100); target_duty FAN_LOW (dt / 512) * step; if (target_duty FAN_HIGH) target_duty FAN_HIGH; if (target_duty FAN_LOW) target_duty FAN_LOW; } // 如果上一时刻是停止而目标转速较高先给一个启动占空比防止启动死区 if (last_duty FAN_STOP target_duty FAN_LOW) { __HAL_TIM_SET_COMPARE(htimx, TIM_CHANNEL_1, 80); HAL_Delay(300); } Motor_SetDuty(target_duty); last_duty target_duty; }这段代码的价值在于说明 PWM 调速不是简单“设定占空比”就结束。要处理启动死区要处理无人关停还要处理温度区间映射。可以按照自己的芯片和驱动板调整占空比范围但要注意TIM 的 ARR 如果设置为 999那么 1% 占空比就是 CCR10变量不要直接往 __HAL_TIM_SET_COMPARE 里传 0~100 范围内的值除非你已经把 ARR 设置为 100 或做了换算。非常常见的错误是占空比传大了导致波形周期完全不对。4.5 按键扫描与模式切换按键扫描建议用“非阻塞读取 GPIO 消抖时间戳”的方式而不是 HAL_Delay 消抖。因为 HAL_Delay 在等待时会卡住其他任务。可以写一个轻量消抖void Key_Scan(void) { if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) GPIO_PIN_RESET) { if (key1_press_tick 0) key1_press_tick HAL_GetTick(); else if (HAL_GetTick() - key1_press_tick 20) { key1_flag 1; key1_press_tick 0; } } else { key1_press_tick 0; } }然后主循环里检测 key1_flag根据当前 mode 切换工作模式。如果做得更精细可以支持“短按”“长按”。但考虑到是单片机毕业设计没必要把所有高级交互都做进来把一个按键逻辑做对、做好比堆一堆不稳定功能要好。这个原则也适用于 OLED 菜单设计。4.6 OLED 显示OLED 显示项目状态时可以使用对应驱动库。需要显示的参数至少包括Mode: Auto Temp: 28.6 C Low: 26 C High: 32 C PWM: 55% Human: YESOLED 刷新不要放在中断里也不用每次调用都全屏清屏。比较好的方式是先清局部区域或使用 DMA 传输但这属于优化不一定在毕设阶段要求。要做的话可以开启 I2C DMA初始化后显示区域数据放缓冲区然后周期性刷新。这里提一句是因为很多人在毕业设计里会遇到“OLED 显示卡顿”“刷新占用大量时间”的问题原因往往是频繁调用清屏函数。5. 功能测试与效果验证由于没有拿到实际运行日志和具体设备环境下面给出一套通用的验证流程。你按这套流程操作基本能从“能编译”推进到“能演示”。5.1 上电前检查先不要急着下载程序。上电前用万用表确认检查项标准说明电源电压3.3V / 5V 正常用万用表测量主控和传感器电源脚地线是否共地各模块 GND 与主控 GND 相连I2C、单总线、PWM 信号都需要共地OLED I2C 地址0x3C 或 0x3D不确定时用 I2C 扫描代码确认DS18B20 上拉电阻数据线对电源有 4.7k 上拉成品模块一般已包含风扇供电使用独立 5V/12V 电源不能从 STM32 3.3V 引脚直接偷电5.2 基础功能测试顺序建议按“显示 - 传感器 - 手动模式 - 自动模式 - 节能逻辑”的顺序逐步验证。第一步烧录最简单的 LED 闪烁和 OLED 显示程序确认芯片和下载链路正常。很多毕业设计一开始直接写完整综合程序结果分不清是传感器坏了还是主控问题这是低效做法。第二步测试 DS18B20。读取到的温度应接近室内温度。如果读出来是 85℃ 或 -55℃通常是 4.7k 上拉缺失、数据引脚接错或延时时序不对。如果能够读到室内温度再用手指捏住 DS18B20观察温度是否能缓慢上升。第三步测试 HC-SR501。模块上电后会有一段稳定时间刚上电时输出可能是高电平等待 10 到 30 秒后再测试。人站在模块前方移动观察输出引脚是否变高人离开后模块经过延时自动恢复低。如果模块一直输出高可能是灵敏度/延时旋钮调得太大或者模块正对空调/热源。第四步测试手动模式。通过按键切换档位风扇转速应从低到高变化。如果低档不转但高档转就在程序里提高最低占空比或者按前文思路加入“启动高占空比后回落”的过程。如果完全不能调速先检查是 GPIO 没有输出 PWM还是驱动板接线不对。用示波器或逻辑分析仪看 PWM 波形是最快的排查方式没有示波器也可以在代码里用串口打印 CCR 值。第五步测试自动模式。设定低温阈值为 25℃高温阈值为 32℃。将 DS18B20 放在空调出风口或者用电吹风加热观察温度到阈值后风扇是否启动。判断成功的标准是人不在时即使温度很高风扇也要关闭或进入待机人出现后在 1~2 秒内风扇自动启动人离开后风扇不应立即停止而应经过设定的延时再停止。5.3 绿色节能效果验证绿色节能不能只看“风扇能停”。要能证明节能效果可以从几个维度记录项目记录方式结果判定无人时耗电电流表串联供电端人离开后观察电流电流应低于有人运行时的 30% 或更低风扇运行时长程序统计电机累计启动时间自动模式应比一直全速运行时间短温度波动响应用加热源靠近 DS18B20 再拿开风扇不会频繁启停手动误操作切换模式和调节阈值OLED 显示与实际动作一致如果条件允许还可以加一个 ACS712 电流传感器把电流值显示到 OLED 上通过串口或蓝牙上传到上位机。这个扩展属于加分项但会增加硬件成本和代码量。如果你的毕设要求偏“控制算法”建议在论文里放多组实验数据相同温度、相同风扇、普通恒速运行与智能自动控制运行下的累计耗电情况对比。6. 数据采集、批量测试与上位机和扩展说明这里要说明一件事很多 AI 本地部署类项目会强调 API 接口和批量任务但这个 STM32 风扇项目本身不是服务端项目没有传统意义上的 HTTP API。不过从毕业设计展示和功能扩展角度它可以扩展出几种与“批量/接口”相似的能力扩展方向实现方式说明串口日志交互STM32 USART 发送字符串上位机用串口助手接收数据上报、结果记录PC 上位机控制Python PyQt / C# 上位机通过串口发送指令按键之外提供远程控制界面ESP8266 Wi-Fi 模块AT 指令或 MQTT 协议接入局域网/云平台手机端查看温度和控制风扇蓝牙模块HC-05 / HC-06 透传近距离手机控制多台风扇节点每台风扇一个 STM32 节点上位机统一管理可以作为“实验室/办公室风扇群控”扩展如果你只需要一个自动开停风扇的单片机项目前面的内容已经够用。但如果你想把完成度拉高串口打印是低成本最好的办法。在代码里加一个串口重定向每隔 1 秒打印一次温度、占空比、当前模式调试和答辩展示都会方便很多。这里给出一个通用串口打印模板#include stdio.h #include usart.h int fputc(int ch, struct __FILE *fp) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 100); return ch; } // 然后在 main 中周期调用 printf(temp%.2f, mode%d, duty%d\r\n, temperature, mode, pwm_duty);注意使用 printf 重定向后如果需要查看打印内容Keil 里要勾选“Use MicroLIB”否则可能无法正确重定向到串口。这个坑很多新手都会遇到。如果不想用 MicroLIB就写一个自己的 log 函数逐字节发送字符串。下面给出一个更通用的发送函数void Debug_SendFloat(const char *name, float value) { char buf[64]; sprintf(buf, %s: %.2f\r\n, name, value); HAL_UART_Transmit(huart1, (uint8_t *)buf, strlen(buf), 100); }7. 资源占用与性能观察毕业设计虽然没有“显存占用”这种概念但单片机的 Flash、RAM、CPU 占用和功耗仍然需要关注。这部分容易被忽略却是最终的评分项。STM32F103C8T6 的 Flash 是 64KBRAM 是 20KB。如果 OLED 全屏使用字符串拼接随手定义一个上百字节的临时数组对一个内存只有 20KB 的单片机来说必须小心。打印日志、格式化浮点数、显示缓冲叠加在一起很容易出现内存不足或栈溢出。建议OLED 显示缓冲如果使用全屏 1KB 或 8KB 缓冲区要看芯片 RAM 够不够。不要在主函数里定义超大局部变量放到 static 或全局数组。浮点运算在 STM32F103 没有硬件 FPUF103 是软件浮点虽不至于不能跑但频繁 printf 和格式化浮点会占 CPU。测量线程任务执行周期用 GPIO 翻转在示波器上观察主循环周期确认传感器读取没有卡死主循环。这个测试方法在嵌入式里代替了看“显存占用”的功能专业度很高。功耗优化可以从几个方向做优化手段做法预期效果降低主频72MHz 改为 64MHz 或 48MHz降低动态功耗空闲时进入低功耗模式无任务时调用 __WFI() 或 STM32 STOP 模式系统功耗下降关闭不用的外设时钟关闭 ADC、USART、I2C 时钟减少外设功耗降低 OLED 刷新频率从 100ms 改为 500ms减少 I2C 总线活动风扇用低占空比待机风扇完全停止而不是低转无风阻、无摩擦损耗这些措施不一定要全部做选一两个实现并在论文中分析即可。不过如果论文标题里有“绿色节能”却没有功耗对比数据最后给老师的印象会弱很多。8. 常见问题与排查方法下面整理一份比较典型的排查表涵盖 DIY 焊接、模块接线、代码下载和运行阶段问题现象可能原因排查方式解决方案程序下载失败BOOT0 状态不对、驱动未安装、芯片锁死按住复位再点击下载检查驱动短接 BOOT0 到 1 再下载重装 ST-Link 驱动板子可下载但 OLED 白屏或花屏I2C 地址错误、引脚接错、供电不足I2C 扫描量 OLED 电源脚改设备地址检查上拉和共地DS18B20 读不出温度上拉缺失、GPIO 模式错误、时序不对示波器/逻辑分析仪抓波形换传感器加 4.7k 上拉延迟函数改用 DWT风扇完全不动PWM 通道没初始化、驱动板供电不足测 IN1/IN2 电平测风扇电源先高电平测试再查定时器初始化风扇能转但不受控一直是最高速GPIO 复用配置错误占空比传错打印 CCR 值检查 ARR 设置换算占空比检查 TIM Channel 配置HC-SR501 无法触发模块稳定时间不够、正对热源、检测距离太近模块断电重启等待 30 秒调整灵敏度旋钮人移动再测试HC-SR501 一直有效延时旋钮调太大、模块收到热气流检查输出电平与人的关系延时调到最小远离空调/暖气自动模式频繁启停缺少迟滞逻辑、温度采样周期太短查看串口温度曲线增加高温-低温迟滞区间如 2℃程序运行一段时间后重启电源电流不够、风扇启动瞬间压降过大万用表量电压跌落风扇单独供电使用大电容OLED 刷新卡顿/温度刷新慢使用了 HAL_Delay 阻塞检查打印时间戳改成非阻塞状态机和定时任务按键偶尔没反应没有消抖、按一次触发多次串口打印按键标志增加 20ms 消抖在人静止不动时风扇停了HC-SR501 对静止人体不敏感确认模块选型改用毫米波雷达人体存在传感器如 LD2410这里的 HC-SR501 问题要特别说明热释电红外传感器本质上是“移动检测”不是严格意义上的“人体存在检测”。人趴在桌子上写代码风扇可能因为没检测到动作自动关闭。如果毕业设计的场景是“智能学习风扇”建议使用 24GHz 毫米波传感器或雷达模块来做人体存在检测虽然贵一些但逻辑更贴合产品需求。如果成本有限就在说明文档里明确传感器工作原理把“无人延时关闭”时间设置成 2 到 5 分钟减少误关困扰。9. 毕业设计文档与工程管理建议如果这个题目最终会写成毕业设计论文或课程设计报告除了代码能跑文档内容也需要覆盖几个点9.1 需求分析部分写清楚“普通风扇有哪些浪费”“智能绿色风扇解决什么问题”不要只写“实现温度检测和自动开关”。问题可以归纳成三方面一是风扇常转不关造成无人空转二是固定风速无法根据温度变化调节三是手动频繁开关不仅麻烦也可能影响风扇寿命。智能系统通过传感器感知环境和人员状态再通过决策逻辑控制风扇运行减少无效功耗这是整套设计的立足点。9.2 硬件设计部分给出系统框图、主控最小系统、传感器接口电路、电机驱动电路。画原理图时注意标注器件型号和参数不要只截图别人的模块。在论文里可以用方框图表示系统组成STM32 作为主控左边是输入设备右边是输出设备下面画电源。模块化框图在答辩 PPT 里非常直观。[温度传感器 DS18B20] ---- 单总线 --- | [人体感应 HC-SR501] ---- GPIO ------- [STM32 主控] -- PWM -- [风扇驱动/风扇] | -- [按键输入] ---- GPIO ------ I2C | -- [电源模块] ---- 供电 ------ [OLED 显示]注意这里只是用文本示意系统结构论文里最好画成规范框图。9.3 软件设计部分可以画出主程序流程图但要注意论文中插入大量源代码并不一定加分核心代码和关键注释放一部分即可重点写控制逻辑和决策表。答辩时老师会问的往往是“为什么这样设计”“如果出现某情况怎么办”而不是每行代码什么意思。答辩高频问题可以提前准备为什么选 STM32F103而不是 51 或 Arduino为什么选 DS18B20和热敏电阻方案有什么区别热释电传感器存在什么局限如何规避PWM 调速频率选多少为什么听不到噪音风扇电机和单片机如何隔离系统的绿色节能体现在哪里如果人坐在风扇前不动系统会怎样是否满足“存在检测”需求对于第 4 个问题PWM 频率一般选择 20kHz 以上可以超过人耳听觉范围但普通直流风扇电机对高频 PWM 响应可能变差很多电动风扇驱动频率在 1kHz 到 25kHz 之间。实际调试时需要听噪音、看转速选定一个合适频率。如果让老师试听时风扇有明显高频啸叫会是很尴尬的演示效果。10. 总结与下一步扩展基于 STM32 的智能绿色风扇项目硬件结构并不复杂核心是控制逻辑和节能策略。做这个毕设时不用一上来追求 321 个功能先把底层驱动打通DS18B20 能读到准确温度OLED 能显示状态按键能切换模式PWM 能控制风扇然后再叠加自动决策逻辑。整个系统的可行顺序是手动模式验证电机自动模式验证温度阈值节能模式验证无人关停。最容易踩的坑集中在几个方面一是风扇低压档不转本质是启动死区需要在高档启动后回落二是 HC-SR501 对静止人体不敏感导致无人判断频繁出现三是 DS18B20 读温度时阻塞主循环影响了按键响应和显示刷新四是按键和高频中断逻辑没加消抖显示状态跳变让人误以为代码有 bug。如果你打算在这个项目上继续扩展可以考虑两个方向。硬件方向是把普通直流风扇换成带霍尔测速的 4 线 PWM 风扇通过 STM32 定时器输入捕获读取转速形成闭环控制让目标转速更准确。软件方向是接入 ESP8266 或蓝牙模块把温度、模式、转速上传到手机小程序实现远程控制和数据记录。这两个方向都是从“演示样机”走向“产品原型”的自然延伸。最后提醒一句如果在宿舍或实验室使用 220V 市电风扇做改装务必注意用电安全方案要增加保护隔离论文和演示阶段建议优先使用低压直流风扇。合理控制、合法用电、规范接线这个设计才算完整。本文提到的所有代码、引脚分配和测试流程都是通用设计模板实际调试时必须根据你选用的 STM32 型号、开发板原理图和传感器模块修改。建议你收藏这份思路真正动手前先从点亮一块 OLED、读取一次温度开始逐步把小模块拼成完整系统。这样即使中途出问题也能很快定位到是哪一级没有打通。