news 2026/10/29 16:42:20

STM32F103智能风扇DIY:HC-SR501人体感应+PWM调速实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103智能风扇DIY:HC-SR501人体感应+PWM调速实战

简介:这是一套面向嵌入式初学者与电子设计竞赛选手的STM32智能风扇完整工程资料,以STM32F103为核心,结合PWM调速、HCSR501人体红外感应与DHT11温湿度采集,实现有人自动开启、无人自动关闭及按环境温湿度智能调节转速的风扇控制系统,适合课程设计、毕业设计与DIY项目参考。压缩包共315个文件,约16.96MB,包含50个c源文件与52个h头文件构成的主程序框架、55个crf与56个o等编译中间文件、2个hex可执行文件及uvprojx、uvoptx等Keil工程配置,另附2份doc说明、2份pdf资料与2张jpg实物图,便于直接编译下载与对照理解。目前已有8891人学习下载,热度较高。资料完整呈现了从传感器数据采集、PWM占空比调节到人机交互的软硬件实现思路,读者可据此快速搭建实验环境、复现功能并在此基础上扩展改进。

1. 从一把“会自己转头”的风扇说起:STM32F103 智能风扇到底在做什么

夏天最烦的不是热,是半夜被冻醒还得摸黑找遥控器。我去年给卧室装了一台自己攒的 STM32 智能风扇,核心就三块:STM32F103 最小系统板、HC-SR501 人体红外模块、PWM 驱动的直流风扇。它干的事很朴素——检测到人进屋就转,人走十分钟自动停,温度高了自动加档,全程不用动手。这套方案在宿舍、工位、小仓库都跑得通,成本不到五十块,比买成品风扇多了“感知”和“联动”两个能力。

标题里几个词其实是一条完整链路:STM32F103 是主控,STM32PWM风扇 是执行方式,hcsr501 是感知入口,stm32风扇模块 是把这三者拼起来的硬件形态。热搜里 stm32f103最小系统、stm32f103 cubemx 定时器3、stm32f103 系列参考手册(rm0008) 这些词,恰好对应了从选型到写代码的必经环节。这篇笔记就按我实际调试的顺序,把选型、接线、PWM 配置、HC-SR501 触发逻辑、避坑和进阶调参讲透,新手能照着复现,熟手能直接拿去改参数。

2. 硬件选型与接线:STM32F103、HC-SR501 和风扇怎么接才不翻车

2.1 为什么是 STM32F103 而不是别的

选 STM32F103C8T6 最小系统板,理由很实际:72MHz 主频跑风扇控制绰绰有余,4 个通用定时器里 TIM3 能出 4 路 PWM,价格便宜到十块钱以内,资料多到搜“stm32f103最小系统”能翻出几百篇。热搜里 stm32f103 pack包下载、stm32芯片包安装 这些词说明很多人卡在环境搭建,我建议直接用 Keil MDK 加 ST-Link,别一上来折腾 VSCode 配置 stm32 开发环境,先把灯点亮再说。

风扇这边分两种:两线直流风扇只能调电压,三线或四线 PWM 风扇才能直接吃 PWM 信号。我手上是四线风扇,红线 12V、黑线 GND、黄线测速、蓝线 PWM。如果你只有两线风扇,就得加一个 MOS 管模块,用 PWM 控制栅极,本质还是 STM32PWM风扇 的思路。

HC-SR501 是经典的人体红外模块,工作电压 4.5V 到 20V,输出 3.3V 高电平,和 STM32 的 IO 直连没问题。它有两个可调电位器:一个调延时(0.3 秒到 5 分钟),一个调灵敏度(3 米到 7 米)。注意它上电后有 30 到 60 秒初始化时间,这段时间输出会乱跳,代码里必须加延时等待。

2.2 接线表与供电注意

模块引脚接到 STM32F103说明
HC-SR501VCC5V模块内部有稳压,5V 供电更稳
HC-SR501GNDGND共地
HC-SR501OUTPA0配置为浮空输入或下拉输入
四线风扇PWMPA6 (TIM3_CH1)需要 3.3V 电平,风扇 PWM 线一般兼容
四线风扇GNDGND共地
四线风扇12V外部 12V不要从 STM32 取电
四线风扇测速PA1可选,用定时器捕获测转速

供电是第一个大坑。STM32 的 5V 引脚从 USB 取电,带不动风扇,必须外接 12V 电源,而且 12V 和 3.3V 要共地。热搜里 stm32f103 5v转3.3v电路 这个词很热,但这里不需要你转,最小系统板自带 AMS1117,你只要保证外部 12V 不灌进 3.3V 就行。

