目录
[PCB图 编辑编辑](#PCB图 编辑编辑)
一、前言
项目成品图片:

(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的智能风扇(机智云)
功能如下:
- 环境采集:采集环境温湿度、有无人
- 显示功能:OLED显示当前环境温度、环境湿度、是否有人和倒计时时间
- 模式切换:通过按键可以切换手动模式和自动模式
- 自动模式:当有人并且环境温度大于温度下限时开启风扇一档风速,温度大于温度平均值时开启风扇二档风速,温度大于温度上限时开启风扇三档风速并开启蜂鸣器报警;当定时模式开启的状态下有人且风扇开启即开启倒计时,倒计时清零时风扇关闭
- 手动模式:可以手动控制灯光和风扇档位(关、一档、二档、三档),风扇开启后可以控制摇头开关
- 阈值调节:可通过按键设置温度上限、温度下限、定时时间(时分秒)、定时功能(开/关)
- 机智云APP:通过WIFI连接机智云APP,APP可以接收环境信息数据、模式切换、手动模式下控制照明和风速,可修改温度阈值
2.主要器件
- STM32F103C8T6最小系统板
- OLED显示屏(4针IIC协议)
- DHT11温湿度传感器
- 光电红外传感器
- ESP8266-01S(WIFI模块)
- TB6612电机驱动模块
- 步进电机
- 风扇
- 蜂鸣器
- LED灯
三、原理图设计

四、PCB硬件设计
PCB图 

五、程序设计
cpp
#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "usart.h"
#include "delay.h"
#include "dht11.h"
#include "oled.h"
#include "key.h"
#include "Modules.h"
#include "TIM2.h"
#include "adcx.h"
#include "flash.h"
#include "Motor.h"
#include "HW.h"
#include "usart2.h"
#include "stepmotor.h"
#include "TIM3.h"
#include "gizwits_product.h"
#include "gizwits_protocol.h"
/****************异方辰电子工作室******************
STM32
* 项目 : STM32智能风扇
* 版本 : V2.0
* 日期 : 2025.7.13
* MCU : STM32F103C8T6
* 接口 : 见代码
* IP账号 : 异方辰电子/辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
* 作者 : 辰哥
* 工作室 : 异方辰电子工作室
* 授权IP : 辰哥单片机设计、异方辰电子、YFC电子、异方辰系列
* 官方网站 : www.yfcdz.cn
**********************BEGIN***********************/
// 按键功能宏定义
#define KEY_Long1 11 // 按键1长按(功能:自动模式 → 设置模式)
#define KEY_1 1 // 按键1短按(功能:自动模式 → 手动模式)
#define KEY_2 2 // 按键2(功能:菜单页面切换/光标移动)
#define KEY_3 3 // 按键3(功能:参数增加/设备开启)
#define KEY_4 4 // 按键4(功能:参数减少/设备关闭)
// Flash存储起始地址:用于保存传感器阈值参数(掉电不丢失)
#define FLASH_START_ADDR 0x0801f000
// 模式定义
#define AUTO_MODE 1 // 自动模式
#define MANUAL_MODE 2 // 手动模式
#define SETTINGS_MODE 3 // 设置模式
// 外部变量声明
//extern u8 data; // 蓝牙数据
extern uint8_t zt_flag;
extern uint8_t one_second_flag;
// 结构体变量声明
SensorModules sensorData; // 声明传感器数据结构体变量
SensorThresholdValue Sensorthreshold; // 声明传感器阈值结构体变量
DriveModules driveData; // 声明驱动器状态结构体变量
// 系统核心全局变量
uint8_t mode = AUTO_MODE; // 系统模式控制:1=自动模式,2=手动模式,3=设置模式
// 模式内部状态变量
static uint8_t auto_page = 1; // 自动模式页面:1=第一页,2=第二页
uint8_t count_m = 1; // 手动模式按键计数:记录当前选中的控制项
static uint8_t count_s = 1; // 设置模式按键计数:记录当前选中的阈值项
static uint8_t is_secondary_menu = 0; // 0一级菜单,1二级菜单
static uint8_t secondary_pos = 1; // 二级菜单光标位置(1-3对应时/分/秒)
static uint8_t last_secondary_pos = 0; // 记录上次光标位置
static uint8_t last_hour = 0xFF, last_minute = 0xFF, last_second = 0xFF; // 记录上次时间值
static uint8_t secondary_initialized = 0; // 二级菜单初始化标记
static uint8_t timer_start_flag = 0; // 倒计时开始标志,1=开始倒计时,0=停止
static uint8_t force_fan_on = 0; // 强制风扇开启标志
void OLED_manualPage1(void);
void OLED_manualOption(uint8_t num);
void ManualSettingsDisplay1(void);
/**
* @brief 主函数(系统入口)
* @note 初始化硬件→读取Flash阈值→主循环
* @param 无
* @retval 无
*/
int main(void)
{
SystemInit(); // 配置系统时钟为72M
delay_init(72);
ADCX_Init();
LED_Init();
LED_On();
Key_Init();
OLED_Init();
DHT11_Init();
OLED_Clear();
BEEP_Init();
MOTOR_Init();
MOTORE_Init();
HW_Init();
TIM2_Init(); ;
USART1_Config(); // 串口初始化
USART2_Config(); // 蓝牙串口初始化
FLASH_ReadThreshold();
delay_ms(1000);
OLED_Clear();
// 静态变量用于记录模式内状态
static uint8_t last_mode = 0; // 记录上一次的系统模式
static uint32_t last_sensor_time = 0; // 传感器扫描时间戳
TIM4_Init(1000-1, 72-1);
userInit(); // 机智云用户初始化(数据点初始化等)
gizwitsInit(); // 机智云协议初始化(WiFi配网、数据通信初始化)
gizwitsSetMode(WIFI_AIRLINK_MODE); //默认一键配网
delay_ms(200);
printf("Start \n");
gizwitsHandle((dataPoint_t *)¤tDataPoint);
ScanGizwitsMode();
delay_ms(200);
while (1)
{
gizwitsHandle((dataPoint_t *)¤tDataPoint);
// 获取当前系统时间
uint32_t current_time = delay_get_tick();
// 优化传感器扫描频率:每200ms扫描一次
if(current_time - last_sensor_time > 200)
{
SensorScan(); // 获取传感器数据
last_sensor_time = current_time;
}
// 立即处理按键
uint8_t current_key_num = KeyNum;
// 模式切换按键立即处理
if(current_key_num != 0)
{
switch(mode)
{
case AUTO_MODE:
if(current_key_num == KEY_1) // 短按KEY1:自动模式→手动模式
{
mode = MANUAL_MODE;
count_m = 1;
// 如果定时开启,风扇保持开启状态
if (Sensorthreshold.timing == 1)
{
// 定时开启时,切换到手动模式保持风扇开启
if (driveData.Fan_Flag == 0)
driveData.Fan_Flag = 1;
}
else
{
driveData.Fan_Flag = 0;
}
driveData.LED_Flag = 0;
KeyNum = 0;
}
else if(current_key_num == KEY_Long1) // 长按KEY1:自动模式→设置模式
{
mode = SETTINGS_MODE;
count_s = 1;
KeyNum = 0;
}
break;
case MANUAL_MODE:
if(current_key_num == KEY_1) // 短按KEY1:手动模式→自动模式
{
mode = AUTO_MODE;
// 如果定时未开启,关闭风扇
if (Sensorthreshold.timing == 0)
{
driveData.Fan_Flag = 0;
}
KeyNum = 0;
}
break;
case SETTINGS_MODE:
// 设置模式内部按键在各自模式中处理
break;
}
}
// 模式切换优化:检测到系统模式变化时清屏并初始化
if(last_mode != mode)
{
OLED_Clear();
last_mode = mode;
// 立即绘制新模式的固定标题内容
switch(mode)
{
case AUTO_MODE:
auto_page = 1;
OLED_autoPage1();
break;
case MANUAL_MODE:
OLED_manualPage1();
break;
case SETTINGS_MODE:
OLED_settingsPage1();
SettingsThresholdDisplay1();
break;
}
OLED_Refresh();
}
// 模式处理
switch(mode)
{
// 自动模式
case AUTO_MODE:
{
uint8_t curr_auto_page = SetAuto();
if(curr_auto_page == 1)
{
SensorDataDisplay1();
}
// else
// {
// SensorDataDisplay2();
// }
AutoControl();
Control_Manager();
break;
}
// 手动模式
case MANUAL_MODE:
{
static uint8_t manual_page_initialized = 0;
static uint8_t last_manual_count = 0;
static uint8_t last_LED_Flag = 0;
static uint8_t last_Fan_Flag = 0;
static uint8_t force_refresh = 0;
// 模式切换时重新初始化状态
if(last_mode != mode)
{
manual_page_initialized = 0;
last_manual_count = 0;
last_LED_Flag = driveData.LED_Flag;
last_Fan_Flag = driveData.Fan_Flag;
force_refresh = 1;
count_m = 1;
}
uint8_t current_manual_count = SetManual();
// 检查设备状态是否改变
uint8_t need_refresh = 0;
if(driveData.LED_Flag != last_LED_Flag || driveData.Fan_Flag != last_Fan_Flag)
{
need_refresh = 1;
last_LED_Flag = driveData.LED_Flag;
last_Fan_Flag = driveData.Fan_Flag;
}
// 需要刷新时重新绘制页面
if(!manual_page_initialized || current_manual_count != last_manual_count || need_refresh || force_refresh)
{
OLED_manualPage1();
OLED_manualOption(current_manual_count);
ManualSettingsDisplay1();
manual_page_initialized = 1;
last_manual_count = current_manual_count;
force_refresh = 0;
OLED_Refresh();
}
// 立即处理手动模式按键
if(current_key_num != 0)
{
ManualControl(current_manual_count);
OLED_manualPage1();
OLED_manualOption(current_manual_count);
ManualSettingsDisplay1();
OLED_Refresh();
KeyNum = 0;
}
Control_Manager();
break;
}
// 设置模式
case SETTINGS_MODE:
{
SettingsModeHandler();
// 按键1:返回自动模式并保存所有设置
if (KeyNum == KEY_1)
{
KeyNum = 0;
mode = AUTO_MODE;
// 保存设置到Flash
FLASH_SaveSettings();
// 重置二级菜单状态
is_secondary_menu = 0;
secondary_initialized = 0;
secondary_pos = 1;
// 清屏并显示自动模式第一页
OLED_Clear();
OLED_autoPage1();
OLED_Refresh();
printf("返回自动模式,设置已保存\n");
printf("定时状态:%s,定时时间:%02d:%02d:%02d\n",
Sensorthreshold.timing ? "开启" : "关闭",
Sensorthreshold.time_hours,
Sensorthreshold.time_minute,
Sensorthreshold.time_second);
}
break;
}
}
// 限制显示刷新频率:每50ms刷新一次(避免屏幕闪烁)
if(current_time % 50 == 0)
{
OLED_Refresh();
}
userHandle();
}
}
六、实验效果

七、包含内容
