☰
基于Proteus与Keil的STM32温湿度采集控制系统仿真设计
2026/10/21 17:38:55 网站建设 项目流程

做课设或者拿大作业练手的时候,“STM32温湿度采集控制系统”几乎是必选题。很多人一上来就想着焊真机,买传感器、调杜邦线、烧了几块板子才发现精力全花在硬件问题上,根本没机会把“采集—显示—控制—报警”这一整条链路彻底打通。这次我换了个思路,用Proteus仿真把硬件环境完全复现出来,配合Keil写代码和联调,最终产出一套完整可交付的项目成果,包括代码、设计报告和演示视频。

这篇内容我从方案选型开始讲,把Proteus电路搭建、Keil代码实现、联调排错的完整过程拆开,最后会专门说设计报告和演示视频怎么做才拿得出手。无论你是嵌入式方向的学生,还是想快速掌握仿真开发流程的爱好者,这篇文章应该都能让你少踩不少坑。

1. 方案选型:仿真方式做温湿度控制系统到底值不值

1.1 从功能需求倒推设计方向

拿到这个题目,第一步不是打开软件画原理图,而是把“要做的系统”拆成清晰的功能模块。一个完善的温湿度采集控制系统,至少要包含四件事:环境温湿度数据采集、当前数值的实时显示、超阈值时的控制动作、状态异常时的报警提示。

在实际的工程训练中,很多人会把重点放在代码量上,觉得功能越多越复杂越好。但我更建议反过来思考:这套系统的核心价值在于数据链路是否完整,传感器采集到的信号,经过单片机处理,最终能不能驱动执行机构产生正确的物理动作。只要这条链路是通的,项目的主干就立住了。

在这个前提下,我决定把系统拆成五个基本单元:以STM32为主控核心,DHT11作为温湿度采集前端,LCD1602负责显示,直流电机模拟风扇做散热控制,蜂鸣器做超限报警。整体是一个闭环:采集—处理—显示—控制—反馈。

1.2 为什么选STM32F103C8T6搭配DHT11

STM32F103C8T6是教学和课程设计里用到最多的芯片之一,64引脚、72MHz主频、丰富的定时器和GPIO资源,做温湿度采集绰绰有余。更重要的是它的资料极其庞杂,任何关于串口、定时器、ADC、外部中断的配置,几乎都能找到现成的参考,这对一个需要兼顾代码和文档产出的项目来说,是很大的便利。

温湿度传感器选DHT11,原因也很直接:它用单总线协议,一根数据线就能完成传输,电路连线上比I2C的SHT30、模拟量的LM35都省事;而且Proteus元件库自带DHT11仿真模型,不需要额外导入第三方库,省掉了最麻烦的环境配置环节。

这里有个很多人忽略的点:DHT11的精度并不高,温度±2℃、湿度±5%,但做控制演示完全够用。如果追求高精度,成本和调试复杂度会大幅上升,对课程设计这个层面的项目来说并不划算。

1.3 Proteus仿真和真机开发之间的性价比权衡

在做方案对比的时候,我认真评估过“直接上真机”和“先用仿真跑通”这两种路线。真机开发有它不可替代的价值,比如引脚电平的实测、传感器在真实环境下的响应、电源纹波对系统的影响。但它的成本也很高:器件采购周期、焊接调试时间、硬件故障的不确定性,这些对时间有限的课设场景来说都是不小的负担。

Proteus仿真的核心优势是可重复性和可演示性。代码崩了,点一下重置就能重来;硬件接错了,改连线重跑一遍就行;演示的时候还能随时更改参数,向评委展示系统在不同条件下的反应。对于“理解系统工作原理、打通软件逻辑”这个主要目标,仿真环境反而比真机更高效。

但我也要说清楚边界:Proteus是逻辑仿真的工具,它模拟的是数字电路的行为和时序,模拟不了真实传感器的物理特性。在仿真里你改变的是模型参数,而不是实际环境变化。所以仿真跑通之后,心里要有数——真机环境下还会面临电源噪声、信号干扰、传感器响应延迟这些问题,这些都需要在真机阶段去验证,不能指望仿真帮你扛过去。