提示:HC-SR501 输出高电平是 3.3V,但如果你买到的模块是 5V 供电输出 5V 电平,直接接 PA0 会烧引脚。用万用表量一下 OUT 对地电压,超过 3.6V 就加一个分压电阻。

2.3 最小系统板的启动模式

STM32F103 的 BOOT0 和 BOOT1 决定启动方式。正常跑程序时 BOOT0 接 GND,BOOT1 任意。如果你用 ST-Link 下载后程序不跑,先查这两个跳线帽。热搜里 stm32芯片第一脚怎么确认 这种问题,在最小系统板上看圆点或者丝印缺口就行,别接反 VCC 和 GND,反接必烧。

3. 用 CubeMX 配 TIM3 PWM:从 0 到风扇转起来的最小工程

3.1 时钟树和 TIM3 参数怎么算

打开 CubeMX,选 STM32F103C8T6,先配 RCC 为外部晶振,时钟树里 HSE 选 8MHz,PLL 倍频到 72MHz。TIM3 挂在 APB1 上,APB1 预分频系数为 2 时,定时器时钟是 72MHz。

PWM 频率计算公式:Fpwm = 72MHz / ((Prescaler + 1) * (Period + 1))。四线风扇的 PWM 推荐频率是 25kHz,人耳听不到啸叫。我取 Prescaler = 71,Period = 39,算下来 72MHz / (72 * 40) = 25kHz。占空比用Pulse = Period * duty来设,duty 从 0 到 1。

// tim.c 中 CubeMX 生成的配置片段 htim3.Instance = TIM3; htim3.Init.Prescaler = 71; // 72分频,定时器时钟 1MHz htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 39; // 自动重装载值,配合预分频得到 25kHz htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_PWM_Init(&htim3); // 配置通道1 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 20; // 初始占空比 50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

这段代码里 Prescaler 和 Period 是核心参数,改频率就动这两个。Pulse 决定占空比,20 对应 50%,因为 Period 是 39,20/40 正好一半。注意 AutoReloadPreload 要开,否则改占空比时会出现毛刺。

3.2 主循环里怎么调占空比

// 设置风扇转速,duty 范围 0.0 ~ 1.0 void Fan_SetSpeed(float duty) { if (duty < 0.0f) duty = 0.0f; if (duty > 1.0f) duty = 1.0f; uint32_t pulse = (uint32_t)(duty * (htim3.Init.Period + 1)); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse); }

__HAL_TIM_SET_COMPARE是 HAL 库的宏,直接改 CCR1 寄存器,比重新调用 ConfigChannel 快得多。duty 为 0 时风扇停,1 时全速。四线风扇在 duty 低于 20% 时可能不转,这是正常现象,不是代码问题。

3.3 验证 PWM 输出的两种方法

第一种,用示波器看 PA6 波形,频率 25kHz,占空比随 duty 变化。第二种,没有示波器就接 LED 加电阻,看亮度变化。热搜里 keilc stm32查看io输出波形 这个词,其实 Keil 的仿真模式也能看,但需要配 Debug 里的 Logic Analyzer,不如直接量来得快。

注意:如果你用的是两线风扇加 MOS 管,PWM 频率要降到 1kHz 以下,否则 MOS 管开关损耗大,发热严重。四线风扇才适合 25kHz。

4. HC-SR501 触发逻辑与状态机:让人来灯亮、人走风停

4.1 HC-SR501 的输出特性与去抖

HC-SR501 检测到人体移动时输出高电平,人不动了它还会保持一段时间,这个时间由延时电位器决定。我一般调到最小,大概 3 秒,然后在代码里做软件延时。模块上电后有 30 到 60 秒初始化,输出会随机跳,所以main函数开头必须加HAL_Delay(60000)或者至少 30 秒。

// 读取 HC-SR501 状态,带简单去抖 uint8_t PIR_Read(void) { static uint8_t last_state = 0; static uint32_t last_time = 0; uint8_t current = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); uint32_t now = HAL_GetTick(); if (current != last_state && (now - last_time) > 200) { last_time = now; last_state = current; } return last_state; }

去抖时间设 200ms,因为 HC-SR501 输出变化不会太快,但电源波动可能引起毛刺。HAL_GetTick()返回毫秒数,依赖 SysTick 中断,别在中断里关掉 SysTick。

4.2 状态机设计:待机、运行、延时关闭

我一般用三个状态:IDLE、RUNNING、COOLDOWN。IDLE 时风扇停,检测到人进 RUNNING,风扇按温度或固定档位转。人走后进 COOLDOWN,风扇继续转 10 分钟,期间如果又检测到人,直接回 RUNNING。

