发布时间:2026/8/9 4:32:49
闭环风扇-EXTI真测RPM与快充协商供电 STM32 闭环风扇PA0 EXTI 真测 RPM CH224K 快充协商供电附完整工程标签STM32、STM32F103C8T6、EXTI、DS18B20、WS2812、Type-C、CH224K、嵌入式硬件仓库https://github.com/kaka12331/stm32-closed-loop-fan这篇解决什么问题网上的「智能风扇」教程基本是同一套ADC 读电位器 → 映射成占空比 → 写 PWM。它有两个说不出口的问题它是开环的。你写下去 60% 占空比风扇到底转了多少转程序完全不知道。风扇卡住、堵转、电压跌了代码一无所觉还在开开心心输出 60%。它供不动真风扇。用 USB 5V 带一个 12V 服务器风扇要么转不起来要么一加速整个板子跟着复位。这个工程把这两点都解决了PA0 用 EXTI 捕获风扇自带的 TACH 测速线算出真实 RPM供电侧用Type-C CH224K 协商高压直供风扇功率轨MCU 和传感器走独立的 5V→3.3V 逻辑轨。顺带记录三个把我坑了很久的地方sprintf(%f)直接死机、DS18B20 在有中断的系统里读不出温度、以及 OLED 全屏刷动画慢得像幻灯片。硬件与引脚引脚功能PA0风扇测速 TACHEXTI上拉PA1电位器 ADC 调速PA2DS18B20 单总线PA7WS2812 数据线PA8风扇 PWM低边开关PB8 / PB9OLED I²C SCL / SDAPB12 / PB15按键动画模式 / 风扇模式供电为什么要上 CH224K普通做法是给风扇单独接一个 12V 电源适配器桌面上就多一根线。这里换了个思路Type-C ──► CH224K 协商高压 ──► VBUS 直供风扇功率轨 │ └──► TPS54260 ──► 5V ──► AMS1117-3.3 ──► MCU / 传感器CH224K 是一颗受电端Sink快充协议芯片向充电器申请高于 5V 的档位。谈成之后 VBUS 上就是高压直接喂给风扇的功率轨MCU 这一侧再用 TPS54260 降到 5V、AMS1117 降到 3.3V。这么做的实际收益是强弱电分轨风扇启动瞬间的浪涌全部在功率轨上消化不会打到 MCU 的 3.3V 上。开头说的「一加速就复位」根因就是风扇和 MCU 共用一路弱电源。一根 Type-C 线同时供电和调速桌面上不用再多一个电源砖——这是这个项目最实用的部分。一、真闭环EXTI 数 TACH 脉冲算 RPM四线 PWM 风扇的第三根线是 TACH 测速输出风扇每转一圈输出固定数量的脉冲绝大多数是 2 个。把它接到 PA0配成 EXTI 上升沿触发中断里只做一件事计数。externvolatileuint32_tFan_Pulse_Count;// EXTI 中断里 然后在 700 ms 的慢速任务里结算__disable_irq();// 关中断保护数据uint32_tcurrent_pulsesFan_Pulse_Count;Fan_Pulse_Count0;__enable_irq();// 开中断real_rpm(uint16_t)(current_pulses*42.85);42.85 这个魔数是怎么来的别背推一遍RPM 脉冲数 ÷ 2每转2个脉冲 ÷ 0.7秒 × 60秒 脉冲数 × 60 ÷ (2 × 0.7) 脉冲数 × 42.857所以如果你的风扇是每转 1 个或 4 个脉冲或者你把窗口从 700 ms 改成别的值这个系数要跟着重算照抄会得到一个离谱的转速。为什么读计数值必须关中断current_pulses Fan_Pulse_Count; Fan_Pulse_Count 0;这两行之间如果来了一个 EXTI那一个脉冲就被清零吞掉了。单次误差不大但它是系统性偏低——每次结算都可能丢转速会一直比真实值小一点。关中断的窗口只有两条赋值语句对 EXTI 的影响可以忽略。OLED 上同时显示目标占空比和真实 RPM这两个数不一致的时候就是风扇出问题的时候——这是开环方案给不了的信息。二、DS18B20 读不出温度先看你有没有关中断DS18B20 是单总线器件时序按微秒算复位脉冲 480 µs、写 0 的低电平 60~120 µs、读时隙必须在 15 µs 内采样。问题来了你的系统里有 EXTI风扇测速、有 TIM 中断。**风扇转起来以后TACH 中断每秒来上百次。**只要有一个中断插在读时隙中间这一位就废了整个字节错位读回来是乱码或者 85.0DS18B20 的上电默认值。所以整段读写必须原子化__disable_irq();// 保护微秒级时序uint8_ttemp_statusDS18B20_ReadTemperature(temperature);DS18B20_TriggerConversion();// 顺手触发下一次转换__enable_irq();这里还用了一个小技巧读完立刻触发下一次转换。DS18B20 转换 12 位精度要 750 ms如果「触发—等待—读取」写在一起主循环就得干等 750 ms。改成「这次读上次的结果顺便触发下次」等待时间被 700 ms 的任务周期自然吸收掉一次都不用等。三、sprintf(%f)直接死机温度是浮点数最自然的写法是sprintf(display_buf,%.2f C,temperature);// 跑到这里就飞了Keil 标准库下printf系列对浮点的支持要额外的库支持和明显更大的栈。默认启动文件里的栈大小常见是 0x400扛不住直接栈溢出进 HardFault。不用去改启动文件把小数拆成两个整数就行inttemp_int(int)temperature;// 整数部分inttemp_frac(int)((temperature-temp_int)*100);// 两位小数if(temp_frac0)temp_frac-temp_frac;// 防止出现 25.-5sprintf(display_buf,%2d.%02d C,temp_int,temp_frac);那行if (temp_frac 0)别删。温度是 -3.25 ℃ 的时候整数部分取到 -3小数部分算出来是 -25拼出来就是-3.-25。同一个坑我在平衡车工程里是主动绕开的——那边干脆自己写了FormatFixed2()和ParseFloat()全程不碰 printf 的浮点。四、OLED 动画把 I²C 通信量砍掉一半128×64 的屏用软件 I²C 刷全屏一帧 1024 字节。原始写法一秒钟刷不了几帧动画像幻灯片。这个工程的图源是 120×120 的方图要缩放贴到 128×64 的屏上。OLED_ShowFrame_Magic()做了四处优化for(page0;page8;page){// 优化1光标直接定位到居中起点 X32跳过左边的黑边OLED_SetCursor(page,32);// 优化2只循环 64 次不画多余的背景I²C 通信量直接减半for(col0;col64;col){oled_byte0;// 优化3用位移 代替除法src_x(col*15)3;for(bit0;bit8;bit){dst_y(page3)bit;src_y(dst_y*15)3;// 优化4用 0x07 代替 % 8 取余if(Image[src_y*15(src_x3)](0x80(src_x0x07))){oled_byte|(1bit);}}OLED_WriteData(oled_byte);}}真正起决定作用的是第 2 条。方图贴到 128 宽的屏上两侧本来就是黑边那 64 列纯粹是在给屏幕发 0。只画中间 64 列I²C 传输量直接从 1024 字节降到 512 字节——通信是瓶颈所以帧率大致翻倍。第 3、4 条3代替/8、0x07代替%8在 Cortex-M3 上收益小得多因为它有单周期硬件除法器。但这种写法在循环体里是免费的写了不亏。改完之后每 20 ms 刷一帧50 FPS。五、调度一个 20 ms 心跳带两条时间线没上 RTOS也没有满屏的delay。主循环只有一个节拍while(1){/* 按键处理 */uint8_tkeyKey_GetNum();if(key15){current_mode1;mode_init_flag1;OLED_Clear();}elseif(key12){current_mode0;mode_init_flag1;OLED_Clear();}if(current_mode0){/* 动画模式每个节拍刷一帧 50 FPS */}else{/* 风扇模式 */adc_valueADC_Get_Average_Value(ADC_Channel_1,10);target_speed(uint8_t)(((uint32_t)adc_value*100)/4095);Set_Fan_Speed(target_speed);/* WS2812 随动低速纯蓝 → 高速纯红 */uint8_tred_val(target_speed*255)/100;uint8_tblue_val255-red_val;for(uint8_ti0;i4;i){WS2812_SetColor(i,red_val,0,blue_val);}WS2812_Refresh();if(fan_slow_tick35)/* 35 × 20 ms 700 ms */{fan_slow_tick0;/* 结算 RPM 读温度 */}}Delay_ms(20);/* 统一心跳 */anim_tick;fan_slow_tick;}快慢分离的理由很实际ADC 和 PWM 要跟手旋钮一转就得有反应20 ms 正好转速需要一个足够长的窗口才能积够脉冲、算得准温度传感器本身也要 750 ms 才转换完塞进 700 ms 的慢速任务刚好。mode_init_flag是配套的细节切模式时OLED_Clear()会把静态标签一起擦掉所以要用这个标志让新模式在第一个节拍里把Tgt:/RPM:/Temp:这些不变的文字重画一次之后每个周期只更新数字。否则你会看到标签在闪。这套「一个心跳 多条计数时间线」是最省事的裸机调度。想更进一步做成事件驱动/分层架构可以看我另一篇告别几千行的 main.cSTM32 裸机开发天花板面向对象与事件驱动架构关键参数速查参数值为什么主循环节拍20 msADC/PWM 跟手的下限慢任务周期700 ms35 拍够积脉冲且 ≥ DS18B20 的 750 ms 转换需求RPM 系数42.8560 ÷ (2 脉冲/转 × 0.7 s)换风扇要重算ADC 平均次数10压电位器抖动动画帧率50 FPS20 ms/帧WS2812 数量4低速纯蓝 → 高速纯红线性渐变复现步骤Keil µVision / MDK-ARM 打开Project.uvprojx目标芯片STM32F103C8T6SWD 下载先别接风扇功率轨。只上 5V 逻辑确认 OLED 亮、电位器数值随旋钮变化接上风扇用手隔着东西短暂挡一下看 OLED 的 RPM 是否跟着掉——不掉就是 TACH 线没接好或者没配上拉确认你的风扇每转几个脉冲不是 2 就改42.85最后接 DS18B20。读回来恒定 85.0 ℃ 说明时序被打断了回头检查__disable_irq()有没有包住整段读写这个工程还能改的地方坦白说现在的Delay_ms(20)是阻塞的——那 20 ms 里 CPU 在空转。想更彻底可以把节拍换成一个 TIM 中断置标志位主循环只查标志。对这个项目来说没必要但如果你要在上面再加 Wi-Fi 或者更多传感器这一步迟早要走。另外DS18B20_ReadTemperature期间关中断那几百微秒里 TACH 脉冲是会丢的。因为只发生在 700 ms 一次的慢任务里对转速的影响远小于 1%可以接受但如果你要把测速精度做到工业级得换成硬件定时器输入捕获来数脉冲。相关文章裸机调度想做得更规范面向对象与事件驱动架构电源部分的底层原理DC-DC 降压电路的「高频热回路」与布板玄学仓库地址https://github.com/kaka12331/stm32-closed-loop-fan标准外设库等第三方代码遵循其原协议。如果你基于这个工程做了改动欢迎在评论区交流。