2. 仿真电路搭建:Proteus里从零搭出完整硬件系统

2.1 元件选择与库文件准备

Proteus 8.9以上版本的元件库已经相当完整,STM32F103C8T6、DHT11、LCD1602、直流电机这些常用器件都能直接搜到。新建一个工程之后,先把下面这些元件添加到原理图:

元件搜索关键词数量用途
STM32F103C8T6STM32F103C81片主控制器
DHT11DHT111个温湿度采集
LCD1602LM016L或LCD16021块数据展示
直流电机MOTOR-DC1个模拟散热风扇
蜂鸣器BUZZER1个超限报警
电位器POT2个模拟环境温湿度变化

这里有一个我自己踩过的小坑:不同版本Proteus里LCD1602的元件名不一样,老版本叫“LM016L”,新版本直搜“LCD1602”也能找到。建议优先用LM016L,这是Proteus里经典的标准LCD模型,引脚定义和16×2显示驱动兼容性最好。

2.2 硬件连线的核心细节

原理图连线是先动手做的第一件事,连对了,后面一切顺畅;连错了,调试阶段一定会被折磨。我最终的接线方案是:DHT11的数据线接PA0,同时加一只4.7kΩ上拉电阻到3.3V;LCD1602的数据口接PB0到PB7,RS接PB11,E接PB10,RW直接接地;直流电机正极接PA1输出的PWM信号,通过一个NPN三极管做驱动;蜂鸣器接PA3,用低电平驱动。

上拉电阻这件事值得单独拿出来说。DHT11的数据线在空闲状态下必须保持高电平,通信时靠拉低总线来发起时序,如果少了上拉电阻,读取出来的数据经常是0xFF或者随机跳变。有过硬件经验的朋友都知道,这是单总线器件最常见的故障点,在Proteus里同样存在——我之前试过把DHT11的DATA引脚直接挂到PA0上不加上拉,结果读出来的温度和湿度全是乱码。

电源和地线也要注意。Proteus仿真不会像真机那样因为电源走线不当产生噪声,但还是要养成良好的习惯:每个芯片的VCC和GND都要明确接好,去耦电容不加仿真是可以正常跑的,但我建议还是加上,这样原理图更完整,报告里也能解释清楚。

时钟电路方面,Proteus里的STM32F103C8T6默认使用内部RC时钟即可运行,不需要像真机那样必须外接8MHz晶振。但如果你在Keil工程里配置的是外部时钟源,仿真时就会跑不起来,两边必须一致。

2.3 DHT11仿真模型的行为差异是最大的隐藏坑

我在仿真环境里花时间最久的地方,不是连线,而是搞清楚Proteus里DHT11模型的工作方式。这里有一个和真实传感器非常不同的关键行为:真实DHT11会随环境温度变化而自动改变输出值,但Proteus里的DHT11模型默认输出一组恒定值,它并不“感知”环境变化。

怎么模拟温度变化?我在实际项目中试过两种办法。第一种是在仿真运行暂停的状态下,双击DHT11元件,在属性面板里直接修改Temperature和Humidity字段,改完再继续运行,系统就会读到新的数值。这种方式最稳定,但演示效果比较生硬。

第二种办法是利用模型预留的参数输入引脚,在模型附近放置电位器,把它和一个虚拟电压节点关联起来,用它来动态调节温湿度值。具体引脚位置在不同版本里略有差异,右键DHT11查看引脚定义就能确认。这个方法在录制演示视频时特别好用——你可以当着镜头拧电位器,让屏幕上的温度从25℃慢慢升到35℃,风扇随之启动,整个过程一气呵成,非常有说服力。

3. Keil工程的搭建与控制逻辑的实现

3.1 工程文件结构与基础初始化

Keil这边我用的是MDK5,新建一个基于标准外设库的工程。可能有人会问,现在STM32CubeMX+HAL库不是主流吗?为什么还选标准库?原因是这个项目规模不大,裸机程序逻辑简单,标准库的直接寄存器操作方式更容易让人理解每一步在干什么,报告里写代码说明时也更直观。工程目录我建议这样组织:

project_root/ ├── Core/ # 主函数、中断服务 │ └── main.c ├── Driver/ # 各外设驱动模块 │ ├── dht11.c │ ├── dht11.h │ ├── lcd1602.c │ ├── lcd1602.h │ ├── delay.c │ └── delay.h └── Output/ # 编译生成的hex文件

基础初始化的逻辑并不复杂,按照GPIO、延时、LCD、外设的顺序依次完成。GPIO配置上,PA0设置为开漏输出,这符合单总线协议的电气要求;PB0到PB7设为推挽输出;PA1用定时器映射为PWM输出通道,这样风扇可以实现调速,而不只是简单的开关;PA3用推挽输出控制蜂鸣器。

3.2 DHT11时序解析:从时序图到可用代码

在编写DHT11驱动时,成功与否完全取决于你能不能在代码里精确模拟单总线时序。基本的数据链路由三个环节构成:主机发起始信号、DHT11发应答信号、DHT11输出40位数据(8位湿度整数、8位湿度小数、8位温度整数、8位温度小数、8位校验和)。

核心的读取函数我写成这样:

uint8_t DHT11_ReadData(uint8_t *humidity, uint8_t *temperature) { uint8_t data[5] = {0}; uint8_t i, j; // 主机发送起始信号:拉低总线至少18ms GPIO_ResetBits(GPIOA, GPIO_Pin_0); delay_ms(20); GPIO_SetBits(GPIOA, GPIO_Pin_0); delay_us(30); // 检测DHT11的80us低电平应答信号 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == RESET) { while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == RESET); // 等待低电平结束 delay_us(40); for(j = 0; j < 5; j++) { for(i = 0; i < 8; i++) { while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET); // 等待50us低电平过去 delay_us(30); if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET) { data[j] |= (0x80 >> i); delay_us(20); } } } } // 校验前四个字节之和是否等于校验字节 if(data[4] == (uint8_t)(data[0] + data[1] + data[2] + data[3])) { *humidity = data[0]; *temperature = data[2]; return 1; } return 0; }

这个函数里最关键的逻辑是延时30微秒后再判断电平。数据位“0”的高电平持续26到28微秒,数据位“1”的高电平持续70微秒。在30微秒这个时间点采样,刚好能区分开两者。延时太短会把“0”误判为“1”,太长则会错过“1”的采样窗口。这段代码里的延时时间需要配合芯片主频微调,72MHz主频下延时函数的参数都能对上。

3.3 控制策略:阈值判断不是简单的开关

在执行机构控制上,我见过很多人的代码是“温度大于某个值就开风扇,小于就关”,这种做法演示起来效果很差——温度在阈值边缘抖动时,风扇会频繁启停,既伤负载也影响观感。正确处理方式是引入滞回控制,也就是常说的施密特触发器思想。

具体做法是设置两个不同的阈值点:启动阈值和停止阈值。温度升到28℃时启动风扇,降到26℃时才关闭风扇。中间这2℃的差值就是滞回区间。在这个区间内,系统保持当前状态不变,不会因为数字的微小波动而反复切换。

#define TEMP_ON_THRESHOLD 28 #define TEMP_OFF_THRESHOLD 26 #define HUMIDITY_LOW_LIMIT 40 void Control_Temperature(float temp) { if(temp >= TEMP_ON_THRESHOLD) { SystemState.fan_status = FAN_ON; // 打开风扇 } else if(temp <= TEMP_OFF_THRESHOLD) { SystemState.fan_status = FAN_OFF; // 关闭风扇 } }

湿度控制的逻辑类似,但方向相反。湿度低于40%时启动加湿器模拟负载,升到45%以上停止。这样设置的好处是系统状态稳定,演示过程中执行机构不会出现抽搐式的频繁启停,也让报告里“控制策略设计”这一章有东西可写。

3.4 LCD1602显示驱动的移植要点

LCD1602的驱动是这里面最“套路化”的部分,网上代码一抓一大把,但真正自己写的时候有几个细节容易翻车。第一是初始化时序,配置为8位数据模式后要依次发送0x38、0x0C、0x06、0x01,每条命令之间保留足够的延时,后面才能正确显示;第二是写数据和写命令的引脚状态切换必须准确,RS引脚在写命令时拉低,写数据时拉高,顺序反了屏幕要么花屏要么显示空白。

void LCD_Show_Data(float temp, float hum) { char buf[16]; LCD_WriteCmd(0x80); // 第一行起始地址 sprintf(buf, "Temp:%.1f C", temp); LCD_WriteString(buf); LCD_WriteCmd(0xC0); // 第二行起始地址 sprintf(buf, "Humi:%.1f %%", hum); LCD_WriteString(buf); }

显示内容我做了格式化处理,温度取一位小数,湿度带百分比符号,这样整体观感比较专业。DHT11读取失败时,我会在LCD上显示“Sensor Error”而不是跳乱码,这个小细节在演示视频里有意外的好处——它证明你的代码处理了异常情况,而不是只会输出正常数据。

4. 联调、跑通与问题排除的完整复盘

4.1 Keil与Proteus的联调方式选择

很多第一次做仿真的同学会纠结“Keil怎么和Proteus联调”。其实最稳定的方式根本不是实时联合调试,而是分两步走:先在Keil里编译生成HEX文件,再把HEX文件加载到Proteus的STM32芯片里。

具体操作流程是:在Keil的Options for Target里勾选Create HEX File,编译通过后在Output目录找到.hex文件;然后在Proteus工程里双击STM32F103C8T6芯片,在Program File一栏填入HEX文件路径,点OK即可。点运行之后,如果程序有串口输出,可以放一个虚拟终端来观察完整的数据流。

实时联合调试的配置(也就是让Proteus作为Keil的调试器)在原理上是可行的,但配置过程涉及VSM调试接口、AGDI驱动等一堆麻烦事,而且版本兼容性问题很多,我建议时间有限的话不要碰这个功能。把HEX烧进去跑,配合Proteus的断点和单步功能,已经能满足绝大部分调试需求。

4.2 仿真中我实打实踩过的三个坑

第一个坑是DHT11温度永远显示0。排查了很久,原因是GPIO模式配置错了。DHT11的数据线在读取数据时需要输入模式,在主机发送起始信号时需要输出模式。如果全程配置为推挽输出,读引脚电平永远读到异常状态。解决方法是把PA0配置为开漏模式,开漏状态天然支持“输出低电平+释放高电平”的双向切换。

第二个坑是LCD1602有背光但无任何字符。这个问题的根源不是接线,而是初始化时没有等待足够的时间。LCD1602上电后需要等待大约15到20毫秒,让内部控制器完成复位,如果立即发送配置命令,命令会丢失。在每条命令之间加一个10毫秒级别的延时后,问题立刻消失。

第三个坑是风扇电机一转起来整个系统画面就卡顿。原因是把电机调速直接放在了主循环里用delay_ms来改变PWM占空比,导致整个主循环的周期变得极其不稳定。解决办法是把风扇调速交给定时器PWM硬件完成,主循环只负责根据阈值改变比较寄存器的值,彻底把时序控制和业务逻辑分开。

4.3 功能验证清单与实测效果

系统跑通之后,我按下面这张表逐项做了功能验证,确认每一个环节都符合预期:

验证项目测试方法预期结果实测情况
DHT11数据读取修改模型温湿度参数数值正确变化通过,误差在1以内
LCD显示观察屏幕刷新温湿度实时更新通过,无花屏
高温报警温度参数调至30℃蜂鸣器鸣叫通过,1秒内响应
风扇控制温度超过28℃电机启动通过,PWM调速正常
湿度控制湿度参数调至35%加湿负载启动通过
回复过程参数调回正常范围执行机构停止通过,滞回区间正常

整个系统跑起来之后的状态是:LCD第一行稳定显示当前温度,第二行显示湿度;温度正常时蜂鸣器不响、风扇不转;把温度模拟参数调到29℃以上,约1秒后风扇启动,蜂鸣器以低频短鸣的方式报警;把温度降回27℃以下,风扇在滞回条件下关闭,蜂鸣器停止。这一套完整的反应流程,就是演示视频的核心内容。

5. 一份能直接拿去交差的报告是怎么写出来的

5.1 设计报告的结构设计与图文编排

标题里特意提到“有报告”,说明这已经是很多课程设计验收的标配要求。我写设计报告的时候,发现很多人容易把报告写成“说明书”——贴一堆代码,画一堆截图,但老师真正想看的逻辑链条反而没有。我最终采用的报告结构是:需求分析、系统总体设计、硬件电路设计、软件设计、仿真测试、总结与展望六个章节。

需求分析这章不要写空话,直接写“系统需要实现温湿度采集、LCD显示、超阈值风扇控制、超限蜂鸣器报警”几个具体功能即可。系统总体设计配一张模块框图,把主控、传感器、显示、执行机构之间的关系画清楚。硬件电路设计提出DHT11为什么需要上拉电阻、PWM电机调速的原理,软件设计按模块拆解,重点讲DHT11时序和滞回控制的思路。

报告里最需要注意的是图和代码必须经过裁剪。截图要裁剪到只保留与当前论述相关的区域,代码片段只截核心函数,注释写清楚,代码全量附录放在最后。排版上建议用表格将硬件选型的规格参数整理出来,这会让报告的专业度上一整个台阶。

5.2 演示视频的节奏控制与录制技巧

演示视频我控制在5分钟左右,时长太短讲不清细节,太长则考验观众的耐心。我总结下来比较理想的节奏是:前30秒用一句话介绍系统功能,然后依次展示Keil工程结构、Proteus电路图、整体运行效果、阈值触发过程,最后用一个表格总结验证结果。

录制的时候有个重要的技巧:如果演示过程中需要修改DHT11参数来模拟环境变化,记得先暂停再修改,避免画面里出现鼠标在属性面板里乱翻的杂乱镜头。我用第一种方式修改参数时,提前把属性面板位置固定好,录制时点击修改后立刻恢复运行,视频看起来就是系统自动感知了环境变化。

另外,在展示蜂鸣器报警时,Proteus仿真的蜂鸣器音量比较小,录制视频时如果直接用麦克风收音会很弱。我选择的做法是在视频里用屏幕字幕同步标注“蜂鸣器报警”的状态文字,让观看者明确知道当前正处于报警状态,而不是干巴巴地等那个几乎听不见的响声。

写在最后:这套仿真实战真正教会我的事

做完整个项目之后我有一个很深的体会:这类仿真控制系统的难点从来不是某个单独模块的实现,而是所有模块在时间尺度上的配合。DHT11的时序以微秒为单位,LCD的命令时序以毫秒为单位,风扇的响应以秒为单位,三层时间尺度同时存在于一套系统里,这对编程时的心智模型是个不小的考验。

如果后续还想继续扩展,我个人觉得有三个方向值得尝试:一是把开关量控制升级为PID闭环控制,让风扇根据温度偏差连续调节转速;二是加入ESP8266模组模拟远程数据传输,把数据上报到上位机软件,这样就从单机采集系统进化成了物联网终端;三是把Proteus仿真出来的代码逻辑移植到真机上,实际感受仿真与真实的差异,那将是这个项目最完整的一次闭环。

另外分享一个制作上的小技巧:在这个项目里花十几块钱买一块真实的STM32最小系统板和DHT11模块,用相同代码在真机上跑一遍,和Proteus截图放一起对照,这份报告的说服力会明显高于纯仿真内容。

无论你是为了完成课程设计,还是在学习嵌入式开发,Proteus加Keil这套组合都是理解单片机系统最直接的路径之一。它能让你把注意力全部集中在代码逻辑和系统设计上,而不是跟硬件故障纠缠。希望这篇复盘能帮你把属于自己的温湿度控制系统顺利跑通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询