typedef enum { IDLE, RUNNING, COOLDOWN } FanState; FanState state = IDLE; uint32_t cooldown_start = 0; void Fan_Update(void) { uint8_t pir = PIR_Read(); switch (state) { case IDLE: if (pir) { Fan_SetSpeed(0.6f); state = RUNNING; } break; case RUNNING: if (!pir) { cooldown_start = HAL_GetTick(); state = COOLDOWN; } break; case COOLDOWN: if (pir) { state = RUNNING; } else if (HAL_GetTick() - cooldown_start > 600000) { Fan_SetSpeed(0.0f); state = IDLE; } break; } }

600000 是 10 分钟,单位毫秒。这个值根据场景改,卧室可以短一点,仓库可以长一点。状态机放在主循环里,每 50ms 调一次,别放中断里,否则 HAL_Delay 会卡死。

4.3 和温度联动的扩展

如果想更智能,加一个 DS18B20 或 NTC 热敏电阻,在 RUNNING 状态里根据温度调 duty。比如 26 度以下 40%,26 到 30 度 60%,30 度以上 100%。热搜里 stm32 adc切换通道 这个词,用 NTC 时就需要 ADC 多通道采样,注意采样时间要够长,否则读数跳。

5. 避坑与排查:HC-SR501 乱触发、PWM 不转、程序跑飞

5.1 现象:HC-SR501 一直输出高电平,风扇停不下来

原因:模块上电初始化没等够,或者灵敏度电位器拧到最大,检测范围覆盖了窗外或走廊。解决:上电后等 60 秒再读,灵敏度调到中间位置,必要时在模块前面加一个遮光罩,只留正前方探测窗口。

5.2 现象:PWM 输出正常但风扇不转

原因:四线风扇的 PWM 线电平不兼容,或者 12V 电源没共地。解决:用万用表量风扇 PWM 线对地电压,STM32 输出 3.3V 方波,如果风扇要求 5V 电平,加一个电平转换模块。共地问题最常见,12V 电源的 GND 必须和 STM32 的 GND 接在一起。

5.3 现象:程序下载后不跑,或者跑一会儿卡死

原因:BOOT0 没接地,或者中断优先级冲突导致 HardFault。解决:检查 BOOT0 跳线,用 ST-Link 调试模式看卡在哪。热搜里 stm32延时函数delay卡死 这个词,多半是因为在中断里调用了 HAL_Delay,而 HAL_Delay 依赖 SysTick 中断,优先级低于当前中断就会死等。

5.4 现象:风扇转速忽高忽低,有啸叫

原因:PWM 频率落在人耳敏感区间,或者占空比更新时没有开 AutoReloadPreload。解决:把频率提到 25kHz 以上,CubeMX 里确认AutoReloadPreload设为 ENABLE。如果还有啸叫,在风扇电源两端并一个 100uF 电解电容。

5.5 现象:HC-SR501 触发距离忽远忽近

原因:环境温度接近人体温度,或者模块供电不稳。解决:HC-SR501 在夏天高温环境灵敏度会下降,这是物理限制。供电用独立的 5V LDO,别和风扇共用一路,风扇启动瞬间压降会让模块复位。

6. 进阶调参:用定时器捕获测转速和串口调 PID

6.1 用 TIM2 捕获风扇测速线

四线风扇的测速线输出方波,频率和转速成正比。一般风扇规格是每转两个脉冲,所以RPM = 频率 * 60 / 2。用 TIM2 的通道 1 做输入捕获,PA1 接测速线。

// TIM2 输入捕获配置,测频率 void TIM2_Capture_Init(void) { TIM_IC_InitTypeDef sConfigIC; htim2.Instance = TIM2; htim2.Init.Prescaler = 71; // 1MHz 计数 htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFF; HAL_TIM_IC_Init(&htim2); sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); } // 捕获中断回调 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { static uint32_t last_capture = 0; static float rpm = 0; uint32_t capture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if (last_capture != 0) { uint32_t diff = capture - last_capture; if (diff > 0) { float freq = 1000000.0f / diff; // 1MHz 计数 rpm = freq * 60.0f / 2.0f; // 每转2脉冲 } } last_capture = capture; }

这段代码里 Prescaler 设 71 让计数频率为 1MHz,diff 是两个上升沿之间的计数差,倒数就是频率。rpm 算出来可以通过串口打印,或者用来做闭环。注意捕获中断里不要做浮点运算太久,我一般只存值,主循环再算。

6.2 串口调 PID 让转速更稳