相关新闻

2026/8/9 4:32:49

什么是数字员工?AI销冠系统与AI提效软件系统的市场优势是什么?

数字员工是新兴的AI销售工具,已逐渐成为企业降本提效的重要手段。通过AI销冠系统、数字员工能够优化业务流程自动化。他们可以在同一时间内完成多个外呼任务、除了提高了效率依赖。这种自动化解决方案使得企业可以将资源集中在高价值的客户交互上,进一步…

2026/8/9 5:32:54

Godot游戏资源解包全攻略:从.pck文件提取素材的两种实用方案

1. 项目概述:为什么我们需要解包Godot游戏资源?在游戏开发或者游戏模组制作的圈子里,你肯定遇到过这种情况:看到一个用Godot引擎做的游戏,里面的美术素材、音效、字体或者脚本设计得特别棒,想学习一下&…

2026/8/9 5:32:54

解决Blender CUDA渲染错误:Failed to retain CUDA context

1. 问题现象与背景分析 当你在Blender中尝试使用CUDA加速进行渲染时,突然弹出一条错误提示:"Failed to retain CUDA context (Illegal instruction)"。这个错误通常发生在使用NVIDIA显卡进行GPU渲染的过程中,表明CUDA运行时环境出…

2026/8/9 5:32:54

2026年市面上口碑好的HDMI矩阵工厂,哪家更专业?

