ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

51单片机双机通信之Proteus仿真与数码管显示设计

51单片机双机通信之Proteus仿真与数码管显示设计 简介基于51单片机的双机通信完整工程包面向单片机初学课设与Proteus仿真爱好者。方案通过甲乙两机协同演示核心交互甲机按键可依次切换全灭、LED1亮、LED2亮、全亮四种状态并同步控制甲、乙两机LED乙机按键则向甲机发送0-9数字由甲机数码管实时显示帮助理解串行通信、数码管驱动、按键消抖及多机控制逻辑。包内共51个文件涵盖Keil源码与hex、Proteus仿真DSN、原理图SchDoc、甲乙方流程图、元件清单xlsx及功能说明txt压缩包约1.05MB目录清晰便于对照查阅。已有241人学习下载。读者可借此快速搭建仿真工程核对电路连接复用模块化收发代码也可作为调试双机通信协议、数码管动态刷新和LED状态机的直接参考模板。1. 基于51单片机的双机通信到底在解决什么问题一块单片机独自完成采集、显示、控制是绝大多数课程设计和入门项目的常态。但一旦遇到两块板子需要互相传数据——主机把数字发给从机显示、从机把状态回传给主机——单机方案就完全失效了。基于51单片机的双机通信本质上是利用51系列自带的UART串口外设让两块芯片通过TXD/RXD两根线完成数据交换再配合数码管、LED把通信结果直观呈现出来。这个标题里同时出现数码管、数字和LED意味着实验板上的可视反馈部分是项目验收的重点发送端要有按键或拨码输入接收端要把收到的数字实时显示在数码管上LED用来指示通信状态。适合的人群很明确正在做51单片机课程设计的学生、想补全串口通信这块短板的嵌入式初学者以及需要快速在Proteus里验证通信逻辑、不想反复烧板子的工程师。这套方案的现实意义在于双机通信是I2C、SPI、CAN等一切板间通信的基础把串口这一关打通后面学什么都顺。2. 串口链路、波特率与帧协议——双机通信的物理层和数据链路层设计2.1 TXD/RXD交叉连接与电平匹配通信链路先物理打通双机通信的第一步不是写代码而是把线接对。51单片机的串口是TTL电平两根数据线分别是P3.1TXD发送和P3.0RXD接收。两块单片机直连时规则只有一条A的TXD接B的RXDA的RXD接B的TXD两块板的GND必须共地。很多人在Proteus里仿真时忽略共地结果数据完全错乱这在原理图阶段就要避免。// 串口初始化代码后面会详细拆解 void UART_Init() { SCON 0x50; // 串口模式18位UART允许接收 TMOD 0x0F; // 清空定时器1的模式位 TMOD | 0x20; // 定时器1设为模式28位自动重载 TH1 0xFD; // 波特率9600晶振11.0592MHz TL1 0xFD; TR1 1; // 启动定时器1 ES 1; // 打开串口中断 EA 1; // 打开总中断 }如果是远距离传输或者连接PC串口TTL电平扛不住需要MAX232做电平转换把TTL转成RS-232电平。但两块51单片机之间做双机通信距离在实验板范围内直接TTL互联即可不需要转换芯片。Proteus仿真同理虚拟环境里没有线缆长度和干扰问题直连最干净。2.2 波特率误差为什么11.0592MHz是教科书的默认答案串口通信双方必须约定相同的波特率否则接收方采样到的比特位全是错的。51单片机的串口波特率由定时器1的溢出率决定公式为波特率 (2^SMOD / 32) × 定时器1溢出率定时器1工作在模式28位自动重载溢出率 晶振频率 / (12 × (256 - TH1))。代入11.0592MHz晶振、9600波特率、SMOD0算出TH1 256 - 11059200 / (12 × 32 × 9600) ≈ 253也就是0xFD。这是绝大多数教材和教程的标准配置。关键问题在于晶振频率的选择。如果手里只有12MHz晶振算下来TH1 256 - 12000000 / (12 × 32 × 9600) ≈ 252.7取整后实际波特率约10417误差约8.5%。串口通信要求误差不超过2.5%左右这个偏差会导致乱码。11.0592MHz这个奇怪数值就是为了让9600波特率误差恰好为0而选定的。Proteus仿真中晶振可以随意指定但代码里写死的是TH1值所以务必保持晶振、TH1、波特率三者一致。在Proteus里双击单片机修改晶振频率为11.0592MHz这是双机通信仿真不翻车的前提。2.3 帧协议防止收到一字节乱码就把整个系统带偏串口底层只保证字节传输不保证语义完整性。接收方如果每收到一个字节就当作有效数据一旦线上有干扰字节整个数据流就错位了。所以双机通信必须要有一层帧协议这是「双机通信」与「串口发送单个字符」的分水岭。常见做法是定义一个固定格式的帧帧字段字节数说明帧头1固定0xAA标识一帧开始命令/类型1如0x01表示发送数字0x02表示查询状态数据长度1后续数据字节数数据N实际内容如要显示的两位数字校验和1前面所有字节累加取低8位接收端的状态机逻辑是空闲状态等待帧头0xAA收到后进入接收数据状态按长度字段收完数据最后做校验。校验通过才更新数码管显示校验失败直接丢弃整帧。这样即使收到一个坏字节也只会丢掉一帧不会把错误数据显示出来。LED可以设计成接收成功时翻转一次直观指示通信质量。3. 在Proteus里搭出可仿真的双机通信电路含数码管与LED3.1 元件清单与选型数码管必须选对共阳还是共阴Proteus 8 Professional是目前课程设计最常用的版本。打开ISIS界面后需要从元件库中取出的元件包括元件名称库中的检索关键字用途AT89C51AT89C51主控芯片两块7SEG-MPX4-CC7SEG-MPX4-CC共阴四位数码管7SEG-MPX4-CA7SEG-MPX4-CA共阳四位数码管二选一LED-YELLOWLED-YELLOW通信状态指示RESPACK-8RESPACK-8P0口上拉电阻排BUTTONBUTTON发送端数字输入CRYSTALCRYSTAL11.0592MHz晶振CAPCAP22pF负载电容晶振两端CAP-ELECCAP-ELEC10μF复位电容数码管的选择直接影响段码表。Proteus里7SEG-MPX4-CC是共阴Common Cathode7SEG-MPX4-CA是共阳Common Anode。共阳数码管段码为0xC0、0xF9、0xA4等共阴的段码则是0x3F、0x06、0x5B。代码里一旦写反显示结果会极其诡异。这次标题里的「数码管数字LED」三个词同时出现通常意味着数码管显示对方发来的两位数字LED显示通信握手是否成功。3.2 双机互联的关键连线方式Proteus里放置两块AT89C51左侧为发送机A右侧为接收机B。A的P3.1TXD连到B的P3.0RXDA的P3.0RXD连到B的P3.1TXD两个GND引脚直接相连。两条连线在原理图上构成一个交叉很多初学的人在这里连成TXD接TXD结果自己发给自己收数据永远到不了对方。P0口作为数码管的段码输出口必须接上拉电阻排RESPACK-8一端接P0的8个引脚另一端接VCC。很多人第一次画原理图时漏掉这一步仿真时P0输出高电平能力不足数码管亮度极低甚至不显示。EA引脚必须接VCC否则单片机默认从外部ROM取指令程序根本跑不起来。复位电路用标准的10μF电容加10kΩ电阻即可Proteus里用按钮模拟复位也行但课设报告里建议画出完整RC复位电路。两块单片机各自的晶振电路都要接完整的电容负载——两个22pF电容分别从晶振两端接地。Proteus里即使不接电容仿真也能出结果但原理图作为交付物时缺少负载电容会被老师挑毛病。3.3 用虚拟终端先做单机收发验证在连接两块单片机之前先单独验证发送机的串口是否正常。从元件库中调出VIRTUAL TERMINAL虚拟终端它的RXD脚接单片机的TXD脚TXD脚接单片机的RXD脚GND接GND。烧入一个简单的循环发送程序后点击仿真虚拟终端里应该能周期性看到字符输出。这个步骤能在5分钟内排除「单片机根本没发数据」还是「接收端解析有问题」的嫌疑。虚拟终端本身是TTL电平直接连51单片机没问题。4. 51单片机C语言实现数码管动态扫描与串口收发4.1 数码管段码表与动态扫描的时序分配四位数码管如果是静态显示需要4个锁存器各自锁存段码占用大量I/O。动态扫描的常见做法是段码接P0口位选接P2口的低4位轮流点亮每一位。人眼视觉暂留约20ms只要每位刷新频率不低于50Hz看起来就是同时亮的。// 共阳数码管段码表0-F unsigned char code segCodeCA[] { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; void Display_Scan() { unsigned char i; unsigned char digit[4]; digit[0] displayNum % 10; // 个位 digit[1] displayNum / 10 % 10; // 十位 digit[2] displayNum / 100 % 10; // 百位 digit[3] displayNum / 1000; // 千位 for (i 0; i 4; i) { P0 segCodeCA[digit[i]]; // 段码 P2 ~(0x01 i); // 位选低电平有效共阳 Delay_Short(); // 每位停留约2ms P0 0xFF; // 消隐防止拖影 } }位选用~(0x01 i)是因为共阳数码管的公共端接高电平、位选端通过PNP三极管或直接拉低才导通。很多Proteus仿真里直接用P2口输出低电平选中某一位没接三极管这在实际硬件上驱动能力是不够的但纯仿真阶段可以工作。代码里的消隐步骤很重要如果不先把P0置0xFF就切换下一位数码管会显示残影。4.2 串口中断接收一字节一收帧状态机驱动串口接收比发送更讲究。发送端可以在主循环里主动发但接收端不知道数据何时到达必须用中断。51单片机的串口中断入口是interrupt 4无论收发都进同一个中断RI置1表示接收完毕TI置1表示发送完毕中断服务函数里要区分这两个标志。unsigned char rxBuffer[8]; unsigned char rxCount 0; unsigned char frameReady 0; unsigned char expectedLen 0; unsigned char checkSum 0; void UART_ISR() interrupt 4 { unsigned char ch; if (RI) { RI 0; ch SBUF; // 简单的帧状态机 if (rxCount 0 ch ! 0xAA) return; // 等待帧头 rxBuffer[rxCount] ch; if (rxCount 3) expectedLen ch; // 第3字节是数据长度 if (rxCount 4 expectedLen) { // 收完整个帧 checkSum 0; for (unsigned char i 0; i rxCount - 1; i) checkSum rxBuffer[i]; if (checkSum rxBuffer[rxCount - 1]) { frameReady 1; // 校验通过主循环处理 } else { rxCount 0; // 校验失败丢弃重来 } } } if (TI) TI 0; // 发送中断清零 }注意中断服务函数里只做收数据和置标志不处理显示、不更新数码管。51单片机的中断里做耗时操作会阻塞主循环导致数码管闪烁。frameReady置1后主循环里检测到这个标志取出数据更新displayNum再清标志。这个「中断存数据、主循环做事情」的分层是嵌入式开发的通用范式也是这个项目里最容易拿高分的设计点。4.3 发送端按键输入与LED状态回显发送端的逻辑是检测矩阵键盘或独立按键按下读取当前拨码开关的数字通过串口发送一帧数据发送过程中点亮LED发送完毕后熄灭。拨码开关接P1口读取值就是0-255的数字刚好可以覆盖两位数显示范围。void Send_Number(unsigned char num) { unsigned char frame[5]; frame[0] 0xAA; // 帧头 frame[1] 0x01; // 命令字发送数字 frame[2] 0x01; // 数据长度1字节 frame[3] num; // 要发送的数字 frame[4] frame[0] frame[1] frame[2] frame[3]; // 累加校验 LED_SEND 0; // 点亮发送指示LED for (unsigned char i 0; i 5; i) { SBUF frame[i]; while (!TI); // 等待发送完成 TI 0; } LED_SEND 1; // 发送完毕熄灭 }发送用查询方式接收用中断方式这是嵌入式里最常见的组合。查询发送简单可靠中断接收不丢数据。LED_SEND接到P2.4口注意这里低电平点亮是假设LED另一端接VCC接法不同极性就得反过来。5. 虚拟终端验证、波特率误差纠偏与仿真调试的实操技巧5.1 用虚拟终端替代接收机验证发送帧结构把两块单片机连跑之前先断开B的RXD引脚把虚拟终端的RXD接到A的TXD上。点击Proteus左下角的运行按钮在发送机上触发一次发送虚拟终端里应该看到5个字节的十六进制数据AA 01 01 数字 校验。如果看到的是乱码首先检查波特率其次检查晶振频率这两个是最常见的翻车点。虚拟终端默认显示ASCII字符要在虚拟终端属性里把Display ASCII勾选去掉改成Hex模式才能看到原始十六进制帧。5.2 波特率误差速查表与代码参数对应关系晶振频率目标波特率TH1实际值实际波特率误差11.0592MHz96000xFD96000%11.0592MHz48000xFA48000%12MHz96000xFD104178.5%12MHz48000xF348000%表格里12MHz配9600波特率的8.5%误差在Proteus里可能能跑通因为虚拟环境没有实际电气噪声但如果拿到真实硬件上大概率出现偶发乱码。12MHz晶振想要串口通信要么把波特率降到4800要么换11.0592MHz晶振。Proteus仿真中修改晶振频率只需要双击单片机在属性面板里改代码里的TH1也同步修改即可。5.3 仿真调试的3个高频坑第一个坑是P0口忘接上拉电阻。P0是开漏结构不接上拉时输出高电平能力极弱数码管可能暗到看不清。第二个坑是两块单片机都用了内部复位但没接EA引脚程序运行时地址总线上乱跳表现为数码管乱闪。第三个坑是帧协议里没有超时复位机制如果发送方只发了半帧就停住接收方的rxCount一直停在某个位置后续所有数据全都错位。解决方法是加一个字节超时判断例如主循环里用定时器检测「距离上次收到字节超过50ms就清零rxCount」。这个细节在实际项目中能避免一半以上的通信故障。5.4 把HC05换成51直连的扩展思路热词里出现HC05蓝牙双机通信如果后续想把有线双机通信升级成无线只需要把串口线断开两端各接一个HC05蓝牙模块一个配主模式一个配从模式硬件上本质上还是UART到UART代码层面完全不需要改动。这就是串口通信的通用性所在——无论是直连、RS232转接、还是蓝牙透传单片机看到的都是SBUF寄存器。先在有线双机通信上把帧协议和状态机调通再换传输介质迁移成本极低。课程设计答辩时展示这个扩展思路会比单纯跑通演示更有深度。本文还有配套的精品资源点击获取
返回列表