简介:这套基于单片机的智能风扇控制系统设计资源,适合电子信息、自动化等专业学生完成课程设计或毕业设计时参考。系统以单片机为核心,结合温度传感器、红外传感器、继电器与变频器,实现根据环境温度自动调档、室内无人自动关闭风扇的完整控制逻辑。压缩包共20个文件,约1.59MB,包含C语言源程序、Keil工程文件、Proteus仿真工程(pdsprj/pdsbak)、Hex烧录文件及课设报告模板(pdf/doc),覆盖从程序编写、仿真调试到文档撰写的全流程。目前已有1105人学习下载,可帮助学习者快速理解温控风扇的系统架构、传感器采集与电机调速思路,也可直接参照工程结构进行二次开发或改装。对于需要提交课程设计报告、演示实物或仿真效果的同学,这套资料能提供较为完整的参考方案。
1. 从“遥控风扇”到“自动风扇”:这个设计到底在解决什么
你手上有一个智能风扇控制系统,核心就一件事:让风扇不再靠人手拧档位,而是根据温度自动决定转多快,同时在手动模式下保留人对转速的绝对控制权。这类设计在课程设计和毕业设计里出现频率极高,因为它的技术栈覆盖非常典型:一颗单片机做逻辑核心,一个温度传感器采集环境温度,一个按键矩阵接收用户意图,一路 PWM 输出驱动电机,再加一个显示器告诉用户当前状态。把它做出来,等于把单片机系统里的输入、输出、中断、定时器、通信协议全走了一遍。
这篇文章不打算给你一份“代抄代过”的完整工程包,而是把这类设计最常见的实现路径讲清楚:主控怎么选、传感器用哪种、PWM 调速怎么调才不抖、自动和手动模式怎么切换不打架,以及最后怎么验证你的系统真的可靠。无论你手里是 STC89C52 还是 STM32,思路都能平移过去。新手可以照着步骤搭出一个能跑的原型,熟手可以重点看模式切换和调速平滑性这几节的边界条件。
2. 智能风扇系统的方案选型:主控、传感器与驱动电路的搭配逻辑
2.1 主控选型:51 内核还是 Cortex-M 内核
这类设计最常见的两个选择是 STC89C52(或同类的经典 51 内核芯片)和 STM32F103 系列。前者便宜、资料多、用 Keil5 写 C 代码直接下载,Proteus 仿真也有现成模型,做课程设计完全够用;后者性能强,适合你要加 LCD 大屏、Wi-Fi 模块或者闭环控制等复杂功能时选用。我不推荐一上来就选 STM32,除非你确实有扩展需求,因为 51 内核在处理 DS18B20 这类单总线协议的时序时足够从容,而 PWM 调速用定时器中断就能实现,没必要引入 Cortex-M 的复杂时钟树。
主频、Flash、GPIO 数量决定了你的硬件架构。以 STC89C52 为例,12MHz 晶振下机器周期是 1μs,DS18B20 的时序要求微秒级延时,这个精度完全可达;如果换成 STC15 系列这种 1T 内核,反而要重新计算延时周期,容易掉进时序坑。你的设计文档里如果没指定芯片,我建议优先选 STC89C52,理由是它的 I/O 口是准双向口,驱动能力强,直接点亮 LED、读取按键都不需要额外电路,能把外围电路复杂度压到最低。
下表是我在这次设计中常用的选型参照,适合写进设计报告的前期论证部分:
| 模块 | 推荐型号/方案 | 选型理由 | 替代方案 |
|---|---|---|---|
| 主控 | STC89C52RC | 资料多、仿真模型全、5V 供电与传感器电平匹配 | STM32F103C8T6 |
| 温度采集 | DS18B20 | 单总线协议、仅占用 1 个 I/O 口、测量范围覆盖室温场景 | 热敏电阻 + ADC |
| 显示 | LCD1602 | 字符型液晶,驱动简单,能显示温度与档位 | 4 位数码管 |
| 电机驱动 | ULN2003 达林顿管阵列 | 内置续流二极管,适配 5V 直流电机 | 三极管 + 继电器 |
| 调速方式 | 定时器输出 PWM | 软件生成,频率可控 | 专用 PWM 芯片 |
提示:如果你的电机是 220V 交流电机,达林顿管方案直接失效,需要换成可控硅或继电器驱动,且要注意强电隔离。课程设计题目没说电机类型时,默认按 5V 直流电机处理,这也是 Proteus 仿真里最常见的情况。
2.2 温度采样方案:DS18B20 与热敏电阻的取舍
DS18B20 是这类设计事实上的标准答案。它把温度传感、ADC 转换、单总线通信全封装在一个 TO-92 管子里,单片机只需要一根 I/O 线就能读到 12 位分辨率温度数据。相比之下,热敏电阻方案需要你自己搭分压电路,再用单片机内置 ADC 采样,然后查表转换,精度和线性度都不如 DS18B20,只适合用来展示“你会用 ADC”这种附加技能点。
DS18B20 的供电有两种接法:寄生供电和外部供电。设计里我一般用外部供电,3 根线连接干净利落,数据线上拉一个 4.7kΩ 电阻到 VCC,这是数据手册规定的标准接法,别省这个电阻——省了会导致通信不稳定,尤其是线缆稍长或者噪声稍大时,读回来的温度会偶发跳变。如果你画 PCB,把上拉电阻放在靠近单片机引脚的位置,比放在传感器旁边效果更好。
读取 DS18B20 的核心是严格按协议时序操作:初始化时主机拉低总线至少 480μs,然后释放并检测从机的存在脉冲;写时序中,写 0 需要拉低总线 60μs 后释放,写 1 则拉低后迅速释放;读时序同样要精确控制采样点。一个常见错误是把延时函数用for循环空转实现,换一颗晶振或者换一个编译优化等级,时序就全变了,所以调试时优先用逻辑分析仪看总线波形,而不是盯着温度值猜。
3. 智能风扇的硬件电路设计:最小系统、传感器接口与电机驱动电路
3.1 最小系统与复位电路:稳定性的第一道防线
单片机最小系统在 Proteus 仿真里经常被简化成只画芯片和电源,但做实物时必须补齐三部分:晶振电路、复位电路、去耦电容。晶振用 12MHz,两个 30pF 负载电容分别接地,电容值不需要高精度,瓷片电容即可;复位电路用 10μF 电解电容串联 10kΩ 电阻,接到 RST 引脚,这个经典组合能保证上电时 RST 脚保持约 100ms 的高电平,让单片机可靠复位。按键复位是可选功能,把一个轻触开关并联在复位电容两端即可。
去耦电容是很多人容易忽略的细节。每个 IC 的电源引脚旁边放一个 0.1μF 陶瓷电容,靠近引脚放置,作用是滤除电源线上的高频噪声。智能风扇系统里电机是最大的干扰源,电刷换向时会产生火花噪声,通过电源线传导回单片机,轻则造成程序跑飞,重则直接复位。我在做实物时还会在电机电源两端并一个 0.1μF 电容和一个 100μF 电解电容,并且在 PCB 上把电机地线和单片机器件地线分开走,最后单点汇合,这样抗干扰能力会明显上一个台阶。
硬件引脚分配上,我一般遵循“固定功能口优先”的原则。DS18B20 的数据口独占一个 I/O 口,LCD1602 的数据口占用 P0 口并外接 10kΩ 排阻上拉,因为 P0 口是开漏输出,必须上拉才能输出高电平;按键用 P1 口,P3 口留给定时器外部中断和串口下载。注意 P3.0 和 P3.1 同时是串口引脚,下载程序时要保证没有外设占用这两个口,否则下载会失败。
3.2 传感器接口与电机驱动电路:电平匹配与续流保护
DS18B20 的接口电路之前提过,3 根线加一个 4.7kΩ 上拉电阻,这里不再重复。需要强调的是,DS18B20 的数据线与单片机 I/O 口直连之前,要确认传感器是 3.3V 还是 5V 版本——如果你用的是 STM32 这类 3.3V 主控,而传感器是 5V 版本,数据线高电平是 5V,会灌进单片机引脚造成永久损伤。常见的做法是用两个 MOS 管做电平转换,或者直接选 3.3V 版本的 DS18B20。
电机驱动电路是硬件设计里最容易出问题的地方。5V 直流电机的启动电流可达正常工作电流的 5 到 8 倍,如果你用单片机 I/O 口直接驱动,会把引脚烧掉。ULN2003 达林顿管阵列可以解决这个问题:它内部集成 7 路达林顿对管,每一路能承受最大 500mA 电流,并且内置了续流二极管,可以吸收感性负载断电时产生的反向电动势。这里补充一点,不要小看这个续流二极管——电机是感性负载,断电瞬间会产生几十伏的尖峰电压,没有续流保护的话,这个尖峰打在晶体管或者单片机上,击穿往往是一次性的。
如果你没有 ULN2003,用三极管(比如 S8050)搭驱动电路也可以,但需要在电机两端反向并联一个 1N4007 二极管完成续流功能。信号从单片机出来先过 1kΩ 基极限流电阻,再接三极管基极,集电极接电机,发射极接地,这样接法才是正确的低边驱动。电机调速的 PWM 信号不是方波直通电机,而是通过控制三极管或 ULN2003 的通断时间比例来改变电机平均电压,这一点在下一章的软件设计里会详细展开。
4. 智能风扇的软件核心实现:单总线温度读取与 PWM 调速逻辑
4.1 单总线协议驱动:DS18B20 时序的代码落地
DS18B20 的驱动代码是软件部分第一个难点,也是很多人卡住的地方。完整流程分四步:初始化、写命令(跳过 ROM 0xCC)、触发温度转换(0x44)、读取暂存器(0xBE,读 9 个字节)。每次上电后需要延时等转换完成,12 位分辨率下最大转换时间是 750ms,你可以延时 750ms 再读,但更聪明的做法是循环读取忙标志位,温度转换完成后传感器会自动恢复高电平,省下的时间可以给显示刷新用。
下面是初始化函数的典型实现,注意延时用的是_nop_()配合空循环,这种写法在课程设计中最常见:
/* DS18B20 复位函数:返回 0 表示存在,1 表示无应答 */ bit DS18B20_Reset(void) { bit presence; DQ = 0; // 主机拉低总线 delay_us(500); // 至少保持 480us,这里留余量 DQ = 1; // 释放总线 delay_us(60); // 等待从机拉低信号 presence = DQ; // 采样:存在脉冲为低电平 delay_us(240); // 时序结束,等待下一个操作 return presence; }delay_us()在 12MHz 晶振下,一个空循环大约耗时 8 个机器周期,即 8μs,所以循环 60 次大约是 500μs。写时序和读时序同样依赖这个延时函数的准确性,如果你换了一颗不同主频的芯片,第一件事就是重新校准延时周期。另外注意,复位函数的返回值逻辑上容易搞反——DQ 被拉低表示器件应答,存在脉冲是低有高无,所以返回 0 代表成功,这个细节在实际调试时能帮你节省大量排查时间。
温度转换命令发出后,读取到的原始数据是 16 位有符号数,低 4 位是小数部分,高 5 位是符号位。把高字节左移 8 位加上低字节得到一个 16 位数,,再右移 4 位得到整数部分温度值。25 度时读到的原始值是 0x0190,右移 4 位得到 0x19 即十进制的 25。如果你要显示 25.5 度,就取低 4 位除以 16 换算成小数部分,但大多数课程设计只需要整数精度,而且整数运算在 51 单片机上速度更快。
4.2 调速核心:定时器中断实现可调占空比的 PWM 波
PWM 调速的原理是控制电机两端平均电压,占空比越高,平均电压越高,转速越快。51 内核没有硬件 PWM 模块,要靠定时器中断模拟。我的实现思路是:定时器 0 产生一个固定周期的中断,比如 100μs,每 100 次中断构成一个 10ms 的 PWM 周期;在中断服务函数里维护一个计数器,计数器小于占空比设定值时输出高电平,否则输出低电平。
/* 定时器0中断服务函数:软件PWM生成 */ void Timer0_ISR(void) interrupt 1 { static unsigned int pwm_cnt = 0; pwm_cnt++; if (pwm_cnt >= PWM_PERIOD) // PWM_PERIOD = 100,周期10ms { pwm_cnt = 0; PWM_PIN = 1; // 一个周期开始,先输出高 } if (pwm_cnt >= current_duty) // current_duty为当前占空比 { PWM_PIN = 0; // 到达占空比设定值,输出低 } }这里的current_duty是全局变量,取值范围 0 到 100,对应 0% 到 100% 占空比。当current_duty为 0 时,pwm_cnt从 0 开始就大于等于 0,输出低电平,电机不转;当current_duty为 100 时,pwm_cnt永远不会大于等于 100,输出持续高电平,电机全速。在中断里更新输出状态,而不在主循环里用延时翻转引脚,好处是输出波形不受主循环其他任务影响,这也是“用定时器保证实时性”的典型应用,和你在其他单片机上写 LED 流水灯控制程序的思路是一脉相承的。
PWM 频率的选择有讲究。频率太低,比如 10Hz,电机转动会一顿一顿的,噪声大且调速不平滑;频率太高,比如超过 20kHz,进入超声波频段,驱动器开关损耗变大,对三极管驱动方式来说会造成过热。我一般把 PWM 周期设在 10ms 到 20ms 之间,即 50Hz 到 100Hz,这是直流电机调速最常见的区间,人耳听不到明显的噪音,开关损耗也可接受。如果你的应用换成 DC 无刷电机或者带编码器的减速电机,频率需要重新调整,但 51 的软件模拟 PWM 在高频下会大量占用中断资源,量力而行。
4.3 自动调速策略:分段调速与线性映射的选择
自动模式是整个系统智能化的核心。常见策略有两种:分段开关式调速和线性映射式调速。分段式是把温度范围划成几个区间,比如低于 20℃ 停转,20℃ 到 25℃ 一档,25℃ 到 30℃ 二档,高于 30℃ 三档,实现简单,代码是几个if-else判断,占空比直接取固定值,比如 25%、50%、75%。线性映射则用一条比例曲线把温度对应到连续占空比,体验更平滑,但要用浮点运算,在 51 上会拖慢响应速度,通常用查表或者整数运算近似实现。
我自己的建议是分段式起步,线性映射作为进阶优化。分段式的好处还在于便于设定滞回区间。你可以为每个档位设置上下两个切换边界,例如温度从低到高升到 25℃ 时切换到二档,但从高到低回落到 23℃ 时才切回一档,这个 2℃ 的差值就是滞回区间。它的作用是避免温度在临界点附近波动时频繁切换档位,让电机转速忽高忽低,既影响舒适度也损害电机寿命。这个思路在工业控制里广泛使用,写进设计文档是一处加分项。
自动模式和手动模式的切换逻辑要注意一个边界条件:切换瞬间风扇转速不要突变。做法是在切换模式时把current_duty渐进调整到目标值,每次在主循环里递增或递减 1,而不是直接赋值,这样就能避免电流冲击。这个细节很多人不会注意,但实测效果差异非常明显,手动挡切自动挡的一瞬间电机“啪”的抖动,和缓缓平滑过渡,用户感受完全不一样。
5. 显示、按键与模式切换:让用户能看懂、能控制
5.1 LCD1602 显示驱动:温度、档位、模式同屏刷新
LCD1602 是 16 列 2 行的字符液晶,一次显示 32 个字符,对于温度、档位、模式这三组信息完全够用。驱动时序上,RS 引脚控制数据/命令选择,RW 接地固定为写模式,E 引脚是使能信号。4 位数据总线模式可以省 4 个 I/O 口,但初始化时序比 8 位模式复杂,第一次调试时用 8 位模式更容易成功,等你把显示逻辑跑通了再改 4 位模式也不迟。每次写命令或数据前,都要先读忙标志位 BF 或延时等待,时序不对时最常见的故障现象是屏幕显示乱码或者干脆不亮。
显示内容布局上,第一行显示温度,第二行显示模式和档位,我一般会整理成下面这样的格式,方便用户扫一眼就抓到关键信息:
/* 显示刷新:在LCD第二行组合模式与档位信息 */ sprintf(disp_buf, "M:%c Spd:%d%%", mode_char, duty_val); LCD1602_ShowString(0, 1, disp_buf); // 第0列第1行mode_char在自动模式下为'A',手动模式下为'M',duty_val是当前占空比百分数。刷新逻辑上要注意控制频率,不要在每次温度读取完成后立刻刷新屏幕,因为 DS18B20 转换需要时间,刷新太频繁反而会闪烁。我的做法是设置一个 200ms 的刷新标志,主循环检测到标志置位才执行一次显示更新。
5.2 按键处理:独立按键的消抖与长按/短按区分
按键是这个系统里唯一的人机交互入口,最少需要 3 个:模式切换键、档位加、档位减。按键消抖是必须处理的环节,机械按键按下和释放时会有约 10ms 到 20ms 的抖动,如果不消抖,一次按下可能被识别成多次。最简单可靠的方式是确认法:检测到按键按下后延时 10ms 再读一次,确认还是按下就认定有效,释放时同样处理。
/* 按键扫描:带消抖和松手检测,返回按键编号 */ unsigned char Key_Scan(void) { if (MODE_KEY == 0) // 检测到按下 { delay_ms(10); // 延时消抖 if (MODE_KEY == 0) { while (MODE_KEY == 0); // 等待松手 return KEY_MODE; } } return KEY_NONE; }手动模式下连续按加键,档位要逐级上升,但到底升到 100% 还是应该留一点余量?实践中有两个常见做法:一是直接允许调整到 100%,让用户获得全速档;二是限制到 90%,因为电机在 100% 和 90% 占空比下转速差距并不明显,却能给电源和驱动电路留出裕量。我更倾向于后者,并且在到顶之后再按加键时不做任何操作,而不是回卷到最小值——回卷这种循环模式看起来很炫,但在风扇控制这种场景下容易造成误操作。
长按连续加档是提升体验的一个小技巧。检测到按键有效后启动一个定时器,如果按键在 500ms 内没有松开,就每隔 100ms 自动加一档,直到松开或者到 90% 上限。这个功能不是必须的,但做出来以后能明显感觉操作效率提升。实现时注意按键扫描函数要在主循环里频繁调用,别在长按期间阻塞了 DS18B20 的温度读取和 PWM 更新。
6. 调试与验证:用 Proteus 仿真、串口监视器和看门狗把系统做稳
6.1 Proteus 仿真下最容易踩的两个时序坑
Proteus 仿真是课程设计最常用的验证手段,但仿真环境毕竟不是真实硬件,有两个坑值得留意。第一个坑是 DS18B20 仿真模型和真实芯片的启动时间不一致,仿真里温度转换结果几乎是瞬间就绪的,如果你的代码用固定延时 750ms 再读,仿真能过,但实物上如果晶振不准或者延时误差累积,有时就会读到 85℃ 这个错误值——这是 DS18B20 上电后的默认温度,说明你读到了暂存器里的初始值而不是真实转换值。第二个坑是仿真默认不模拟电机换向噪声,也不会因为电源干扰导致单片机复位,所以仿真跑得再稳,都不代表实物没问题,一定要留出实物调试的时间。
把串口用起来是加快调试速度的关键手段。STC89C52 自带 UART,通过 USB 转 TTL 模块连到电脑,可以用串口监视器打印温度值、占空比设定值、模式状态这些内部变量,比盯着 LCD1602 猜状态快得多。在调试阶段,我会在每个模式切换的地方打印一条日志,比如自动模式切到手动的瞬间发生了什么,温度读到了多少,这样能把出问题的模块缩小到具体函数甚至具体行。
6.2 软件看门狗与异常恢复:让系统自己从死机里走出来
温度传感器和电机都是电气噪声源,单片机程序跑飞是这类系统里必然会遇到的实际问题,你不能指望用户断电重启,所以初始化时打开看门狗是更贴近工程的做法。STC89C52 内置看门狗,通过特殊功能寄存器 WDT_CONTR 控制,设计上需要在主循环里定时“喂狗”,一旦程序跑飞无法循环,看门狗超时后自动复位系统。喂狗的位置很有讲究,如果你卡在一个阻塞很久的循环里,比如长时间按键等待,就会误触发复位,所以喂狗语句应该放在主循环的入口处,而不是散落在各个子函数里。
最后的整体验证建议分三步走。第一步用 Proteus 仿真搭好最小系统,确认温度读取、显示刷新、按键响应逻辑都正确;第二步在实物上测试自动模式的温度响应,用吹风机对着 DS18B20 加温,观察档位是否按预定阈值切换;第三步测试手动模式上下限和按键长按连续调速的体验。整个系统闭环验证完毕后,把关键参数整理成一张表格存入设计报告,比如各个档位的温度阈值、占空比数值、PWM 周期,这些实测数据能直接证明你的设计不是停留在仿真层面的纸面方案。如果你用的是 STM32 平台,这套验证流程可以原样复用,只是把底层的寄存器操作换成 HAL 库调用即可。
本文还有配套的精品资源,点击获取