首页/新闻资讯/正文详情

Proteus DHT11仿真教程:51单片机温湿度读取与LCD显示

发布时间:2026/9/25 1:31:00 来源:云帆数科 栏目:资讯中心
Proteus DHT11仿真教程:51单片机温湿度读取与LCD显示
1. 为什么要在Proteus里跑DHT11仿真很多刚接触单片机的朋友第一个卡住的地方不是写代码而是硬件还没到手板子没焊传感器也没买代码写完根本不知道对不对。这时候Proteus这类仿真工具的价值就体现出来了——你可以在纯软件环境里把电路搭出来把编译好的固件加载进去观察DHT11的温湿度数据能不能正常读出来、LCD能不能正确显示。整套流程跑通之后再动手焊实物心里就有底了。DHT11这颗传感器在仿真里有个特殊性Proteus自带的元件库里并没有原生的DHT11模型。这一点和LED、按键、数码管完全不同那些元件拖出来就能用。DHT11必须靠第三方库文件补进去或者用替代方案模拟。这也是为什么很多人搜Proteus DHT11的时候看到的教程要么语焉不详要么直接给一个下载链接就完事了中间的关键步骤全被跳过。这篇内容面向的是已经会一点51单片机、装好了Keil和Proteus、但还没成功在仿真里读出DHT11数据的同学。我会把库文件怎么装、元件怎么放、代码怎么写、调试怎么排错按我实际操作的顺序完整讲一遍。涉及到的工具链是Keil C51加Proteus 8.x芯片用STC89C52或AT89C51都行代码逻辑通用。需要提前说明的是DHT11的仿真模型和实物在时序上存在差异仿真能跑通不代表实物一定没问题但仿真跑不通实物基本也不用试了。这个认知很重要后面讲调试的时候会反复用到。2. 仿真前的环境准备与库文件安装2.1 Proteus版本选择和安装注意事项Proteus目前主流用的是8.x系列8.9到8.15这几个版本对第三方库的兼容性比较稳。我实测下来8.13和8.15这两个版本在加载DHT11库的时候最省心8.6以前的版本偶尔会出现元件加载后引脚不显示的问题。安装路径建议保持默认不要放在中文目录下这一点是老生常谈但确实有人栽跟头——路径里有中文库文件注册的时候会静默失败你看到元件列表里就是没有DHT11查半天查不出原因。安装完成后先确认一件事打开Proteus在元件选择界面搜索AT89C51如果能搜到说明基础库没问题。搜不到的话大概率是安装时组件没选全需要重新运行安装程序把Library相关的组件勾上。2.2 DHT11库文件的获取与放置DHT11的Proteus模型文件通常包含两个部分一个是.LIB文件一个是.IDX文件有的打包里还会带.HEX或者示例电路。这些文件的来源一般是社区开发者制作的网上能搜到不少版本。我手头用的是比较常见的一个版本文件名叫DHT11.LIB和DHT11.IDX。放置位置有两个选择。第一种是放在Proteus安装目录下的LIBRARY文件夹里比如C:\Program Files\Labcenter Electronics\Proteus 8 Professional\LIBRARY。放进去之后需要重启Proteus然后在元件搜索里输入DHT11就能看到。第二种是放在用户自定义库目录通过Library菜单里的Library Manager手动添加路径。第一种方式更直接推荐新手用第一种。注意放库文件之前先把Proteus关掉放完之后再打开。如果Proteus开着的时候放进去它不会自动扫描新文件你会以为库没装成功。2.3 验证库是否安装成功重启Proteus后点左侧工具栏的P按钮Pick Devices在搜索框里输入DHT11。如果安装成功列表里会出现一个名为DHT11的元件类别通常显示为Sensors或者Temperature Sensors。选中它右侧会显示它的引脚图一般是三个引脚VCC、DATA、GND。有的版本会多一个NC引脚不用管它。如果搜不到先检查文件是不是真的放到了LIBRARY目录下再检查文件名大小写——Proteus在Windows下对大小写不敏感但有些打包文件解压后文件名会带多余的后缀比如DHT11.LIB.txt这种要手动改回来。还有一种情况是库文件版本和Proteus版本不匹配换一个版本的库文件试试。3. 电路搭建与元件参数设置3.1 核心元件清单与选型理由搭建这个仿真电路需要的元件不多但每个都有讲究。下面这张表是我实际用的配置元件型号/参数数量作用单片机AT89C51或STC89C521主控跑DHT11驱动代码温湿度传感器DHT111采集温湿度数据液晶显示LCD16021显示温湿度数值晶振11.0592MHz1提供系统时钟电容30pF2晶振起振匹配电阻10kΩ1DHT11数据线上拉电阻10kΩ1LCD1602对比度调节可用电位器替代电解电容10μF1复位电路电阻10kΩ1复位电路按键BUTTON1手动复位晶振选11.0592MHz而不是12MHz原因是这个频率下串口波特率更准虽然这个项目不用串口但养成习惯没坏处。DHT11的数据线必须接上拉电阻因为它的DATA引脚是开漏输出没有上拉电阻的话总线一直是低电平读不到数据。这个上拉电阻在实物上通常用4.7kΩ到10kΩ仿真里10kΩ就够。LCD1602用标准的16引脚版本Proteus里搜LM016L就是它。对比度调节那个引脚VEE第3脚接一个10kΩ电阻到地仿真里就能正常显示实物上一般用电位器调。3.2 电路连接步骤与引脚对应连接顺序建议从单片机往外扩这样不容易乱。先把单片机的电源和地接好40脚接VCC20脚接地。晶振接在18和19脚之间两个30pF电容分别从18、19脚接地。复位电路是9脚接10μF电容正极电容负极接VCC9脚同时接10kΩ电阻到地再并一个按键到VCC。DHT11的三个引脚1脚VCC接5V4脚GND接地2脚DATA接单片机的P2.0口同时P2.0口接一个10kΩ上拉电阻到VCC。这里注意DHT11的引脚编号在不同库里可能不一样有的库1脚是VCC有的库1脚是DATA放上去之后双击元件看一下引脚标注以实际显示为准。LCD1602的连接1脚GND2脚VCC3脚接10kΩ到地4脚RS接P2.55脚RW接P2.66脚E接P2.77到14脚数据线接P0.0到P0.7。P0口需要接上拉电阻排因为51单片机的P0口是开漏输出不接上拉的话LCD显示会不正常。在Proteus里可以放一个RESPACK-8排阻一端接P0口另一端接VCC。提示Proteus里连线的时候如果两个引脚之间直接拉线不方便可以用网络标签Net Label。在需要连接的引脚上放一个标签名字相同就表示连在一起。这样电路图会干净很多尤其是LCD那16根线。3.3 仿真参数配置与常见设置项电路搭完之后双击单片机在Program File里加载Keil编译出来的.hex文件。时钟频率填11.0592MHz和晶振保持一致。如果用的是STC89C52Proteus的AT89C51模型可以直接替代代码兼容。在Edit Component对话框里还有一个Use Remote Debug Monitor选项这个是配合Keil联调用的纯仿真阶段不用勾。如果后面要做单步调试再回来勾上。仿真速度方面Proteus默认的实时仿真在跑DHT11这种带微秒级延时的代码时会显得很慢因为DHT11的时序里有很多微秒级的等待。可以在System菜单里的Set Animation Options把Frames per Second调低一点或者直接用Step模式单步跑。我一般先把仿真速度调到最快看整体效果出问题了再放慢单步查。4. DHT11驱动代码的编写与关键时序4.1 DHT11单总线协议的核心逻辑DHT11用的是单根数据线完成双向通信这种协议叫单总线。它的通信过程分三步主机发开始信号、DHT11响应、DHT11发送40位数据。40位数据里前16位是湿度8位整数加8位小数但DHT11小数部分恒为0中间16位是温度最后8位是校验和。时序上主机先把数据线拉低至少18毫秒然后拉高20到40微秒接着释放总线。DHT11检测到这个开始信号后会先把总线拉低80微秒作为响应再拉高80微秒然后开始逐位发送数据。每一位数据都以50微秒的低电平开始后面的高电平持续时间决定这一位是0还是1高电平持续26到28微秒表示0持续70微秒表示1。这个时序是DHT11驱动的核心代码里所有的延时函数都是围绕这些时间参数写的。51单片机在11.0592MHz下一个机器周期约1.085微秒写延时函数的时候要按这个来算。4.2 延时函数的精确计算先定义一个微秒级延时函数。11.0592MHz晶振下一个机器周期是12/11.0592约等于1.085微秒。如果要用for循环做延时每次循环大概消耗几个机器周期需要实测校准。下面这个是比较常用的写法void DelayUs(unsigned int us) { while(us--) { _nop_(); _nop_(); } }这个函数在11.0592MHz下每次循环大约1微秒出头实际用的时候要根据仿真效果微调。更稳妥的做法是用定时器做精确延时但DHT11的时序要求不算特别苛刻普通延时函数够用。毫秒级延时直接用嵌套循环void DelayMs(unsigned int ms) { unsigned int i, j; for(i 0; i ms; i) for(j 0; j 110; j); }这个110这个数字是校准出来的不同编译器优化等级下会有差异需要根据实际情况调整。4.3 读字节与读位的代码实现读一位数据的逻辑是先等低电平过去然后延时30微秒左右采样如果此时还是高电平说明这一位是1否则是0。代码长这样unsigned char DHT11_ReadBit(void) { unsigned char bit_data 0; while(DHT11_PIN); // 等待低电平结束 DelayUs(30); // 延时30us后采样 if(DHT11_PIN) bit_data 1; while(DHT11_PIN); // 等待高电平结束 return bit_data; }读一个字节就是把8个位拼起来unsigned char DHT11_ReadByte(void) { unsigned char i, byte_data 0; for(i 0; i 8; i) { byte_data 1; byte_data | DHT11_ReadBit(); } return byte_data; }这里有个细节while(DHT11_PIN)这个等待循环在仿真里可能会卡死因为仿真环境下引脚状态变化和实际电路有差异。如果发现程序跑飞可以在等待循环里加一个超时计数超过一定次数就强制退出避免死循环。4.4 完整的DHT11读取函数把上面的部分串起来完整的读取函数如下unsigned char DHT11_ReadData(unsigned char *temp, unsigned char *humi) { unsigned char buf[5]; unsigned char i; // 主机发送开始信号 DHT11_PIN 0; DelayMs(20); DHT11_PIN 1; DelayUs(30); // 等待DHT11响应 if(!DHT11_PIN) { while(!DHT11_PIN); // 等待响应低电平结束 while(DHT11_PIN); // 等待响应高电平结束 // 读取40位数据 for(i 0; i 5; i) buf[i] DHT11_ReadByte(); // 校验 if(buf[0] buf[1] buf[2] buf[3] buf[4]) { *humi buf[0]; *temp buf[2]; return 1; // 读取成功 } } return 0; // 读取失败 }这个函数返回1表示成功0表示失败。调用的时候把温度和湿度的指针传进去函数内部会把数据填好。5. 主程序框架与LCD显示整合5.1 主循环的结构设计主程序的结构很直接初始化LCD然后在一个死循环里不断读DHT11读到了就刷新显示读不到就显示错误提示。DHT11的采样周期不能太快数据手册要求两次读取间隔至少1秒所以循环里要加一个延时。void main(void) { unsigned char temp, humi; unsigned char ret; LCD_Init(); LCD_ShowString(0, 0, DHT11 Test); while(1) { ret DHT11_ReadData(temp, humi); if(ret) { LCD_ShowString(0, 1, T:); LCD_ShowNum(2, 1, temp, 2); LCD_ShowString(5, 1, C H:); LCD_ShowNum(9, 1, humi, 2); LCD_ShowString(11, 1, %); } else { LCD_ShowString(0, 1, Read Error ); } DelayMs(1500); } }这个框架跑起来之后仿真里应该能看到LCD上显示温度和湿度数值。如果显示的是Read Error说明DHT11读取失败需要排查时序或者电路。5.2 LCD1602驱动函数的精简实现LCD1602的驱动代码网上很多这里给一个最精简的版本只保留必要的功能#define LCD_DATA P0 sbit LCD_RS P2^5; sbit LCD_RW P2^6; sbit LCD_EN P2^7; void LCD_WriteCmd(unsigned char cmd) { LCD_RS 0; LCD_RW 0; LCD_DATA cmd; LCD_EN 1; DelayUs(5); LCD_EN 0; DelayMs(2); } void LCD_WriteData(unsigned char dat) { LCD_RS 1; LCD_RW 0; LCD_DATA dat; LCD_EN 1; DelayUs(5); LCD_EN 0; DelayMs(2); } void LCD_Init(void) { LCD_WriteCmd(0x38); // 8位数据两行显示 LCD_WriteCmd(0x0C); // 开显示关光标 LCD_WriteCmd(0x06); // 光标右移 LCD_WriteCmd(0x01); // 清屏 DelayMs(5); }显示字符串和数字的函数就是在LCD_WriteData基础上循环调用数字显示需要把数值拆成单个数字字符。5.3 Keil编译配置与HEX文件生成代码写完之后在Keil里新建工程选AT89C51或STC89C52把.c文件加进去。关键的一步是勾选Options for Target里的Create HEX File不勾的话编译完不会生成.hex文件Proteus就加载不了。晶振频率在Target标签页里填11.0592MHz和Proteus里保持一致。编译的时候如果报错说找不到absacc.h或者intrins.h检查一下头文件路径这两个是Keil自带的一般不会有问题。编译成功后在工程目录下的Objects文件夹里能找到.hex文件。回到Proteus双击单片机在Program File里选中这个文件点确定然后点左下角的运行按钮仿真就开始跑了。6. 仿真调试中的典型问题与排查方法6.1 DHT11读取失败的常见原因仿真跑起来之后最常见的问题就是LCD上一直显示Read Error。这个问题我遇到过很多次原因基本集中在几个地方。下面这张表是我整理的排查顺序现象可能原因排查方法一直Read Error上拉电阻没接检查DATA线是否有10kΩ到VCC一直Read Error引脚定义错误确认代码里sbit定义的引脚和电路一致偶尔成功偶尔失败延时不准调整DelayUs的循环次数仿真卡死不动while等待死循环在等待循环里加超时计数LCD显示乱码P0口没接上拉加RESPACK-8排阻LCD完全不亮对比度没调检查VEE引脚电阻上拉电阻这个问题最隐蔽因为电路图上看线是连着的但如果没有上拉DHT11的DATA线在空闲时不是高电平主机发开始信号后DHT11根本检测不到。仿真里DHT11模型对上拉电阻的依赖比实物更明显实物上有些情况下不加也能凑合仿真里不加基本必挂。6.2 仿真速度与时序不匹配的处理Proteus的仿真速度和真实时间不是严格对应的尤其是跑带微秒延时的代码时仿真时间会被拉长。这会导致一个现象代码在实物上跑得好好的在仿真里就是读不到数据。原因是仿真环境下DHT11模型的响应时间和代码里的延时对不上。处理办法有两个。一是调整代码里的延时参数把DelayUs(30)改成DelayUs(20)或者DelayUs(40)多试几次找到能稳定读取的值。二是换用Proteus里自带的DHT22模型如果库里有的话DHT22的时序容错性比DHT11好一些但代码需要相应调整。我个人的经验是在11.0592MHz下把读位函数里的采样延时从30微秒改成25微秒左右仿真成功率会明显提高。这个值不是固定的跟Proteus版本和电脑性能都有关系需要自己微调。6.3 Keil与Proteus联调的操作要点如果单靠改延时调不出来可以用Keil和Proteus联调单步跟踪代码执行看看到底卡在哪一步。操作步骤是在Keil的Options for Target里把Debug标签页的调试器选成Proteus VSM Simulator然后在Proteus里勾选单片机的Use Remote Debug Monitor。两边都设置好之后在Keil里点Start Debug Session就能在Keil里单步跑代码同时Proteus里的电路会跟着响应。联调的时候重点看几个地方主机发开始信号后DHT11有没有把总线拉低读位的时候采样点是不是落在高电平期间。如果发现DHT11根本没响应说明开始信号的时序不对如果响应了但读出来的数据全是0或全是1说明采样点偏了。提示联调模式下仿真速度会非常慢只适合排查关键时序不要用它跑完整流程。查完问题就退出联调正常跑仿真看效果。7. 从仿真到实物的过渡经验仿真跑通之后把代码烧到实物上大概率还会遇到新问题。这不是仿真没用而是仿真和实物之间本来就有差距。DHT11实物对电源质量比较敏感供电不稳的时候读出来的数据会跳变。数据线的上拉电阻在实物上建议用4.7kΩ比仿真里的10kΩ更稳。另外实物的DHT11响应速度比仿真模型慢两次读取之间的间隔建议拉到2秒以上。我在实物上踩过的一个坑是仿真里用P2.0口读DHT11没问题实物上换成P1口之后就读不到了。查了半天发现是P1口内部有上拉和外部上拉电阻并联之后阻值变小导致高电平驱动能力不够。换回P2口就好了。所以引脚选择上尽量用P0或P2口P1和P3口内部有上拉和外部上拉配合的时候要注意。还有一点DHT11的供电电压范围是3.3V到5.5V实物上用3.3V供电也能工作但数据线的上拉电阻要接到3.3V而不是5V否则会通过上拉电阻给DHT11的DATA引脚灌电流长期运行可能损坏传感器。这个细节在仿真里体现不出来但实物上必须注意。最后分享一个调试小技巧如果实物上读不到数据先用示波器或者逻辑分析仪抓一下DATA线的波形看主机发开始信号后DHT11有没有拉低总线。有拉低说明传感器在工作问题在后续的时序没拉低说明传感器没收到开始信号检查接线和上拉电阻。这个排查思路比盲目改代码高效得多。

相关推荐

OFDM PAPR抑制新方案:分组SLM结合幅值标记,免边带低复杂度
OFDM PAPR抑制新方案:分组SLM结合幅值标记,免边带低复杂度

简介:针对正交频分复用系统中传统SLM方法计算复杂度高、需要额外带宽传输边带信息的问题,这份PDF资料提供了一种低复杂度改进方案。内容以学术论文形式完整呈现:先介绍正交频分复用峰均功率比问题及现有SLM改进思路,再给出发送端对… · 2026/9/25 1:31:00

MCU选型实战指南:从需求分析到国产替代的完整流程
MCU选型实战指南:从需求分析到国产替代的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:31:00

ESP32-S3麦克风阵列实战:从选型到回声消除
ESP32-S3麦克风阵列实战:从选型到回声消除

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:31:00

【Python深度学习】Keras六步实现简单循环神经网络
【Python深度学习】Keras六步实现简单循环神经网络

Keras 作为高级神经网络库,为机器学习算法工程师提供了快速上手神经网络的便捷工具。本文将通过使用 Keras 和简单的 6 步操作,介绍如何利用循环神经网络(RNN)进行时间序列数据的预测。本文所涵盖的内容也是算法工程师求职面试中的常见考察题目之一,旨在测试求职者对神经网… · 2026/9/25 2:09:09

【Python深度学习】Classes类在Keras中常用方法
【Python深度学习】Classes类在Keras中常用方法

在 Python 编程中,class 类是面向对象编程的基本构建块之一,通过类的定义可以创建对象、实现属性和方法的封装。在机器学习开发中,类的应用尤为广泛,包括数据结构的创建、模型的定义和优化、回调函数的实现等。 特别是在 Keras 中,利用类可以实现强大的回调功能,以监控和… · 2026/9/25 2:09:09

Centos7.x在线/离线安装/升级Docker/Docker Compose
Centos7.x在线/离线安装/升级Docker/Docker Compose

文章目录 前言 安装docker 1.升级docker 1.1.在线升级 1.2.离线升级 2.安装docker 2.1.在线安装docker 2.2.离线安装docker 3.配置镜像加速器 3.1.腾讯云 3.2.阿里云 安装docker-compose 1、在线安装 2、离线安装 安装runlike工具 前言 推荐:centos7系统(稳定,对docker支持友… · 2026/9/25 2:09:09

【Python深度学习】识别人类活动的一维卷积神经网络模型
【Python深度学习】识别人类活动的一维卷积神经网络模型

人体活动识别(Human Activity Recognition, HAR)是一项根据运动传感器数据预测个体行为的技术,通过智能手机、智能手表或其他传感设备实时捕获数据,实现对个体活动状态的分析。一个经典的 HAR 数据集是 2012 年推出的“使用智能手机的活动识别数据集”,它由意大利热那亚大… · 2026/9/25 2:09:09

【Python深度学习】使用 PyTorch 计算导数
【Python深度学习】使用 PyTorch 计算导数

导数是微积分的核心概念之一,描述了自变量的变化如何影响函数的输出。在深度学习中,导数计算(特别是梯度计算)用于更新神经网络的参数,使得模型逐步优化。PyTorch 提供了强大的自动微分模块 Autograd,通过简洁的 API 支持用户轻松计算导数,使得在构建和优化神经网络时更… · 2026/9/25 2:09:08

omnet++构架与源码分析(1)
omnet++构架与源码分析(1)

omnet模型以及运行环境部分使用c开发,IDE以及插件使用Eclipse以及插件方式开发。其中c代码位于解压后的include与src目录;src下面分为:sim:仿真内核类的CC代码;各种头文件,都在include目录;comm… · 2026/9/25 2:09:02

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码