在视听系统集成项目中,HDMI矩阵的价值往往容易被低估——很多项目交付后,用户最终抱怨不是屏幕不清晰,而是信号切换卡顿、黑屏、不兼容这些“小毛病”。一套功能完备、稳定可靠的矩阵,往往才是整个系统能否“好交付”的关键。今天…

2026/8/9 5:32:54

2026 流量计十大品牌排行:工业计量标杆品牌深度盘点

一、行业背景:工业数字化驱动流量计量产业高质量发展在工业 4.0 落地深化、双碳管控趋严与智能制造升级的多重驱动下,流量计作为工业测控体系的核心感知终端,已成为化工、电力、冶金、水务、热力、生物医药等支柱产业不可或缺的基础装备。随着…

2026/8/9 5:27:53

合规无人直播|7×24小时自动带货的直播变现全新解决方案

引言:直播行业的效率革命 在直播电商如火如荼的今天,传统直播模式正面临严峻挑战:高昂的主播人力成本、有限的直播时长、夜间流量白白流失、多账号管理繁琐……利润空间被不断压缩。商家们急需一种既能降本增效,又能合规稳定运营的…

2026/8/9 0:01:56

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:56

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/9 0:01:56

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:56

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/7 9:44:18

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/7 19:03:32

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/8 2:17:42

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…