如果风扇负载变化大,转速会掉,可以用 PID 调。热搜里 stm32串口调试pid 这个词,核心是把 PID 参数做成串口可改的变量。我用一个简单的结构体:

参数含义典型值
Kp比例系数0.5
Ki积分系数0.1
Kd微分系数0.01
Target目标转速1200 RPM

串口收到P=0.8就改 Kp,收到T=1500就改目标。PID 输出限幅到 0 到 1,再喂给Fan_SetSpeed。调的时候先只加 P,看到转速接近目标但有静差,再加 I,最后加 D 抑制超调。别一上来三个参数一起调,那是玄学。

6.3 一个我踩过的坑:测速线电压

风扇测速线是开漏输出,需要上拉电阻到 3.3V,否则 STM32 读不到高电平。我一开始没加上拉,捕获中断死活不进,查了半天以为是定时器配置错了。后来在 PA1 和 3.3V 之间焊了一个 10k 电阻,立刻正常。这个坑在风扇手册里通常不写,但血泪经验告诉我,四线风扇的测速线必须上拉。

6.4 验证方法:用串口画曲线

没有上位机就用串口助手,每 100ms 打印一次rpm和duty,复制到 Excel 画曲线。看转速能不能稳定在目标值上下 5% 以内。如果振荡,先把 Kd 降到 0,把 Ki 减半。我一般会留一个后悔药:在 Flash 里存一组默认 PID 参数,调崩了长按按键恢复。

这套东西跑通之后,你会发现 STM32F103 加 HC-SR501 加 PWM 风扇的组合,能复用到鱼缸散热、机柜通风、宠物窝降温很多场景。我现在的习惯是每做一个新板子,先把 PWM 和串口调通,再往上叠传感器,这样出问题能快速定位是硬件还是代码。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 16:41:24

JSP游戏社交论坛全栈开发实战指南

1. 项目概述&#xff1a;JSP游戏社交论坛全栈开发实战 这个项目是一个基于JSP技术的游戏社交论坛系统&#xff0c;包含了从程序开发到部署上线的完整解决方案。作为一名有十年全栈开发经验的工程师&#xff0c;我完整走通了这套系统的开发流程&#xff0c;现在把关键技术和踩坑…

作者头像 李华
网站建设 2026/10/29 16:41:08

脑机接口人才需求与应聘指南

1. 项目背景解析"强脑科技招聘一则"这个标题背后反映的是当前科技行业人才争夺战的一个典型切片。作为一家专注脑机接口与人工智能融合领域的高科技企业&#xff0c;强脑科技这类公司的招聘动态往往能折射出行业技术发展方向和人才需求趋势。过去三年里&#xff0c;脑…

作者头像 李华
网站建设 2026/10/29 16:40:07

AI模型集成与动态切换的工程实践与优化

1. 模型集成与切换的核心价值在AI工程化落地的过程中&#xff0c;单一模型往往难以满足复杂场景的需求。我经历过多个项目从POC到上线的完整周期&#xff0c;发现模型集成与动态切换能力已经成为生产环境的标配需求。这就像赛车手在比赛中需要根据路况随时换挡——直道用高速档…

作者头像 李华
网站建设 2026/10/29 16:40:05

caveman debugging:一行print搞定生产环境疑难Bug

看到“caveman”这标题&#xff0c;如果你脑子里蹦出来的是穴居人、原始人、或者旧石器时代的饮食法&#xff0c;那咱俩想的不是一回事。我说的是程序员圈子里一个流传了很多年的老梗——caveman debugging&#xff08;原始人调试法&#xff09;。说直白点就是&#xff1a;出Bu…

作者头像 李华
网站建设 2026/10/29 16:39:48

数字藏品AI客服系统设计与优化实践

1. 项目背景与核心价值数字藏品平台的客服需求与传统电商有着本质区别。藏家们往往对数字艺术品的版权、区块链存证、转赠规则等有高度专业化咨询需求&#xff0c;而普通客服人员培训周期长、响应速度慢。我们团队为某头部数字藏品平台设计的AI智能客服系统&#xff0c;上线后人…

作者头像 李华
网站建设 2026/10/29 16:38:31

Marketing Skills本质是用户认知建模与信任节奏控制

1. 这不是“学营销”&#xff0c;而是重建你和用户之间的信任通道“marketingskills”这个词最近在招聘平台、自由职业接单群、甚至小红书知识博主的标题里高频出现&#xff0c;但它绝不是“怎么发朋友圈更吸睛”或“短视频脚本怎么写才爆火”的速成技巧合集。我带过37个从零起…

作者头像 李华