尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

STM32智能温控风扇系统:从Proteus仿真到代码实现

发布时间:2026/9/2 2:17:39

资讯中心
01
ARTICLE

STM32智能温控风扇系统:从Proteus仿真到代码实现

STM32智能温控风扇系统:从Proteus仿真到代码实现
简介基于STM32单片机的智能温控风扇控制系统完整项目资源非常适合嵌入式初学者、高校学生完成课程设计或毕业设计时参考学习。系统以STM32F103为核心处理器通过温度传感器实时采集环境温度利用PWM脉宽调制技术控制风扇转速涵盖从硬件选型、电路设计到C语言程序编写的完整开发流程。压缩包共155个文件以C源码、H头文件、Proteus仿真工程、HEX烧录文件、原理图文档为主整体大小6.09MB结构清晰可直接打开仿真工程验证功能。已有2053人学习下载附带的开发文档和调试配置文件能帮助读者快速理解温控算法与模块化编程思路对于需要二次开发的工程师也可参考其中ADC采集、定时器PWM输出及中断处理等核心代码进行功能扩展。 做了几个温控小项目之后回过头看这个基于STM32的智能温控风扇控制系统依然觉得它是非常适合新手入门的综合练习。它不像纯点灯实验那样只涉及GPIO操作也不像完整物联网项目那样上来就要怼协议栈而是把ADC采集、传感器读取、PWM输出、显示交互、按键处理全部串在一起正好覆盖了单片机开发的几大基本功。这篇文章我就把这套系统的完整设计思路、Proteus仿真搭建过程、核心代码实现以及调试中遇到的那些坑一次性讲清楚方便你直接照着复现也能理解每个环节为什么要这么做。1. 项目整体设计与方案选型1.1 系统要解决什么问题先搞清楚这套系统的本质需求环境温度升高时风扇能自动加速温度降下来后风扇自动减速或者停止同时能够实时显示当前温度并支持手动设定目标温度阈值。听起来简单但放到实际工程里就涉及一连串决策——用什么传感器测温、用哪个通道采样、用哪种方式驱动风扇、温度阈值怎么存储和修改。我选择STMF103系列作为主控原因是它的ADC、定时器PWM、I2C/单总线外设齐全而且Proteus里对STM32F103系列的仿真支持已经比较成熟。相比用51单片机做温控风扇STM32的优势主要体现在多通道ADC采样更稳定、PWM分辨率更高16位定时器、以及代码后续扩展空间大——比如以后想加个OLED显示或者Wi-Fi模块资源完全够用。这套方案的实际应用场景很明确嵌入式课程设计、电子竞赛热身项目、或者单纯想系统练一遍STM32外设开发的人。它的价值不在于风扇本身而在于把“传感器-处理器-执行器”这条完整链路走通这套方法论放到恒温箱、智能晾衣架、机房散热系统里都是一样的。1.2 关键器件的选择逻辑温度传感器Proteus里最常用的是LM35和DS18B20。LM35是模拟输出接ADC直接读电压换算温度DS18B20是数字单总线协议需要自己写时序。我做的是仿真版本用LM35在Proteus里仿真更直观调整电位器就能模拟温度变化不需要纠结时序问题。实际做硬件时如果追求精度和抗干扰可以直接换DS18B20代码里保留模拟量采集的抽象接口就行。风扇驱动Proteus仿真中用直流电机代表风扇通过PWM调速。关键在于电机不能直接接在STM32的GPIO上必须加驱动级。硬件上正经做法是用MOS管或电机驱动芯片仿真里可以用PWM信号去控制一个电压控制开关或者直接接电机——前提是逻辑电平匹配这个后面会详细说明。显示与交互1602 LCD显示温度和风扇档位按键用来切换手动/自动模式、调节上下限阈值。选1602而不是OLED一方面是因为Proteus对1602的支持非常稳定另一方面1602作为最经典的字符屏能逼你把字符映射和光标控制搞清楚比用现成库刷OLED学到的东西更多。2. 硬件电路设计与关键参数计算2.1 STM32F103C8核心电路Proteus里使用STM32F103C8芯片时首先要确认BOOT0和BOOT1引脚的接法还要在芯片属性里设置好启动模式。更关键的一步是电源和地的处理——Proteus中STM32的VDD/VDDA必须全部接3.3VVSS/VSSA接GND否则仿真直接报错或者芯片无法运行。复位电路我用经典的RC复位10kΩ上拉电阻加上100nF电容到地上电时NRST引脚保持低电平一段时间然后被拉高完成复位。这个电路在硬件上是标配仿真里虽然不点复位按钮也能跑但保留这个电路能保证后续烧录和调试逻辑一致。晶振电路我要特别提醒一下Proteus仿真STM32时外部晶振经常不工作导致仿真卡死我实测下来最稳的做法是直接用芯片内部的HSI时钟8MHz代码里配置系统时钟时走RCC_PLLConfig或者干脆用默认的HSI。如果你非要用外部晶振请在Proteus里给晶振添加“Digital”激励源但说实话没必要仿真阶段用内部时钟足够了。2.2 LM35测温电路与温度换算LM35是一个非常经典的模拟温度传感器输出电压与摄氏温度呈线性关系0°C时输出0V每升高1°C输出电压增加10mV。也就是说25°C时输出250mV。在Proteus里LM35的测温范围是-55°C到150°C我不建议直接拿它的输出接STM32的ADC引脚——因为STM32的ADC参考电压是3.3V而LM35在室温下的输出电压只有几百毫伏直接采样虽然也能用但ADC的分辨率会浪费很多。最规范的接法是在LM35输出端加一个同相放大电路用运算放大器把信号放大3倍左右让0-100°C对应的电压范围扩展到0-3V充分利用ADC的满量程。放大电路典型参数运放用LM324或者LM358同相放大倍数Av1Rf/R1取R110kΩRf20kΩ放大倍数为3倍。此时ADC采样的电压换算公式为float voltage (float)adc_value * 3.3f / 4095.0f; // 12位ADC float temperature voltage / 0.03f; // 每10mV对应1°C放大3倍后每30mV对应1°C如果你不想加运放直接ADC采样LM35原始输出也行只是分辨率低一些比如在25°C时原始电压250mV对应12位ADC的数值约310温度分辨率约为0.8°C做演示足够但不够“精致”。我在一开始做的时候偷懒没加运放后来发现温度显示跳变明显加了放大电路后稳定很多。2.3 电机驱动与PWM调速直流电机的PWM调速原理是改变MOS管栅极的PWM占空比从而改变电机两端的平均电压。Proteus仿真中不直接接MOS管也行——可以直接把PWM信号经过一个“电压控制开关”模型接到电机上但我建议还是按真实电路画一个N沟道MOS管比如IRF540加上续流二极管1N4007这样仿真更接近实际硬件后面做实物时电路可以直接平移过去。PWM频率的选择也有讲究。电机驱动频率太低会有明显噪音和抖动太高则MOS管开关损耗增大工程上常用20kHz左右。STM32定时器输出PWM时设置PSC为72-1定时器时钟72MHzARR设置为50-1这样PWM频率就是72MHz/(72×50)20kHz。占空比通过CCR调节0到100对应0%到100%转速void PWM_Init(void) { // 以TIM2为例 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // PA0作为PWM输出 GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period 50 - 1; // ARR TIM_TimeBaseStructure.TIM_Prescaler 72 - 1; // PSC TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 0; // 初始占空比0 TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM2, TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_Cmd(TIM2, ENABLE); }3. Proteus仿真搭建全程实录3.1 工程创建与芯片配置打开Proteus 8 Professional新建工程时直接搜索STM32F103C8。芯片放置到原理图后双击芯片进入属性设置有一个非常关键的选项是“Clock Frequency”Proteus里默认可能不是8MHz你要手动改成8M否则后面定时器PWM频率算出来全不对。接着放置LM35、电位器用来模拟温度变化、LM324运放、直流电机、1602LCD、按键、电阻和MOS管。这里有一个经验Proteus的元件搜索关键词要准确直流电机搜“MOTOR-DC”1602搜“LM016L”或“LCD1602”运放搜“LM324”N沟道MOS管搜“IRF540”。电源和地的连接方式也容易踩坑。Proteus仿真STM32时VDD/VDDA接3.3V网络但注意LM35和运放需要5V供电所以整个电路里要有3.3V和5V两个电源网络可以通过添加“VCC”和“5V”终端标签来区分。我在第一次布线时直接全部接5VSTM32直接冒烟仿真里表现为芯片不工作后来改成3.3V才正常。3.2 模块间连接要点ADC通道LM35放大后的输出电压接PA1ADC1的通道1PA0我留给了PWM输出避免信号冲突。LCD1602的RS、RW、EN、D4-D7分别接PB0-PB5这种4线接法可以省4个引脚。RW引脚直接接地只写不读简化操作。按键三个按键分别接PA2、PA3、PA4另一端接3.3VGPIO配置为上拉输入——这里要记住按键按下为高电平逻辑上别弄反。也有教程按下为低电平用内部下拉都行但务必和代码保持一致。电机驱动PA0的PWM输出接MOSFET栅极源极接地漏极接电机一端电机另一端接5V电机两端反向并联续流二极管。连接完成后先别急着写代码。Proteus里可以先给LM35旁边放一个电位器用电压表测量LM35输出转动电位器观察电压变化这能确认传感器模型是否正常工作。这一步看似多余实际能省很多后面联调的时间。3.3 烧录与仿真运行设置Proteus仿真STM32需要加载hex文件而STM32的hex文件由Keil MDK生成。在Keil工程里点击Options for Target在Output选项卡勾选“Create HEX File”编译后会生成hex文件。然后在Proteus里双击STM32芯片在Program File一栏选择这个hex文件。这里有个非常常见的坑如果你的Keil工程用的设备不是STM32F103C8或者Flash大小设置不对生成的hex文件在Proteus里可能无法运行。解决办法是在Keil的Device选项卡里确保选择的芯片型号与Proteus一致比如STM32F103C8就选STM32F103C8不要选成STM32F103C8T6的特殊变体除非你有充分的理由。仿真启动后如果一切正常1602 LCD上会显示实时温度和当前风扇档位。此时调节电位器模拟温度变化温度低于下限阈值时风扇停止温度落在上下限之间时风扇低速运转温度超过上限时风扇全速运转。这就是完整的温控逻辑。4. 核心代码实现与逻辑优化4.1 系统主循环与温控策略整套代码主要分为四块ADC采集、LCD显示、按键扫描、PWM输出。主循环采用“状态机轮询”的方式不用中断嵌套方便调试。温控部分我采用的是分段式PID思想和多档调速结合的策略。最简单的实现是双阈值比较温度低于下限T_low时关风扇超过上限T_high时满转中间按比例调速。但我实际做的时候发现直接把温度映射到PWM占空比更平滑uint16_t calculate_duty(float temp, float t_low, float t_high) { if (temp t_low) return 0; if (temp t_high) return PWM_PERIOD; // 满占空比 // 线性映射温度在范围内时占空比从0线性增长到最大 float ratio (temp - t_low) / (t_high - t_low); return (uint16_t)(ratio * PWM_PERIOD); }为了让风扇转速变化更自然我在主循环里加了软件滤波每200ms采样一次温度取最近5次采样值的平均值再用于控制。这个滤波虽然简单但能有效避免ADC采样抖动导致的转速跳动。如果你追求更好的动态性能可以在此基础上升级成增量式PID但针对风扇这种大惯性被控对象温度变化本来就慢比例控制已经够用了。4.2 ADC采样与滤波实现ADC采样采用DMA方式比轮询更高效但为了让新手能看懂我先用轮询实现了一遍核心代码如下uint16_t ADC_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) RESET); return ADC_GetConversionValue(ADC1); } float Read_Temperature(void) { uint32_t sum 0; for (uint8_t i 0; i 5; i) { sum ADC_GetValue(); delay_ms(10); } uint16_t avg sum / 5; float voltage (float)avg * 3.3f / 4095.0f; float temp voltage / 0.03f; // 放大3倍后灵敏度为30mV/°C return temp; }需要注意的细节初始化ADC时要选择采样时间为55.5周期或更长时间因为STM32的ADC输入阻抗不够高采样时间太短会导致采样电容充不满实测电压值会偏低。另外ADC_SoftwareStartConvCmd必须在每次转换前重新调用否则只转换一次。4.3 LCD1602驱动与按键处理1602的驱动代码大家应该很熟了我只说两个容易出错的地方。第一4线模式下初始化时序必须严格遵循HD44780手册上电后至少要等待40ms以上然后依次发送0x30、0x30、0x30再切换到4线模式。如果你直接发送0x28很多屏会不工作。第二写数据和写命令之间要加足够延时一般在Proteus里仿真速度很快但真实硬件上如果延时太短会丢数据我习惯每条指令后加delay_us(50)写数据前检查Busy标志。按键处理用简单的状态机防抖。Proteus里按键不会像真实硬件那样产生机械抖动但代码上还是保留防抖逻辑保证移植到真实板卡时不用返工。按键功能我设计了三个模式切换键自动/手动、阈值加、阈值减。在手动模式下按键直接控制风扇速度档位自动模式下按键调整温度上下限。5. 常见问题、排查思路与避坑指南5.1 仿真常见问题速查表现象可能原因解决方案仿真无法启动提示芯片无电源VDDA/VDD未接3.3V检查所有电源引脚是否连接正确温度显示不变LM35输出未接入ADC通道或ADC初始化通道错误用电压表测量ADC引脚电压确认电压变化风扇转速始终不变PWM引脚复用配置错误或CCR未更新确认GPIO模式为AF_PP确认使用了正确的TIM通道LCD显示乱码初始化时序不对按HD44780时序重新初始化检查4线数据引脚连接按键无效上拉/下拉配置和按键接法不一致确认按键按下时电平逻辑与代码判断一致仿真运行极慢时钟频率配置不当或采样循环过密检查芯片属性Clock Frequency适当降低ADC采样频率5.2 我实测踩过的三个坑第一个坑是PWM通道选择。STM32的同一定时器不同通道对应不同引脚TIM2_CH1是PA0TIM2_CH2是PA1如果不小心把GPIO配置成PA1但用TIM2_CH1输出结果就是PA1永远是低电平。所以表格里我特意写了“确认使用的TIM通道”这个错误不仔细排查根本发现不了。第二个坑是Proteus中电机模型的响应速度。Proteus里的直流电机模型转动惯量很大PWM占空比变化后转速变化有明显的“延迟”这不是你的控制逻辑有问题而是模型的物理特性。为了验证PWM输出是否正确最好在电机前端加一个电压表或者示波器探针直接观察PWM波形的占空比变化。第三个坑是LM35的模型方向和输出电压范围。Proteus里的LM35默认输出有直流偏置有些版本库里LM35在0°C时会有零点几伏的偏置导致你换算温度时偏差很大。最直接的办法是先用温度源标定把LM35放到温度设置为25°C的环境在Proteus中通过修改属性或放置温度源然后用ADC读出数值反推公式中的系数不要去硬套数据手册的10mV/°C。5.3 从仿真到实物的过渡建议如果你打算在Proteus仿真跑通后做成实物有几个地方需要额外注意。首先仿真里LM35的输出可以直接接STM32但实物中建议加一个100nF滤波电容在ADC引脚对地减小电源噪声干扰。其次实物中的电机驱动绝对不能直接接GPIO一定要用三极管或者MOS管并且电机要加续流二极管否则关断瞬间的反电动势会打坏芯片。第三实物调试时LCD对比度需要通过外接电位器调整Proteus里不会出现对比度问题但实物上这个电位器必不可少。温控精度方面仿真和实物会有差别。Proteus里一切数据都是理想化的但实际环境中LM35周围可能有其他发热元件测温点位置不同温度读数可能差好几度。我通常在实物项目中把传感器放得离风扇远一点避免风扇气流直接吹到传感器导致测的是“假温度”。6. 效果演示与后续扩展仿真跑起来后完整的运作效果是这样的1602上第一行显示“Temp: 28C”第二行显示“Fan: Auto 40%”。温度低于20°C时风扇停转20到30°C之间线性调速超过30°C满速运转。按键可以调整上下限调整后设置值写入Flash模拟EEPROM区域下次上电自动加载。如果想在这个项目基础上继续深化我建议按下面几个方向做扩展升级为闭环PID温控目前是线性比例控制加上积分和微分后可以让温度稳定在设定值附近波动更小适应负载变化的鲁棒性也更强。增加OLED显示和曲线绘制把温度历史数据画成趋势曲线直观观察温控效果这个需求在Proteus里用OLED模块也能仿真。加入Wi-Fi模块做远程监控用ESP8266通过串口把温度数据和风扇状态上传到云平台。STM32这边只需扩展一个USART的代码核心温控逻辑不用变。换成DS18B20做多节点测温用单总线协议挂多个DS18B20实现多点温度采集更接近机房或温室的实际需求。这套系统我用“有没有实现单闭环控制”作为分水岭——完成了闭环控制你就从单纯的“会写外设驱动”进阶到“会做控制系统”这是嵌入式开发中非常关键的一步。Proteus仿真虽然不能完全替代实物硬件调试但在这类控制逻辑验证、参数调节和功能演示场景下它的效率是真的高。我的建议是先仿真摸清整个系统的行为特性再拿着明确的设计方案去做实物能少走一大半弯路。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。