
简介基于STM32的智能温控风扇控制系统是一份包含完整源码、Proteus仿真与全套工程文档的毕设/课设资源适合嵌入式初学者、电子专业学生及需要快速复现温控风扇项目的开发者。系统以STM32为核心配合DS18B20等温度传感器采集环境温度通过PWM调节风扇转速实现自动恒温控制Proteus仿真可直接运行验证降低实物调试成本。压缩包共155个文件核心代码以 .c/.h 源文件为主另有 .hex 烧录文件、.pdsprj/.pdsbak 仿真工程、.uvprojx 工程配置、.pdf 原理图及 .doc 说明文档等分工明确便于对照学习和二次开发。压缩包仅6.09MB内容精简却覆盖项目全流程。已有2053人学习下载本资源通过源码分析与仿真调试可掌握STM32外设配置、传感器读取及PWM调速等关键技能并可直接用于报告撰写或项目答辩准备。 说实话第一次在Proteus里把STM32的温控风扇整套跑起来的时候我还是有点小激动的。不是因为这个项目本身有多难而是它把“读传感器、做控制、输出显示、按键交互”这一整条嵌入式开发的经典链路完整串起来了。对于正在学STM32或者准备课程设计的人来说这种项目属于那种“看起来不难自己动手全是坑”的类型——但只要你把它拆开揉碎了看每个模块其实都有非常清晰的套路。我拿到这套“基于STM32单片机智能温控风扇控制系统Proteus仿真源码仿真全套资料”的时候先没急着打开源码而是自己先对着标题推演了一遍系统应该长什么样。后来发现推演出来的结构和源码里的实现基本吻合这种“先想清楚再动手”的习惯正是我想在这篇文章里跟你聊的第一件事。1. 先把需求想明白这套温控风扇要做的不是开关而是调节很多新手拿到“温控风扇”这个题目第一反应是温度高了就开风扇温度低了就关风扇。这本质上是个继电器开关逻辑太浪费STM32的算力了也不符合“智能温控”这几个字的含金量。真正的温控风扇核心在于“调节”——根据当前温度和设定目标温度的差值平滑调整风扇转速让温度稳定在一个舒适区间而不是反复开关制造噪音和机械磨损。1.1 这套系统真正要解决的三个问题从功能层面拆解这套系统其实就回答三个问题问题一现在环境温度是多少这个由温度传感器来解决常见方案是DS18B20或者LM35分别对应数字输出和模拟输出两条技术路线。Proteus里两者都有仿真模型我后面会详细对比。问题二风扇应该转多快这就是控制逻辑的范畴了。最简单的做法是分段控制温度低于下限阈值时风扇停止高于上限阈值时全速转中间按比例调速或者分档调速。这种逻辑用一个滞回比较器分段PWM就能实现也是这套源码里最核心的算法部分。问题三用户怎么知道当前状态、怎么干预一块LCD1602显示温度、模式、转速级别两到三个按键用来切换自动/手动模式、调整温度阈值或者手动挡位。这三个问题对应的正好是传感器、控制器、执行器、人机交互这四大块是几乎所有智能小家电的通用架构。所以这个项目虽然名字叫“温控风扇”但它的学习价值在于你掌握了这套架构后面做温控器、智能浇花系统、孵化箱温控换壳不换里。1.2 自动模式下的调速策略怎么定如果让我来设计调速策略我不会用单一的阈值比较而是用“滞回比较线性映射”的组合。举个例子设定目标温度25℃回差2℃当温度低于23℃时PWM占空比为0风扇停当温度在23℃到33℃之间时占空比从10%线性增加到100%当温度高于33℃时保持100%这个策略的好处是避免风扇在阈值附近频繁启停这是PID还没上马时最实用的防抖手段同时让风扇转速随温度连续变化而不是“突然加速”让人明显感觉到换挡。从这套资料的源码来看作者采用的是分段线性映射的方式每隔一定温度步进对应一个占空比等级逻辑清晰且容易在Proteus仿真中通过修改DS18B20的属性值来观察转速变化。这种策略非常适合课程设计和入门项目因为它不需要PID参数整定又能直观展示PWM调速的效果。2. 器件选型心得Proteus里哪些组合最不容易翻车很多人在Proteus里做STM32仿真最容易翻车的地方不是写代码而是选错仿真器件、元件库里找不到某颗芯片、或者器件之间的兼容性出问题。我把自己在仿真中反复验证过的一套组合列在下面照抄基本不会出大问题。2.1 主控为什么首选STM32F103C8T6这套资料用的是STM32F103C8T6蓝色 pill 板那颗经典芯片在Proteus里的模型非常成熟。它的优势是主频72MHz在仿真里完全够用20KB RAM、64KB Flash跑这套温控逻辑绰绰有余GPIO、TIM、ADC、USART外设齐全后面你想扩展OLED、蓝牙模块、ESP8266物联网功能也不需要换主控。Proteus里添加元件的关键词是STM32F103C8T6注意不是STM32F103C8因为版本不同、引脚封装对不上会导致连线困难。另外Proteus里的STM32模型不会默认接上电源和地你需要在Design - Configure Power Rails里确认VDD、VSS、VDDA、VSSA这些引脚都被分配到了正确的电源网络。这个细节很关键我见过太多人仿真跑不起来就是死在这一步。2.2 温度传感器DS18B20还是LM35这是个经典二选一问题我给你的建议是追求仿真稳定性和代码通用性选DS18B20想顺便练ADC采集选LM35。对比项DS18B20LM35输出信号单总线数字信号模拟电压10mV/℃接线3根线VCC、GND、DQ3根线VCC、GND、VOUT精度默认9~12位可配置取决于ADC位数和参考电压外部上拉电阻需要典型4.7kΩ不需要代码复杂度需要严格时序时序只需要ADC采样换算Proteus仿真表现模型支持温度属性实时修改模型也支持但需要用电压源模拟Proteus里DS18B20的仿真模型做得很好你可以运行时直接修改它的温度属性TemperatureLCD上的数值会实时变化风扇转速也会随之调整演示效果非常直观。这套源码采用的就是DS18B20方案主要是因为数字传感器省掉了ADC采样和标定的步骤温度换算的代码也更简单、更好向别人讲解。2.3 风扇驱动三极管还是L298N驱动芯片Proteus仿真里面风扇通常用MOTOR-PWM或者普通直流电机代替这些模型对驱动电流不敏感所以很多人会忽略驱动电路的设计。但如果你是打算后续做实物这一步就不能跳过。实物上驱动直流小风扇有两种方案方案ANPN三极管/MOS管 续流二极管。适合5V、几百毫安的小风扇用STM32的PWM引脚直接控制栅极简单、成本低、PCB面积小。方案BL298N或TB6612驱动芯片。适合稍大功率或者需要正反转控制的场景功能强但电路更复杂课程设计一般用方案A就足够。仿真中我建议你仍然把三极管/MOS管和续流二极管画上去哪怕模型不检查这些细节。原因是仿真图纸本身也是一份交付物评阅老师或面试官看到你在仿真里就考虑了驱动设计会明显高看一眼而且后续转实物时PCB设计可以参考仿真图不用推倒重来。选用MOS管时注意逻辑电平STM32的IO是3.3V最好选Vgsth低于2V的逻辑电平MOS管比如AO3400这类。如果只有普通三极管可以用NPN管S8050配合基极限流电阻注意放大倍数够不够必要时用达林顿结构。3. 仿真环境搭建细节从新建工程到首次点亮LCD这个部分我默认你已经装好了Proteus和Keil MDK。版本方面Proteus 8.9以上对STM32的仿真支持都比较完整Keil 5配STM32F1系列标准外设库Standard Peripheral LibrarySPL或者直接开HAL库都行。这套资料用的是标准外设库风格我觉得对学习来说反而更好读。3.1 新建工程时容易忽略的布线环节Proteus里从元件库拖出STM32F103C8T6、DS18B20、LCD1602、LED、电阻、按键之后先不要急着连线。我建议按下面的顺序操作配置电源轨Design - Configure Power Rails把VDD/VDDA连接到VCC/VDD网络VSS/VSSA连接到GND网络。给DS18B20的DQ引脚加上拉电阻阻值取4.7kΩ一端接DQ、另一端接3.3V。仿真模型对这个上拉不是特别敏感但这是真实硬件的要求养成好习惯。LCD1602的对比度引脚V0接一个电位器或者直接接地仿真中直接接地一般也能显示但如果出现显示过淡或乱码优先检查这个引脚。按键一端接GPIO、另一端接地并在GPIO端接上拉电阻。STM32内部可以配置上拉所以外部不接也能工作但仿真里为了保证状态稳定外接10kΩ上拉更不容易抖动。关于电机风扇Proteus的电机模型没有明确的正负极标记区分接反了也能转但实物上要注意标记。仿真里用一个NMOS门控的MOTOR-PWM模型即可PWM频率和占空比可以从示波器观察。3.2 晶振和复位电路看不见却影响全局的部分STM32芯片内部有RC振荡器不上外部晶振也能跑但USART等外设的波特率可能不准。Proteus里我建议仍然画上8MHz晶振和两个20pF负载电容这样跟实际硬件更接近。复位电路方面STM32是低电平复位在NRST引脚接一个10kΩ上拉电阻到3.3V然后接一个0.1μF电容到地即可。如果你看到仿真一段时候后程序“卡死”“跑飞”而复位引脚悬空多半就是这个原因。还有一个容易踩的坑是BOOT0和BOOT1引脚。在Proteus里STM32F103C8T6模型的BOOT0引脚默认可能悬空这会导致仿真上电后进入系统存储器模式而不是用户Flash模式程序跑不起来。你需要在BOOT0引脚接一个10kΩ下拉电阻到地BOOT1同样下拉这样保证从主Flash启动。这个坑如果不注意够你排查一个晚上的。3.3 把Hex文件加载到仿真芯片代码在Keil里编译通过后右键Proteus里的STM32芯片选择Edit Properties在Program File一栏选择编译输出目录下的.hex文件。注意Keil默认输出的是.axf文件需要先在Keil的Options for Target - Output里勾选Create HEX File才能在编译后生成.hex。加载完成后直接点运行LCD上应该出现实时温度。如果什么都没显示先别急着改代码按下图顺序排查电源轨配置、HEX文件是否正确加载、芯片是否进入用户Flash模式BOOT0是否拉低。这三个环节的经验排查顺序比任何代码调试都优先。4. 软件代码关键模块拆解读温度、出PWM、清按键代码部分是这个项目的灵魂。这套源码整体风格偏“教学向”模块划分清楚没有花哨的抽象和封装很适合对着学习。我看完源码后把几个关键实现挑出来逐一给你讲透。4.1 主循环与状态机结构主程序的核心结构大致是这样的int main(void) { Delay_Init(); GPIO_Config(); TIM_PWM_Init(); DS18B20_Init(); LCD1602_Init(); Key_Init(); uint8_t mode AUTO_MODE; int8_t target_temp 25; LCD_ShowString(0, 0, Temp:); LCD_ShowString(0, 1, Mode:); while (1) { // 每500ms读取一次温度避免频繁访问单总线 if (timer_flag_500ms) { timer_flag_500ms 0; current_temp DS18B20_GetTemp(); LCD_ShowTemp(current_temp); } key_value Key_Scan(); if (key_value ! KEY_NONE) { mode Key_Handle(key_value, mode, target_temp); } if (mode AUTO_MODE) { pwm_duty AutoFan_Map(current_temp, target_temp); } else { pwm_duty manual_duty; } TIM_SetCompare1(TIM2, pwm_duty); LCD_ShowMode(mode); } }这个结构的精髓在于主循环是“轮询事件标志位”的模式温度采集不阻塞在while循环里而是靠定时器置位一个标志按键扫描也不会用延时消抖把CPU占死。这跟很多初学者“一个Delay到底”的习惯完全不同——虽然这个项目复杂度不高但这种结构写出来就明显更有工程师味。4.2 DS18B20的时序这是整个项目最值得抠的代码DS18B20是单总线器件所有通信靠一根数据线在严格时序下完成。初始化、读位、写位都有具体的微秒级延时要求。在这套源码里作者用延时函数实现了这些时序而且给了比较充裕的时间余量。// DS18B20初始化 uint8_t DS18B20_Init(void) { uint8_t presence; DQ_GPIO_OUT(); DQ_SET_LOW(); Delay_Us(480); // 480us以上的低电平复位脉冲 DQ_SET_HIGH(); DQ_GPIO_IN(); Delay_Us(80); // 等待DS18B20拉低总线 presence DQ_READ(); Delay_Us(400); // 读完整时序余量 return presence; }这个时序有两点特别需要注意第一延时必须准确。Proteus仿真里的延时跟指令周期挂钩如果仿真速度被调得很慢延时也会被拉长导致时序不满足DS18B20模型的要求。这时候跑一次Temperature Read大概率会读出85这个默认值DS18B20上电复位后的默认温度值。这不是代码错是你仿真速度设太低了。第二端口方向切换不能少。DS18B20是双向数据线主机发送时要把GPIO配成输出接收时要赶紧切回输入。很多新手漏了GPIO方向切换导致总线电平被主机自己拉死永远读不到从机的响应。小技巧是在代码里封装一个DS18B20_WriteByte和DS18B20_ReadByte函数在函数内部处理方向切换而不是在外层分散管理。4.3 PWM调速和按键逻辑的细节PWM输出一般挂在TIM2或者TIM3的通道1上。STM32的TIM输出PWM本质是某个计数器在周期内计数比较寄存器CCR决定高电平的持续时间。占空比 CCR / ARR × 100%。比如设ARR为999CCR为500占空比就是50%。这套源码里PWM占空比是直接映射到LCD显示的转速等级如1挡到5挡而不是直接改CCR值给用户看。这种设计更符合直觉用户看到的是“当前3挡”而不是“占空比60%”。对应代码如下uint8_t AutoFan_Map(int8_t temp, int8_t target) { int8_t diff temp - target; if (diff -2) return 0; // 温度低于目标2℃以上停转 if (diff 8) return 100; // 温度高于目标8℃以上全速 // 在-1到7之间线性映射到10%~100% if (diff 0) return 10; return 10 (diff 1) * 13; // 简单比例映射 }按键逻辑上这套源码用了一个矩阵扫描的思路虽然只有2到4个独立按键核心在于按键扫描放在主循环中每次循环只扫描一次不做长延时消抖连续两次读到相同稳定状态才认为按键有效消抖时间大概十几毫秒长按功能没有在这套里做但如果你想扩展可以用定时器记录按键按下的持续时间来区分单击和长按。我曾经见过有人在这个项目里用“按键按下之后Delay 20ms”来做消抖结果主循环卡住温度更新和LCD刷新全部变慢。正确的做法是按键扫描和LCD刷新都在主循环里快速轮询只有确认按键事件是有效的那一次才去进入模式处理逻辑。5. 仿真跑不通时的排查链路我遇到过的几个“悬案”这部分是我最想写的。因为这项目看着简单但Proteus仿真里会出现几个非常典型的“悬案”网上搜半天也找不到明确答案。我把自己的排查经验整理成三条链路你按照这个顺序查能省不少时间。5.1 温度读数永远卡在85℃不动DS18B20上电后的寄存器复位值是85℃如果你读取到的温度一直是85说明单总线通信没有成功MCU读到的只是默认寄存器内容并不是实际温度。排查链路如下确认复位时序用示波器Proteus自带虚拟示波器观察DQ引脚初始化时是否有大于480μs的低电平脉冲然后主机释放总线DS18B20是否会在60μs左右拉低总线并保持约240μs。如果总线上没有这个应答脉冲说明DS18B20没收到复位信号。检查上拉电阻是否存在、阻值是否正确。DQ引脚悬空时总线默认状态无法被拉高时序会乱掉。检查GPIO方向配置。复位后主机必须把DQ切回输入模式才能读到DS18B20的应答脉冲。检查仿真速度。Proteus运行速度如果低于“实时”延时函数实际等待时间会变长DS18B20模型对超时容忍度有限建议把仿真速度调回Force Digital或恢复正常速度再测。5.2 风扇完全没反应但LCD温度和模式都正常LCD正常说明主程序在运行问题集中在PWM输出或电机驱动链路上。排查链路如下用虚拟示波器接在TIM PWM输出引脚比如PA0看有没有PWM波形。如果没有波形基本可以确定定时器配置问题可能是GPIO没有复用成PWM模式配置AFIO也可能是TIM的时钟没有使能。如果有波形但电机不转大概率是驱动电路的问题。仿真中三极管/MOS管连接方向错误、限流电阻太大、或者电机的参考地没有和MCU共地都会导致不转。如果以上都正常看看PWM通道选择。STM32的TIM1和TIM8是高级定时器开启PWM需要在软件上配置TIM_CtrlPWMOutputs用于主输出使能忘了这句话波形就是出不来。TIM2这种通用定时器没有这个问题这也是我建议新手先用TIM2的原因。5.3 LCD1602乱码、闪屏或干脆黑屏LCD1602是最老牌的显示模块但Proteus仿真里它反而最容易“闹脾气”。排查顺序寄存器初始化是否符合1602的时序要求特别是功能设置、显示开/关、清屏这三步之间要有延迟。如果上电后立即读写模块还没准备好就会乱码。确认是否配置为4线还是8线模式和接线是否一致。很多代码里用8线模式接线上却只接了D4-D7会导致显示数据错位。对比度引脚V0仿真中如果V0悬空屏上可能出现一排黑方块像乱码但其实是LCD偏压异常。把V0接地或接电位器中点通常会恢复。检查忙检测逻辑。如果代码用轮询BF位方式等待LCD空闲确认GPIO输入方向切换是否正确。仿真中BF位的时序是正常的但如果主机一直读不到BF位置0就会卡在等待循环里整屏不动。6. 从仿真搬到实物时你需要重新考虑的几件事Proteus仿真再漂亮最终还是要落到实物的。我自己经历过“仿真跑得好好的一上真板子全线罢工”的尴尬阶段所以想提前给你打几针预防针。仿真和实物之间至少有下面这几个差异是仿真完全无法体现的。6.1 三个典型的仿真-实物差异差异一DS18B20的时序宽容度。Proteus模型对时序的宽限期非常大延时差个几微秒基本没事。实物芯片不一样如果总线上经过连线长了、上拉电阻阻值偏大或偏小、主控GPIO驱动能力不足都要现场调整延时。建议在代码里把delay参数做成宏定义方便调试时统一修改。差异二电机转动时的电源纹波。仿真里的电源都是理想源电机怎么转电压都不变。实物上一颗5V风扇启动瞬间电流能到几百毫安甚至1A如果电源没有足够的滤波电容STM32和DS18B20的供电就会被拉低轻则温度读数跳变重则系统直接复位。经验做法是电机电源和主控电源要分开走线在电机两端并联一个100nF电容和一个小电解电容必要时加一个续流二极管吸收反向电动势。差异三LCD1602的延迟时间比Proteus模型更敏感。实物液晶模块的响应时间和初始化等待时间比仿真模型要严格代码里的初始化延时通常要在仿真基础上放大1.5到2倍才稳妥。特别是清屏命令0x01之后手册上要求1.64ms以上延时Proteus里可能几百微秒也能显示正常实物上就是各种乱码。6.2 我做实物时的“最小可行验证”顺序如果你打算把这套系统做成实物我建议你按照这个顺序来验证而不是一次性把所有模块全焊上去先把STM32最小系统板Keil的LED闪烁程序跑通确认芯片能工作、下载器正常然后接LCD1602只显示静态字符串确认接线和初始化正确再接DS18B20用串口把温度数据打出来不开风扇确认温度读数准确、稳定最后才接MOS管和风扇测试PWM控制和按键切换。这个顺序每一步失败时都能把问题范围缩小到一个模块内而不是面对一整块不工作的板子无从下手。这也是我每次做嵌入式项目都坚持的流程。另外提一句Proteus里的STM32是纯逻辑模型但你真做实物的时候如果遇到烧录一次后第二次下载不了程序先看看BOOT0引脚有没有被外部电路拉高。相信我这个坑比你想象的常见得多。本文还有配套的精品资源点击获取