这次我们来做一个基于STM32的智能定时风扇项目。这个设计结合了STM32微控制器、OLED显示屏和PWM调速技术,能够实现风扇的智能定时控制和无级调速功能。对于想要学习嵌入式系统开发、PWM控制原理以及实际项目应用的开发者来说,这是一个很好的实战案例。
智能定时风扇的核心功能包括:通过STM32的定时器生成PWM信号控制风扇转速,使用OLED显示屏实时显示当前状态和设置参数,支持多档定时设置和手动调速模式。整个系统硬件成本低,代码结构清晰,适合作为STM32入门到进阶的练习项目。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 主控芯片 | STM32F103C8T6(兼容其他STM32F1系列) |
| 显示模块 | 0.96寸OLED显示屏(I2C接口) |
| 调速方式 | PWM无级调速(支持4线风扇) |
| 定时功能 | 多档可调定时(1-120分钟) |
| 控制方式 | 按键输入+旋转编码器 |
| 开发环境 | Keil MDK-ARM + STM32CubeMX |
| 供电要求 | 5V/2A电源适配器 |
| 适合场景 | 学习PWM控制、嵌入式UI设计、定时器应用 |
2. 适用场景与使用边界
这个智能定时风扇项目主要适合以下场景:
学习应用场景:
- STM32入门开发者学习GPIO、定时器、PWM、I2C等外设使用
- 嵌入式UI设计实践,掌握OLED菜单显示和用户交互
- PWM控制原理的实际应用,理解占空比与转速关系
- 定时器中断编程,实现精准的时间控制
实际使用场景:
- 桌面小风扇的智能控制
- 需要定时关闭的通风设备
- 实验室环境的风速可调装置
- 物联网设备的原型验证
使用边界提醒:
- 本项目驱动的是小型直流风扇(通常5-12V),不能直接控制大功率电机
- OLED显示在强光下可视性较差,适合室内使用
- 定时精度受STM32内部时钟精度影响,需要高精度定时时应使用外部晶振
- PWM频率需要匹配风扇电机特性,过高或过低都可能影响控制效果
3. 环境准备与前置条件
3.1 硬件准备清单
核心控制器:
- STM32F103C8T6最小系统板(蓝色药丸板)
- ST-Link V2调试下载器
显示模块:
- 0.96寸OLED显示屏(SSD1306驱动,I2C接口)
- 4针I2C接口线(VCC、GND、SCL、SDA)
执行部件:
- 5V或12V直流风扇(建议使用4线PWM风扇)
- MOSFET驱动模块(如IRF520模块)
- 散热片(根据风扇功率选配)
输入设备:
- 旋转编码器(带按键功能)
- 轻触按键(备用方案)
电源系统:
- 5V/2A电源适配器
- DC电源接口
- 杜邦线若干
3.2 软件环境准备
开发工具:
- Keil MDK-ARM(建议V5.25以上版本)
- STM32CubeMX(最新版本)
- ST-Link Utility(用于固件下载)
驱动安装:
- ST-Link V2驱动程序
- CH340串口驱动(如需串口调试)
库文件准备:
- STM32F1xx HAL库
- SSD1306 OLED驱动库
- 旋转编码器处理库
4. 硬件连接与电路设计
4.1 核心控制器引脚分配
// STM32F103C8T6引脚定义 #define OLED_SDA_PIN GPIO_PIN_7 // PB7 - I2C1 SDA #define OLED_SCL_PIN GPIO_PIN_6 // PB6 - I2C1 SCL #define FAN_PWM_PIN GPIO_PIN_0 // PA0 - TIM2_CH1 #define ENCODER_A_PIN GPIO_PIN_1 // PA1 - 编码器A相 #define ENCODER_B_PIN GPIO_PIN_2 // PA2 - 编码器B相 #define ENCODER_BTN_PIN GPIO_PIN_3 // PA3 - 编码器按键4.2 电路连接示意图
电源部分:
5V电源 → STM32 VCC (5V) → 风扇正极 → OLED VCC GND → STM32 GND → 风扇负极 → OLED GND → MOSFET源极信号连接:
STM32 PA0 (PWM) → MOSFET栅极 STM32 PB6 (SCL) → OLED SCL STM32 PB7 (SDA) → OLED SDA STM32 PA1,PA2,PA3 → 编码器A,B,按键 MOSFET漏极 → 风扇PWM控制线4.3 重要注意事项
- 电平匹配:STM32是3.3V系统,直接驱动5V OLED需要确认模块支持3.3V
- 电流要求:风扇电机启动电流较大,确保电源能提供足够电流
- PWM频率:风扇PWM频率通常在25kHz左右,需要设置合适的定时器分频
- 滤波电路:在PWM输出端可加入RC滤波,提高信号质量
5. 软件架构与代码实现
5.1 工程结构设计
SmartFan/ ├── Core/ │ ├── Src/ │ │ ├── main.c │ │ ├── stm32f1xx_hal_msp.c │ │ └── stm32f1xx_it.c │ └── Inc/ │ ├── main.h │ └── stm32f1xx_it.h ├── Drivers/ │ └── STM32F1xx_HAL_Driver/ ├── OLED/ │ ├── oled.c │ └── oled.h ├── PWM/ │ ├── pwm.c │ └── pwm.h └── Encoder/ ├── encoder.c └── encoder.h5.2 核心功能模块代码
PWM初始化配置:
// pwm.c void PWM_Init(void) { TIM_HandleTypeDef htim2; TIM_OC_InitTypeDef sConfigOC; // 定时器基础配置 htim2.Instance = TIM2; htim2.Init.Prescaler = 71; // 72MHz/72 = 1MHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 39999; // 1MHz/40000 = 25Hz htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim2); // PWM通道配置 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 20000; // 50%占空比 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); // 启动PWM HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); }OLED显示界面:
// oled.c void OLED_ShowFanStatus(uint8_t speed, uint16_t remaining_time, uint8_t mode) { OLED_Clear(); OLED_ShowString(0, 0, "Smart Fan", 16); // 显示转速 OLED_ShowString(0, 2, "Speed:", 16); OLED_ShowNum(48, 2, speed, 3, 16); OLED_ShowString(72, 2, "%", 16); // 显示进度条 OLED_DrawProgressBar(0, 4, speed); // 显示剩余时间 OLED_ShowString(0, 6, "Time:", 16); if(remaining_time > 0) { OLED_ShowNum(40, 6, remaining_time/60, 2, 16); OLED_ShowString(56, 6, "m", 16); OLED_ShowNum(72, 6, remaining_time%60, 2, 16); OLED_ShowString(88, 6, "s", 16); } else { OLED_ShowString(40, 6, "OFF", 16); } }旋转编码器处理:
// encoder.c int8_t Encoder_Scan(void) { static uint8_t last_state = 0; uint8_t current_state = (HAL_GPIO_ReadPin(ENCODER_A_GPIO_Port, ENCODER_A_Pin) << 1) | HAL_GPIO_ReadPin(ENCODER_B_GPIO_Port, ENCODER_B_Pin); // 编码器状态机 if(last_state == 0x00) { if(current_state == 0x02) return 1; // 正转 if(current_state == 0x01) return -1; // 反转 } last_state = current_state; return 0; }6. 功能测试与效果验证
6.1 PWM调速功能测试
测试目的:验证PWM信号能否正确控制风扇转速
测试步骤:
- 编译下载程序到STM32
- 用示波器测量PA0引脚波形
- 观察PWM频率是否为25kHz
- 改变占空比,观察风扇转速变化
- 测试0%、25%、50%、75%、100%五个档位
预期结果:
- PWM频率稳定在25kHz±5%
- 占空比从0%到100%线性变化
- 风扇转速随占空比增加而提高
- 0%占空比时风扇完全停止
常见问题:
- 频率不正确:检查定时器分频系数计算
- 无输出:检查GPIO配置和定时器使能
- 风扇不转:检查MOSFET连接和电源
6.2 定时功能测试
测试目的:验证定时关闭功能是否准确
测试步骤:
- 设置1分钟定时
- 启动风扇,开始计时
- 观察OLED显示倒计时
- 时间到后检查风扇是否自动关闭
- 测试5分钟、30分钟等不同时长
预期结果:
- 定时精度误差小于±1秒/分钟
- 时间到后风扇自动停止
- OLED显示实时更新
- 可中途取消定时
6.3 OLED显示测试
测试目的:验证用户界面显示正常
测试步骤:
- 上电检查OLED是否正常初始化
- 旋转编码器,观察菜单切换
- 测试所有显示页面
- 检查字符显示是否清晰
- 测试长时间显示有无残影
预期结果:
- 上电后显示欢迎界面
- 菜单切换流畅无闪烁
- 所有字符显示清晰
- 无显示残影问题
7. 系统优化与性能提升
7.1 功耗优化策略
动态频率调整:
// 根据系统负载调整CPU频率 void SystemClock_Config_Optimized(void) { // 正常模式:72MHz // 低速模式:8MHz(待机时) // 睡眠模式:更低功耗 }外设电源管理:
- 不使用时关闭OLED背光
- 定时器在无PWM输出时进入低功耗模式
- 使用STM32的停机模式降低待机功耗
7.2 控制算法优化
PID转速控制:
// pid.c typedef struct { float Kp, Ki, Kd; float integral; float prev_error; } PID_Controller; float PID_Update(PID_Controller* pid, float setpoint, float actual) { float error = setpoint - actual; pid->integral += error; float derivative = error - pid->prev_error; float output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; pid->prev_error = error; return output; }转速平滑过渡:
- 避免转速突变导致电流冲击
- 实现软启动和软停止功能
- 加入转速变化率限制
8. 常见问题与排查方法
8.1 硬件连接问题
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| OLED不显示 | 电源接反、I2C地址错误 | 检查VCC/GND、测量I2C信号 | 确认3.3V供电,调整I2C地址 |
| 风扇不转 | MOSFET损坏、PWM无输出 | 测量栅极电压、检查PWM波形 | 更换MOSFET,检查GPIO配置 |
| 编码器无反应 | 引脚接触不良、上拉电阻 | 检查接线、测量引脚电平 | 添加上拉电阻,重新焊接 |
| 系统重启 | 电源电流不足 | 测量工作电流 | 更换更大功率电源 |
8.2 软件调试问题
PWM输出异常:
- 现象:频率不正确或占空比不对
- 排查:检查定时器分频系数和重载值计算
- 解决:使用STM32CubeMX重新生成配置
I2C通信失败:
- 现象:OLED无法初始化
- 排查:用逻辑分析仪抓取I2C波形
- 解决:调整I2C时钟速度,检查从机地址
定时器中断冲突:
- 现象:系统卡死或运行异常
- 排查:检查中断优先级配置
- 解决:合理分配中断优先级,避免嵌套过深
8.3 性能优化问题
风扇转速波动:
- 原因:电源纹波大或PWM频率不合适
- 解决:增加电源滤波电容,调整PWM频率
按键响应迟钝:
- 原因:消抖算法过于保守或主循环阻塞
- 解决:优化消抖参数,使用中断处理编码器
显示刷新慢:
- 原因:OLED全屏刷新耗时过长
- 解决:使用局部刷新,优化显示算法
9. 扩展功能与进阶应用
9.1 无线控制扩展
蓝牙模块接入:
// 通过HC-05蓝牙模块接收手机控制指令 void Bluetooth_Control_Handler(uint8_t* data) { switch(data[0]) { case 'S': // 设置转速 SetFanSpeed(data[1]); break; case 'T': // 设置定时 SetTimer(data[1] * 60); break; case 'M': // 模式切换 SwitchMode(data[1]); break; } }Wi-Fi远程控制:
- 使用ESP8266模块实现联网功能
- 通过MQTT协议接入智能家居系统
- 支持手机APP远程控制
9.2 环境感知扩展
温度传感器集成:
// 使用DS18B20检测环境温度 void Temperature_Control(void) { float temp = DS18B20_ReadTemp(); if(temp > 30.0f) { SetFanSpeed(80); // 高温自动加速 } else if(temp < 25.0f) { SetFanSpeed(30); // 低温自动减速 } }湿度检测功能:
- 添加DHT11/DHT22湿度传感器
- 实现基于温湿度的智能控制策略
- 支持除湿模式自动开启
9.3 数据记录与分析
运行数据存储:
// 使用EEPROM记录运行统计 typedef struct { uint32_t total_runtime; uint16_t start_count; uint8_t max_speed; uint8_t avg_speed; } Fan_Statistics; void Save_Statistics(void) { // 定期保存到EEPROM EEPROM_Write(STATS_ADDR, &stats, sizeof(stats)); }能耗统计功能:
- 基于转速估算功耗
- 统计每日/每月用电量
- 提供节能建议
10. 项目总结与进阶方向
这个基于STM32的智能定时风扇项目涵盖了嵌入式开发的多个重要知识点。通过实际动手实现,可以深入理解PWM控制原理、定时器应用、I2C通信协议以及用户界面设计。
最值得尝试的优化:
- 首先验证PWM控制是否稳定,这是整个系统的基础
- 完善用户交互体验,让操作更加直观流畅
- 加入软启动功能,延长风扇电机寿命
最容易踩的坑:
- PWM频率设置不当导致风扇异响
- I2C地址配置错误使OLED无法显示
- 电源功率不足引起系统不稳定
后续扩展方向:
- 移植到其他STM32系列芯片,学习不同型号的特性差异
- 加入FreeRTOS实现多任务管理,提升系统可靠性
- 开发配套的手机APP,实践物联网应用开发
- 优化控制算法,实现更精准的转速和温度控制
这个项目代码结构清晰,模块化程度高,非常适合作为STM32学习的实战案例。建议在基本功能实现后,根据自己的需求继续添加新功能,不断提升嵌入式开发能力。