
简介基于51单片机与Proteus仿真的无线叫号系统设计资源面向单片机课程设计、电子竞赛及医院/银行等需要排队取号与叫号联动的场景适合基础学习者动手实践。系统包含主机与从机两个终端主机侧通过独立按键完成叫号数码管清晰显示当前被叫号码蜂鸣器同步发声提醒顾客从机侧基于串行通信完成自助取号功能并实时显示队列前方等待人数从而实现双机协同的无线叫号流程。压缩包共61个文件主要涵盖Proteus仿真图、AD原理图、Keil工程源码C语言与汇编启动代码、hex烧录文件、原理图PDF预览及设计文档等整体约1.82MB目录结构清晰便于按需查阅。目前已有69人学习资料中附有文件清单与说明文本可辅助理解各模块功能和引脚连接。整套资源不仅覆盖多机通信、数码管动态显示、按键处理、蜂鸣器驱动等核心知识点还提供可直接运行与修改的工程方便二次开发是一套完整且易上手的课程设计参考方案。1. 无线叫号机仿真51单片机项目到底在仿什么你按一下取号按钮柜台再按一次“呼叫下一号”显示屏上就多一位号码这就是叫号系统的全部业务闭环。现实中它由射频模块、高低频震荡电路和数码管显示共同完成但落到“基于51单片机protues仿真的无线叫号机”这种课程设计上最容易被绕进去的地方是Protues仿真里根本没有空气也没有电磁波。所谓“无线”在仿真图中的真实形态是一根把发射端I/O和接收端I/O直接连起来的导线或者干脆只是一个同名网络标号。因此这个项目真正要仿的是链路协议不是载波调制。你要处理的只有三件事发射端按键怎么把号码编成脉冲串接收端怎么把脉冲串解出来以及这段数据如何在51单片机的定时器和外部中断之间流转。把这三件事拆开再配上数码管显示、蜂鸣器提示和AD原理图重绘就是一个可以在Proteus里反复运行、也能拿去答辩的完整设计。文章写给正在做51单片机课程设计的人也适合已经能点亮LED、想再走一个带通信协议的项目练手的同行。2. 51单片机无线叫号系统架构、选型与链路分工2.1 叫号链路先拆成四块再决定用什么器件一套完整的无线叫号机从功能上可以拆成四个独立块按键取号与呼叫输入、编码发射、解码接收、号码显示。实体产品里这四块有各自的电路而在51单片机protues仿真里最常见的做法是两块AT89C51芯片分别承担发射和接收中间用一对PT2262/PT2272编解码芯片充当无线链路的数据载体。功能块与器件选型可以按下表来定功能块常用器件仿真中的作用发射端主控AT89C51 / STC89C52读取按键状态生成叫号数据帧编码发射PT2262 或 I/O 模拟把地址和号码打成串行脉冲接收端主控AT89C51外部中断接收脉冲软件解码解码接收PT2272 或 中断定时器识别同步码和数据位号码显示两位共阳数码管 / LCD1602显示当前排队号码提示单元蜂鸣器、LED取号成功、呼叫提示这里先说一个原则仿真时如果Protues元件库有PT2262和PT2272可以直接放置并连接它们的Dout与Din引脚如果库版本里没有这两个芯片不要硬等用51的I/O口模拟2262的发射时序即可。“51单片机模拟pt2262工作及发射”本身就是很多课程设计的标准退路它绕开了芯片库缺失问题也让时序变成可调试的源代码。你在答辩时还能多讲一句“载波调制不是本设计重点”反而把项目核心聚焦到叫号逻辑上。2.2 无线链路参数同步码、数据位“1”和“0”的宽度比PT2262的编码格式是串行脉冲典型参数为同步码由4T高电平和124T低电平组成数据位“1”在一个码元宽T内先高电平后低电平比例约2:1数据位“0”则反之比例约1:2。这里的T由编码芯片的振荡电阻决定典型值振荡电阻选1.2MΩ解码端PT2272选200kΩ左右。关键参数整理成表参数项典型值说明振荡电阻发射端1.2 MΩ决定编码时钟T振荡电阻接收端200 kΩ需要与发射端匹配同步码4T 高 124T 低帧起始标志数据位 1高2/3 T 低1/3 T用脉宽比例表示数据位 0高1/3 T 低2/3 T与电平绝对值无关地址位A0~A7 三态可设高、低、悬空在仿真环境中我不会真的去按比例还原射频载波而是用一组方波代替同步码发送一段较长的低电平数据位用不同的高电平持续时间区分“1”和“0”。这样接收端只需要一个定时器测量脉冲宽度就能完成解码。下面两行定义就是仿真里替代天线和射频模块的最小连接sbit RF_TX P1^0; // 发射端输出替代PT2262的Dout引脚 sbit RF_IN P3^2; // 接收端外部中断输入替代PT2272的Din引脚在Protues里把RF_TX和RF_IN直接用导线连起来或给两端取同一个网络名就完成了无线链路的仿真等效。载波、天线增益、接收灵敏度这些参数在这个层级上不需要考虑因为51单片机只能识别高低电平而编码数据也是靠高低电平持续时间传递的。2.3 51单片机引脚资源分配避免显示和通信打架一块AT89C51的I/O资源做这种项目够用但要注意P0口是开漏结构驱动共阳数码管时需要在每一位加10kΩ上拉电阻P2口驱动位选时也要注意电流限制。发射端和接收端的引脚分配建议如下功能发射端引脚接收端引脚取号按键P3.2-呼叫下一号按键P3.3-无线数据输出/输入P1.0P3.2 /INT0数码管段码P0P0数码管位选P2.0~P2.1P2.0~P2.1蜂鸣器-P1.7接收端选择P3.2作为无线数据输入是因为它同时也是外部中断INT0引脚下降沿可以自动触发中断配合定时器测脉宽比在主循环里轮询电平更稳定。发射端不需要中断按键扫描放在主循环即可。这样分配之后代码里不会出现两个功能抢同一个引脚的问题后续画AD原理图时网络关系也清晰。3. 在Protues里搭建无线叫号系统仿真图3.1 放置51芯片与最小系统Protues入门常错的三个点打开Protues后第一步是通过左侧Component Mode点“P”进入元件库。搜索AT89C51添加主控芯片再搜索RES、BUTTON、CAP-ELEC、7SEG-COM-ANODE添加电阻、按键、电解电容和共阳数码管。具体操作可以按下面顺序执行1. 点击左侧工具栏的 Component Mode元件模式 2. 点击对话框左下角 PPick Devices打开库浏览器 3. Keywords 输入 AT89C51双击添加到设计 4. 继续搜索 RES、BUTTON、CAP-ELEC、7SEG-COM-ANODE 5. 放置元件后右键旋转元件按已有图纸布局Protues入门最容易错的有三个地方第一晶振不用像画AD原理图那样非要放一个XTAL只要双击单片机在“Clock Frequency”属性里填12MHz即可第二复位电路不是必须加仿真里RST脚悬空也能跑但如果要画AD原理图就必须补上10kΩ复位电阻和10μF电容第三放置电阻后要改阻值用鼠标双击电阻元件直接改而不是重新搜索。3.2 无线链路直连与网络标号通信引脚这样接发射端RF_TX和接收端RF_IN的连线可以采用两种方式布局在同一张图纸时直接放置Wire连接如果为了整洁把发射和接收分成两个区域则用“LBL”工具放置网络标号。给P1.0所在的导线命名RF_TX给接收端P3.2所在导线也命名RF_TX两者就默认电气连接不需要拉一根横穿整张图的线。这里涉及一个常见问题“protues怎么添加引脚”如果你需要的芯片在库里找不到现成符号可以用左侧Terminal Mode里的DEFAULT引脚放置后用导线连接并改名。但大多数情况下直接用51引脚替代编解码芯片更高效。仿真的重点是协议是发送端和接收端之间这根线上跑的时序不是引脚封装本身。连接完成的检查点有三个发射端P1.0是否接到网络RF_TX接收端P3.2是否也接入RF_TX两边的GND是否统一接入同一地网络。Protues仿真中即使不画GND线芯片的GND引脚默认连接也会参与仿真但养成接地的习惯对后面AD原理图重绘有好处。3.3 数码管接线、电源设置与HEX文件装载叫号号码用两位数字显示就足够一位显示十位一位显示个位。段码通过共阳数码管的a~g、dp引脚接51的P0口位选接P2.0和P2.1。如果代码里段码表按共阳方式编码这里就不能接共阴数码管否则显示会反相表现为数字乱跳或相同段全亮。装载编译好的HEX文件是让仿真跑起来的最后一步操作如下1. 双击AT89C51芯片打开 Edit Component 对话框 2. Program File 一栏选择 Keil 输出的“叫号发射端.hex” 3. Clock Frequency 保持 12MHz与Keil工程设置一致 4. 同样方式给接收端单元格载入“叫号接收端.hex” 5. 点击左下角运行按钮Program File是编译后的目标文件Protues通过它模拟单片机执行程序因此程序逻辑错误只能在源码层面修改后重新编译。Clock Frequency必须和Keil中选用的晶振一致否则软件延时或定时器超时的时间基准就会整体偏移表现为发射端发送过快、接收端解码失败。仿真报错时优先查看仿真控制台最后一行的错误信息最常见的两类错误是HEX路径为空和元件引脚重复连接。4. Keil C源代码实现叫号编码、解码与显示逻辑4.1 发射端源代码取号、呼叫下一号与脉冲帧生成发射端负责两件事按取号键时把当前排队号加一按呼叫键时发送最新号码。数据帧结构我固定为“同步码 1字节地址 1字节号码”地址固定为0x5A号码范围1~99。下面是发射端最核心的三个函数/* 发射端主程序取号、呼叫、发送一帧数据 */ #include reg51.h #define ADDR_CODE 0x5A // 发射端与接收端约定的地址 sbit KEY_TAKE P3^2; // 取号按键 sbit KEY_CALL P3^3; // 呼叫下一号按键 sbit RF_TX P1^0; // 无线发射引脚 unsigned char current_no 1; void delay_us(unsigned int n) { while (n--); } void delay_ms(unsigned int n) { unsigned int i, j; for (i 0; i n; i) for (j 0; j 120; j); } void send_frame_head(void) { RF_TX 1; delay_us(400); // 同步码高电平 RF_TX 0; delay_us(1200); // 同步码低电平 } void send_byte(unsigned char dat) { unsigned char i; for (i 0; i 8; i) { if (dat 0x80) { // 数据位“1”宽高电平 窄低电平 RF_TX 1; delay_us(600); RF_TX 0; delay_us(300); } else { // 数据位“0”窄高电平 宽低电平 RF_TX 1; delay_us(300); RF_TX 0; delay_us(600); } dat 1; } } void send_frame(unsigned char no) { send_frame_head(); send_byte(ADDR_CODE); send_byte(no); delay_ms(10); } void main(void) { while (1) { if (KEY_TAKE 0) { while (KEY_TAKE 0); // 松手消抖 send_frame(current_no); // 取号并发送当前号 } if (KEY_CALL 0) { while (KEY_CALL 0); if (current_no 99) current_no; send_frame(current_no); // 呼叫下一号 } } }这段代码的关键在于把“无线发射”理解成一组不同宽度的方波。同步码的400μs高电平加1200μs低电平是接收端判断帧起始的边界数据位“1”和“0”的脉宽比例是2:1只要接收端能识别这个比例就能解码不需要关心绝对时间精度。地址码0x5A放在每帧第二段目的是过滤相同环境里可能存在的其他干扰帧。注意这里使用了源码中的软件延时在Keil默认优化级别O0下时序基本稳定如果开启高优化必须改成定时器延时。4.2 接收端源代码外部中断配合定时器做脉冲宽度解码接收端如果用轮询方式读RF_IN51单片机单周期指令会漏掉短脉冲因此正确做法是把数据线接到INT0利用下降沿触发中断同时用Timer0记录两次下降沿之间的时间。宽度大于设定的经验阈值时判为“1”小于阈值判为“0”超长的低电平则判定为同步码并复位当前字节。/* 接收端中断解码INT0下降沿 T0测脉冲宽度 */ #include reg51.h #define ADDR_CODE 0x5A #define WIDTH_1 450 // 经验阈值单位是定时器计数 sbit BUZZER P1^7; volatile unsigned char rx_byte 0; volatile unsigned char bit_cnt 0; volatile unsigned char state 0; volatile unsigned char recv_no 0; volatile unsigned char frame_ready 0; void timer0_init(void) { TMOD 0x01; // 定时器016位模式 TH0 0; TL0 0; ET0 0; TR0 1; } void int0_isr(void) interrupt 0 { unsigned int t; t (TH0 8) | TL0; // 读取上次清零到这次的计数 TH0 0; TL0 0; if (t 1200) { // 同步码对应的超长低电平 state 0; bit_cnt 0; rx_byte 0; return; } if (t WIDTH_1) rx_byte | 0x80 bit_cnt; // 宽电平判为“1” if (bit_cnt 8) { bit_cnt 0; if (state 0 rx_byte ADDR_CODE) { state 1; // 地址接收成功准备号码 rx_byte 0; } else if (state 1) { recv_no rx_byte; // 号码字节 frame_ready 1; state 0; rx_byte 0; } else { state 0; rx_byte 0; } } } void main(void) { IT0 1; // INT0下降沿触发 EX0 1; EA 1; timer0_init(); while (1) { if (frame_ready) { frame_ready 0; BUZZER 0; // 低电平驱动蜂鸣器 // 此处调用数码管显示 recv_no BUZZER 1; } } }接收解码最核心的判定动作发生在中断里读TH0和TL0拼接出两次下降沿之间的时间t然后把t和阈值WIDTH_1比较。阈值450的取值依据是12MHz晶振下350μs对应的定时器计数约为420600μs约为720取中间值450能稳定区分。同步码因为低电平持续1200μs计数超过1200可以放心作为帧复位信号。使用外部中断的好处是CPU不参与电平轮询主循环可以同时处理数码管动态扫描和蜂鸣器控制不会因为显示刷新丢数据。4.3 叫号逻辑的边界防抖、重复帧和号码上限叫号系统看似简单实际跑仿真最容易出的问题有两个一次按键发出多帧以及号码超过99后溢出。前面的代码已经用while等待松手处理了按键抖动但如果你用的是实体按键最好在while里加一段5ms延时再判断IO电平否则机械抖动可能导致一次按下被当成两次。发射帧重复发送问题可以通过在接收端加一个“上次号码缓存”解决连续两帧号码相同且值不为0时只刷新显示不触发蜂鸣器。现象常见原因对策按一次取号键跳两个号按键消抖不足主循环加松手检测必要时加5ms延时接收端显示乱码地址字节或号码字节顺序错检查帧结构确认先发地址再发号码号码超过99后退回0unsigned char溢出发送前判断current_no是否小于99仿真运行时死循环定时器未清零或中断标志未清在中断入口重新赋TH0、TL0这段逻辑做完发射端和接收端的源代码就已经能配合Protues仿真图完整跑通。下一步要做的是把同样的电路从仿真图搬成可生产的AD原理图并在转换中验证连接关系。5. AD原理图重绘与仿真波形验证5.1 从Protues仿真图到AD原理图的重绘路径Protues的仿真图和AD原理图不能直接一键互导常见做法是重绘。重绘时把发射端和接收端放在两个Sheet中用同网络名跨页连接。在AD里放置网络标号的快捷键是P和N放置后双击网络标号可改名要跳转同名网络时先点选中一个Net Label再通过“Edit - Jump”输入网络名即可定位到另一页相同网络这也是处理AD原理图网络跳转最直接的方法。重绘前先把Protues里的连接关系整理成列表逐项检查。电源和地是AD中最容易漏掉的部分Protues仿真里POWER端子会自动提供5V逻辑电平但AD必须显式安排电源网络发射端和接收端各放一个电源地网络混合信号电路不能有悬空的电源引脚。5.2 AD原理图规则检查与常见警告处理AD检查原理图有没有连上用的是工程编译功能。在工程面板右键项目名选择Compile PCB ProjectMessages面板会把所有Error和Warning列出来。这里的Error通常代表网络短路或引脚悬空必须清零Warning常见于未连接电源引脚或元件位号重复例如两个AT89C51的复位引脚没有网络标号DRC会报“Unconnected Pin”。处理方法是给未连接引脚放置“No-ERC”标记或者直接补上网络。要注意的是Protues允许IO悬空不报错AD中悬空I/O引脚会被严格提示这会逼着你去确认每一个引脚的实际用途。5.3 用Protues虚拟示波器实测时序验证发射与解码一致性代码和AD原理图都完成后回到Protues重新运行仿真调出左侧虚拟仪器里的OSCILLOSCOPE把通道A接RF_TX网络通道B接接收端解码输出缓冲引脚的暂态点。运行后用示波器观察波形重点看三点1. 帧与帧之间是否有间隔间隔是否稳定 2. 同步码之后是否跟着两组数据位 3. 高电平宽度与低电平宽度比例是否符合2:1如果同步码后没有数据位检查发射端send_frame是否在同步头之后调用send_byte如果数据位全是等宽方波检查WIDTH_1阈值是否把数据和同步码混在一起。你可以给示波器的横轴调到1ms/div一轮帧总共约20ms五格内就能看到完整帧结构。这个方法比直接看数码管显示结果更早暴露时序问题因为数码管可能恰好显示正确但帧边界已经错位换一组号码就乱。把示波器截图留存答辩时可以直接作为测试依据也方便后续把同样的验证流程复制到其他51单片机硬件设计项目里。本文还有配套的精品资源点击获取