ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

51单片机RS485多机通信与DHT11温湿度采集的Proteus仿真实现

51单片机RS485多机通信与DHT11温湿度采集的Proteus仿真实现 简介这是一份基于单片机Proteus仿真的温湿度检测RS485多机通信设计资料面向单片机课程设计、毕业设计以及需要学习RS485总线与多机通信的开发者。系统以51单片机为核心包含1个主机和2个从机从机通过DHT11采集温湿度经RS485总线将数据上传至主机最终由LCD1602液晶屏集中显示完整演示了典型工业分布式采集场景的软硬件设计思路。资源包共67个文件、约6.91MB主要包含Proteus仿真工程.pdsprj/.pdsbak、Keil C51源码.c/.h及编译产物.hex、工程配置文件.uvproj/.uvopt等另附操作演示录像便于对照仿真与实物逻辑。目前已有204人学习下载。通过学习该资料可获得可运行的仿真图与全套源代码理解多机RS485通信的地址分配、数据帧收发和LCD显示程序设计也能参考作者对从机、主机程序的模块划分快速搭建自己的温湿度采集系统。1. 这个题目为什么适合在 Proteus 里做又能用在哪里“单片机 Proteus 仿真 RS485 多机通信”这个组合看上去有点拧巴RS485 的价值在于长距离、抗干扰和多节点组网而这些恰恰是仿真环境最难呈现的部分。但真把一套设计做完会发现难点从来不在差分信号本身而是多机通信里的帧格式怎么定、从机怎么判断一帧是不是发给自己的、半双工方向切换早了会不会丢最后一个字节、地址冲突了总线会不会乱这些逻辑问题在 Proteus 里照样会暴露而且比接真实线缆更好定位。下文按硬件选型、DHT11 温湿度采集、RS485 主从协议、联调验证的顺序展开适合做课设或毕设初稿的初学者也适合有 51 单片机基础、想快速补齐 RS485 多机通信方案的工程师。2. 硬件选型与 Proteus 仿真图的关键节点2.1 主机与从机51 系列单片机是这套设计最稳的底座Proteus 新版已经能仿真一部分 STM32 型号但从完成度看用 51 系最稳。原因很简单STM32 的外设仿真覆盖不全串口、中断、多从机轮询组合在一起时模型一旦不配合你分不清是代码问题还是仿真模型问题。常见方案里主机和从机都用 AT89C52 代替 STC89C52 使用引脚和基本外设完全兼容Proteus 元件库里没有 STC 型号AT89C52 是最常用的等效替代。这套设计一主多从主机和从机都用同一颗芯片能省掉不少麻烦头文件一致、烧录时序一致、从机数量增加时只需要复制图纸再改地址。从机数量在 2 到 4 台时仿真速度还能接受超过 4 台交互仿真会明显变卡联调时建议先只挂一台跑通了再加。2.2 温湿度传感器选型DHT11 是仿真和实物能对上号的选择DHT11 在 Proteus 的 Sensor 库里自带模型引脚和真实器件一致这是课设标配的重要原因。DHT22 精度更高但老版本模型缺失新版本也要确认元件名单为了精度多花时间不上算。DHT11 精度为 ±2℃、±5%RH分辨率 1响应周期约 1 到 2 秒对 RS485 轮询来说反而合适主机轮询地址的节奏天然限制在秒级。列一张元件清单照着放不会漏元件Proteus 分类数量作用AT89C52Microprocessor ICs主机1 从机N主从节点DHT11Sensors每从机1温湿度采集MAX485Data Converters每节点1TTL 转 RS485 差分COMPIMVirtual Instruments按需映射到宿主机虚拟串口电位器Resistors1Proteus 中模拟 DHT11 温湿度10k 排阻Resistors每板1上拉120Ω 电阻Resistors总线最远两端终端匹配原理性电位器这一栏值得专门说Proteus 的 DHT11 模型不回读真实环境温湿度它的读数靠输入电压换算旋转电位器改变分压就能模拟出不同的温湿度值。第一次在仿真图里加 DHT11 的人经常卡在这个点不放电位器时读数永远是固定值。2.3 MAX485 自动收发电路省一个 IO 还是省一份调试时间MAX485 是 RS485 通信中最常见的收发器RE 接收使能低有效DE 发送使能高有效。经典接法把 RE 和 DE 并在一起用一个 IO 控制方向平时输出 0 待在接收态要发送时写 1发完立即恢复 0。这个方案多占一个 IO但逻辑直白仿真和真板行为一致给课设或毕设推荐这个就够。自动收发电路把方向控制交给硬件省掉这个 IO原理是 TXD 出现低电平起始位时通过三极管自动把 DE 拉高TXD 空闲为高时 DE 自动回落。听起来省事实际有坑起始位本身是低电平DE 从 0 到 1 需要时间波特率一旦超过 9600对端会丢掉起始位。常见反馈是到 19200 就开始随机错帧。自动收发适合节点大部分时间只听不发的应用从机要回帧、要频繁切换方向用自动收发是给自己添堵。2.3.1 经典方向控制电路的接法MAX485 的 RO 接单片机 RXDDI 接 TXDRE 和 DE 并联后接到一个普通 IO比如 P1^0。A、B 是差分对多个节点的 A 全部并在一起B 全部并在一起。Proteus 连多从机时用 Wire Label 标注 A、B 网络名比一根根拉线清晰得多排连线错误也更快。2.3.2 自动收发电路的适用前提想在某节点用自动收发至少要守住三条波特率不高于 9600帧间隔不小于 5 个字节时间发送期间关闭该节点的串口中断接收。不然起始位被削平、总线切换毛刺被当成数据排查起来比省一个 IO 的收益大得多。2.4 终端电阻与偏置电阻的仿真取舍Proteus 里 MAX485 的 A/B 是逻辑级联不存在传输线反射接不接 120Ω 终端电阻波形没差异但仿真图里照画因为它解释了原理。工程上终端电阻必须接在总线物理最远的两端各一个 120Ω吸收反射信号偏置电阻让总线所有节点都空闲时 A-B 压差大于 200mV避免从机收到噪声帧。常见接法主机侧 A 线上拉 390Ω 到 5VB 线下拉 390Ω 到 GND。真实 RS485 组网时这两组电阻不能省仿真图里删掉终端电阻跑通的现象不代表实物也能跑通。3. DHT11 读取时序先把温湿度数据弄准3.1 单总线时序起始信号与 40 位数据的对齐DHT11 用一根数据线完成双向通信。主机先拉低总线至少 18ms再释放上拉电阻把总线拉回高。传感器识别到起始信号后把总线拉低 80us 再拉高 80us 应答然后逐位输出 40 位数据。每一位都是 50us 低电平开始后面跟着高电平高电平 26 到 28us 表示 0高电平约 70us 表示 1。读取技巧就是在高电平开始后延时 40us 采样仍为高是 1已经回落是 0。40 位布局固定为湿度整数、湿度小数、温度整数、温度小数、校验和校验和是前四字节累加和的低 8 位。3.2 51 单片机读取 DHT11 的完整 C 代码#include reg52.h #include intrins.h sbit DHT11_DQ P2^0; // 微秒级延时12MHz晶振下每个_nop_约1us void delay_us(unsigned int us) { while (us--) _nop_(); } // 读取一个字节从高位开始 unsigned char dht11_read_byte(void) { unsigned char i, dat 0; for (i 0; i 8; i) { while (DHT11_DQ 0); // 跳过50us低电平时隙 delay_us(40); // 延时到采样点 if (DHT11_DQ 1) { // 高电平持续数据1 dat | (0x80 i); while (DHT11_DQ 1); } } return dat; } // 读取温湿度成功返回1 bit dht11_read(unsigned char *humi, unsigned char *temp) { unsigned char d[5], i; DHT11_DQ 0; delay_us(18000); // 起始信号拉低至少18ms DHT11_DQ 1; delay_us(30); if (DHT11_DQ 0) { // 从机应答低电平 while (DHT11_DQ 0); // 跳过80us应答低电平 while (DHT11_DQ 1); // 跳过80us应答高电平 for (i 0; i 5; i) { d[i] dht11_read_byte(); } if ((d[0] d[1] d[2] d[3]) d[4]) { *humi d[0]; // 湿度整数部分 *temp d[2]; // 温度整数部分 return 1; } } return 0; }这段代码有三个参数需要重点把握。延时精度是第一个_nop_()是一条机器周期空指令12MHz 晶振下约 1us但 Proteus 的仿真步长会放大这个值这是 3.3 里的坑。第二个是起始延时 18000us主机拉低时间短于 18ms传感器可能不应答太长也没必要超过 30ms 不会更稳。第三个是采样点delay_us(40)放在高电平开始之后数据 0 的 26 到 28us 高电平早已结束采样到 0数据 1 的 70us 高电平还在保持采样到 1。校验表达式(d[0]d[1]d[2]d[3]) d[4]用一字节加法溢出等价于取低 8 位比写 0xFF更直白51 编译器也不会有额外开销。主循环里两次dht11_read的间隔必须大于 1000ms这是 DHT11 本身的上限。读太快时传感器不响应函数返回 0程序要自己处理重试逻辑不能直接拿上一次的缓存值当新数据用。3.3 Proteus 里跑 DHT11 的三个典型坑第一个坑是仿真步长。Proteus 交互仿真按固定步长推进默认步长可能高于 10us而 DHT11 数据 0 的高电平只有 26 到 28us步长太粗直接跳过窄脉冲读回来的数据全是 0xFF 或频繁校验失败。在 System - Animation Options 里把步长调到 10us 以下能解决代价是仿真明显变慢。第二个坑是引脚选错。51 的 P0 口是开漏结构直接挂 DHT11 拉不回来数据线要接 P2 或 P3 这类准双向口并且外接 4.7k 到 10k 上拉电阻。仿真图里漏上拉起始信号后总线浮空DHT11 应答时序对不上函数永远走不进循环。第三个坑是模型版本差异。Proteus 的 DHT11 模型从旧版到新版行为不完全一致有的版本需要在元件属性里勾选启用传感器模拟。如果dht11_read返回的一直是 0先把模型属性翻一遍再查步长和上拉这三个检查项能覆盖九成的情况。4. RS485 多机通信协议与主从代码实现4.1 帧格式设计地址、命令、校验怎么编排自定义 5 字节帧结构如下字节字段说明1帧头固定 0xAA同步用2从机地址1~310 为广播255 为非法3命令码0x01 读温湿度0x02 返回数据4数据请求时为 0x00应答时放数据5校验前 4 字节累加和的低 8 位选累加校验是因为代码好读、答辩好解释。它查不出两个字节互换的错误如果项目后续要对接组态软件或上位机直接换 Modbus RTU 更省事地址(1) 功能码(1) 数据(n) CRC16(2)帧结构清晰还有免费调试工具。自定义帧和 Modbus 的边界在于单主机轮询、数据量小的场景下自定帧够用需要多主机、广播、事件上报时自定帧的地址管理和冲突处理会越来越麻烦那时候别犹豫换 Modbus。4.2 主机轮询逻辑与发送代码#include reg52.h sbit RS485_DE P1^0; // 0接收1发送 // 串口初始化9600bps11.0592MHz晶振 void uart_init(void) { SCON 0x50; // 模式1允许接收 TMOD 0x0F; TMOD | 0x20; // 定时器1模式2 TH1 TL1 0xFD; // 波特率9600 TR1 1; } void rs485_send_byte(unsigned char dat) { SBUF dat; while (!TI); TI 0; // TI必须软件清零 } void rs485_send_frame(unsigned char addr, unsigned char cmd) { unsigned char sum; RS485_DE 1; // 切到发送方向 rs485_send_byte(0xAA); rs485_send_byte(addr); rs485_send_byte(cmd); sum 0xAA addr cmd; rs485_send_byte(0x00); rs485_send_byte(sum); delay_xms(2); // 等停止位完整送出 RS485_DE 0; // 切回接收方向 } void main(void) { uart_init(); while (1) { rs485_send_frame(1, 0x01); delay_xms(20); rs485_send_frame(2, 0x01); delay_xms(20); } }先说 TH1 0xFD 这个参数定时器 1 模式 2 是 8 位自动重装计算公式是TH1 256 - 晶振/12/16/波特率11.0592MHz 晶振下 9600 波特率正好算得 253也就是 0xFD。很多仿真里串口乱码第一反应就是检查晶振是不是 11.0592MHz用 12MHz 晶振算不出整数的 9600 定时初值。delay_xms(2)是方向切换的关键。TI1 代表移位寄存器已经发完最后一个字节的停止位逻辑上此时 DE 已经安全但 Proteus 的串口模型和部分 STC 芯片里TI 置位与线上电平变化有半步偏差发完立即切方向可能把停止位截断。保守做法是发送函数内部延时 2ms 再恢复接收9600 波特率下一字节约 1.04ms2ms 覆盖了最后一个字节加上帧间隔。主循环里轮询两个从机各间隔 20ms足够从机完成回帧。4.3 从机中断接收状态机如何识别发给自己的帧#include reg52.h #define MY_ADDR 1 sbit RS485_DE P1^0; unsigned char rx_buf[5]; unsigned char rx_idx 0; unsigned char rx_state 0; // 0找帧头 1地址 2命令 3数据 4校验 bit rx_ok 0; void uart_isr(void) interrupt 4 { unsigned char dat, i, sum 0; if (!RI) return; RI 0; dat SBUF; switch (rx_state) { case 0: if (dat 0xAA) { rx_buf[0] dat; rx_idx 1; rx_state 1; } break; case 1: if (dat MY_ADDR) { // 地址匹配才继续收 rx_buf[1] dat; rx_idx 2; rx_state 2; } else { rx_state 0; // 不是自己的帧丢掉 } break; case 2: rx_buf[2] dat; rx_state 3; rx_idx 3; break; case 3: rx_buf[3] dat; rx_state 4; rx_idx 4; break; case 4: rx_buf[4] dat; for (i 0; i 4; i) sum rx_buf[i]; if (sum dat) rx_ok 1; // 校验通过主循环处理 rx_state 0; break; } } void main(void) { // 串口初始化同主机 while (1) { if (rx_ok) { rx_ok 0; if (rx_buf[2] 0x01) { // 读取DHT11并组织回帧发送 } } } }这个状态机有点讲头。地址放在第二字节从机在收到地址后立刻决定是否继续不匹配的帧在两字节内就被丢弃后面 3 个字节完全不参与中断处理多从机场景下能省下可观的 CPU 周期。从机收到完整 5 字节后做累加和校验校验失败直接丢弃不回帧由主机超时重发兜底。中断里只用位变量rx_ok通知主循环不在中断里做耗时的 DHT11 读取和回帧发送这是 51 单片机写串口接收的基本功。如果在中断里读取 DHT11一次读取要占用几百微秒到毫秒级9600 波特率下串口可能已经溢出丢帧。4.4 半双工方向切换切早了丢最后一个字节RS485 同一时刻只允许一个节点发送。方向切换最容易出错的位置是最后一帧发完到 DE 拉低之间的窗口。理论上 TI1 就代表停止位已经移出但实际中单片机模型和真实芯片一样存在标志位时序偏差切太早对端把停止位截断表现为从机能收到大部分帧但最后一字节偶尔丢失或错数据。给个对应表波特率单字节时间建议切换延时4800约2.08ms4ms9600约1.04ms2ms19200约0.52ms1ms4.5 多机地址规划与一主多从的连接方式地址 1 到 31 给从机0 留作广播255 当作非法地址扔掉。主机按 1、2、3 顺序轮询不建议跳地址排查哪台从机没响应时顺着序号找更快。从机地址在代码里用宏定义烧录前确认每台的MY_ADDR都不重复。同地址的两台从机会在收到读命令后同时把帧发到总线发生数据碰撞主机收到的第一个字节往往是乱码。联调时遇到乱码第一反应就该是查地址重复。Proteus 里一主多从的连线把所有 MAX485 的 A 引脚用一个网络标签连起来B 脚同理从机节点从主线引出的线尽量短。实物接线是手拉手菊花链仿真图里也按手拉手画能避免理解偏差。回帧方向切换时序与主机相同从机回完帧后也要延时再切回接收态。5. 联调与验证把 RS485 多机通信在 Proteus 里跑通5.1 用 VSPD COMPIM 做外部主机Proteus 的 COMPIM 能把单片机串口桥接到 Windows 虚拟串口。在 VSPD 里添加一对 COM3-COM4Proteus 中 COMPIM 绑定 COM3宿主机串口助手打开 COM4串口助手就成了外部主机。这套链路验证的是帧协议而不是差分信号因为 COMPIM 只接在 MAX485 的 TTL 侧。注意 Proteus 关闭时 COMPIM 占用的串口不能被其他程序锁定否则仿真启动会报 Open 失败。5.2 用串口助手校验帧数据从机回帧的格式是 AA 从机地址 0x02 湿度 温度 校验。例如收到AA 01 02 1C 1E E70x1C 是 28%RH0x1E 是 30℃校验和0xAA 0x01 0x02 0x1C 0x1E 0xE7与最后一字节相符这帧就是合法的。串口助手一般带累加和计算可以用工具核验不用逐帧手算。5.3 在仿真图上挂虚拟示波器看停止位怀疑方向切换截断帧尾时把 Virtual Oscilloscope 挂在单片机 TXD 引脚上看波形。UART 空闲为高起始位是低脉冲停止位回到高。如果看到最后一个字节的停止位高电平变短基本就是 DE 切早了回到 4.4 的表格把延时调大。5.4 换到 STM32 时要改的三处把整套方案搬到 STM32 只改单片机相关部分串口引脚重映射和 GPIO 模式TXD 推挽复用、RXD 浮空输入发送等待标志从 TI 换成 TXE接收中断从单字节状态机升级为环形缓冲区。协议帧、地址规划、半双工切换延时这些都不用动改造量集中在串口外设初始化和中断缓冲区的实现上。本文还有配套的精品资源点击获取
返回列表