简介:这份单片机课程设计排队叫号系统设计资料,面向电子信息工程、自动化、计算机科学与技术等专业的学生及工程师,围绕课程设计从任务书到报告撰写的完整流程展开,可作为排队叫号系统设计、单片机课程考核与答辩准备的参考样例。资源为单一PDF文件,压缩包约2.83MB,内容集中,便于查阅。文中依次覆盖取票、休息等待、按键叫号、前去办理四项功能,并给出系统需求分析与整体设计、排队系统工作流程、数据处理流程、客户与工作人员工作流程、硬件与软件概要设计。硬件部分细化主机与从机电路、单片机最小系统、液晶显示、按键、蜂鸣器及TXD/RXD串行收发电路,软件部分包含主从机程序、蜂鸣器、LCD显示和窗口消号子程序,并延伸至Proteus仿真实现。已有1299人学习下载,适合需要完整报告结构、电路设计思路与仿真验证方法的读者参照。
1. 从窗口叫号到单片机排队叫号系统:课程设计要落地什么
银行柜面、医院分诊、食堂取餐都有一个共同动作:顾客先拿号,屏幕显示当前号码,窗口按键叫下一位。排队叫号系统的课程设计常被做成“数码管加几个按键”,真正要拿高分,得把取号、等待、叫号、过号、清零串成稳定状态机。主控用 51单片机、STC单片机都行,外设用 LCD1602 或数码管、矩阵键盘、蜂鸣器和串口。适合单片机课程设计、毕业设计入门,也适合拿蓝桥杯单片机基础模块练手。核心不是界面多花,而是队列不乱、掉电不丢号、窗口不重复叫号。
2. 排队叫号系统的硬件选型与最小系统搭建
课程设计里,排队叫号系统不是拼外设数量,而是先确认“窗口叫号”这条主线。单窗口、号码小于 50、只要求数码管和按键,51单片机足够;需要掉电保存、串口上报、多窗口,STC单片机更省事;需要语音播报和触摸屏,才考虑 STM32。选型错了,后期串口、EEPROM 和定时器都会卡。
2.1 排队叫号系统主控与显示选型:51、STC 和 STM32 的差别
| 方案 | 典型资源 | 适合的排队叫号系统规模 | 课程设计风险 |
|---|---|---|---|
| 51单片机 | 4KB Flash/128B RAM,2 个定时器 | 单窗口,LCD1602,30 个号以内 | RAM 紧,队列别用链表 |
| STC单片机 | 内部 EEPROM,部分型号双串口,ISP 烧录 | 单/双窗口,掉电保存,串口屏 | 头文件寄存器和普通 51 有差异 |
| STM32 | 多串口,定时器多,主频高 | 多窗口、语音、上位机 | 外设初始化复杂,调试时间翻倍 |
提示:Proteus 仿真优先选 AT89C51 这类经典 51 内核,代码可直接迁到 STC单片机,注意 STC 的头文件和 ISP 寄存器不同。
2.2 GPIO 分配与最小系统接线:把取号键、LCD 和蜂鸣器接到 P 口
| 功能 | 引脚 | 电平/参数 | 说明 |
|---|---|---|---|
| 取号键 | P1.0 | 低有效 | 10k 上拉,按下接地 |
| 叫号键 | P1.1 | 低有效 | 窗口人员按 |
| 过号键 | P1.2 | 低有效 | 当前号作废或重排 |
| 蜂鸣器 | P1.3 | 三极管驱动 | 高电平响或低电平响看电路 |
| LCD1602 数据 | P0.0-P0.7 | 8 位 | P0 需 10k 排阻上拉 |
| LCD1602 控制 | P2.0-P2.2 | RS/RW/EN | RW 可接地省线 |
| 串口 | P3.0/P3.1 | RXD/TXD | 接 USB-TTL 时交叉 |
#include <reg51.h> sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; sbit LCD_EN = P2^2; sbit KEY_TAKE = P1^0; sbit KEY_CALL = P1^1; sbit KEY_PASS = P1^2; sbit BEEP = P1^3; void gpio_init(void) { P0 = 0xFF; /* LCD 数据口置高,配合外部排阻上拉 */ P1 = 0xFF; /* 按键输入先置高,外部 10k 上拉 */ P2 = 0x00; BEEP = 0; /* 按驱动电路调整:低电平关蜂鸣器 */ } void beep_short(void) { unsigned int i; BEEP = 1; /* 高电平鸣叫,若用 PNP 三极管则改为 0 */ for (i = 0; i < 300; i++); BEEP = 0; }gpio_init 把 P0 置高,因为 51单片机 P0 为开漏,驱动 LCD 数据线需要外部上拉排阻;P1 置高让按键默认高电平,按下读到 0。beep_short 用简单循环产生短鸣,放在主循环里可以,放在定时器中断里要改成计数器,避免中断时间过长。参数说明:LCD 用 8 位模式时 P0 全部被占用;若改用 4 位模式,只接 P0.4-P0.7,能释放 4 根线给状态灯。蜂鸣器若为有源蜂鸣器,给电平即响;无源蜂鸣器需要 2kHz 左右方波,用定时器翻转引脚更稳。
2.3 电源、复位和烧录接口:课程设计板最容易忽略的三处
| 项目 | 常见值 | 说明 |
|---|---|---|
| 晶振 | 11.0592MHz | 串口波特率误差小 |
| 复位电容 | 10uF | 上电复位 |
| 复位电阻 | 10k | 下拉到地 |
| 按键上拉 | 10k | P1 输入 |
| LCD 对比度 | 1k-2k 到地 | 调不清会只亮不显 |
供电用 5V,LCD1602 和蜂鸣器同时工作时电流会上去,USB 口直接带容易掉电复位,建议独立 5V 电源或加 100uF 电解电容。复位电路常见是 10uF 电容到 VCC、10k 电阻到地,STC单片机冷启动烧录时还要保证 RST 脚不悬空。烧录接口用 USB-TTL 时,TXD 接单片机 P3.0,RXD 接 P3.1,GND 必须共地。
注意:STC单片机冷启动烧录时,部分开发板要拔掉其他串口模块,避免 P3.0/P3.1 被占用;Keil5 安装教程51单片机里常选的 AT89C51 没有内部 EEPROM,掉电保存要外挂 24C02。
3. 用 Keil C51 写排队叫号系统核心队列逻辑
课程设计代码常写成 while(1) 大循环,按键一抖就乱。排队叫号系统的核心是队列和状态机。Keil 新建 C51 工程时,选 AT89C51 或对应 STC 型号,晶振填 11.0592MHz,Output 里勾选 Create HEX File,后面 Proteus 仿真和烧录都靠这个文件。
3.1 排队叫号系统队列模型:环形缓冲比动态链表更适合 51
51单片机 RAM 只有 128B,动态链表要指针和 malloc,课程设计里不划算。环形缓冲用固定数组就能表达“先取先叫”,头尾指针移动一位,等待人数单独计数。
#define QUEUE_MAX 32 unsigned char q_buf[QUEUE_MAX]; unsigned char q_head = 0; /* 当前已叫号的下标 */ unsigned char q_tail = 0; /* 下一个取号写入位置 */ unsigned char q_count = 0; /* 队列中等待人数 */ unsigned char take_ticket(void) { unsigned char id; if (q_count >= QUEUE_MAX - 1) return 0; /* 0 表示号池满 */ q_tail = (q_tail + 1) % QUEUE_MAX; id = q_tail; /* 号码从 1 开始,0 保留为无效号 */ q_buf[q_tail] = id; q_count++; return id; }q_head 指向已叫出的号,q_tail 指向最新取号。q_count 比 head/tail 直接判空满更可靠,因为环形队列空和满时 head 与 tail 可能相等。QUEUE_MAX 取 32,实际可用 31 个等待号,足够单窗口课程设计。若号码要显示为 A001,可在显示层格式化,不必把字符串存进队列。参数说明:如果 RAM 紧张,QUEUE_MAX 降到 16;如果号码需要跨天,必须配合 EEPROM 或铁电存储。
3.2 取号、叫号、过号三个动作的状态机实现
| 动作 | 按键 | 队列变化 | 显示 | 蜂鸣 |
|---|---|---|---|---|
| 取号 | P1.0 | tail 后移,count+1 | 显示新号码 | 短鸣 |
| 叫号 | P1.1 | head 后移,count-1 | 显示当前号 | 短鸣 |
| 过号 | P1.2 | 当前号清除或重排 | 显示等待 | 短鸣 |
| 清零 | 组合键 | head=tail=count=0 | 显示 000 | 长鸣 |
unsigned char current_no = 0; unsigned char queue_empty(void) { return (q_count == 0); } unsigned char call_next(void) { if (queue_empty()) return 0; q_head = (q_head + 1) % QUEUE_MAX; current_no = q_buf[q_head]; q_count--; beep_short(); return current_no; } void pass_current(void) { if (current_no != 0) { /* 过号方案一:直接作废;方案二:重新插入队尾 */ current_no = 0; beep_short(); } }call_next 只在队列非空时移动 q_head,把当前号更新为出队号码,q_count 减一。pass_current 只清当前号,不自动叫下一位,窗口人员再按叫号键。若医院场景要求过号后补叫,可以把 current_no 重新执行入队操作,但要注意总等待数增加,屏幕提示“过号重排”。参数说明:current_no 为 0 表示无当前号;按键处理应放在 20ms 定时器扫描里,不要用 while 等待释放。
3.3 定时器去抖与叫号提醒:别在 while 里写 delay
unsigned char key_scan(void) { static unsigned char last = 0xFF; static unsigned char cnt = 0; unsigned char now = P1 & 0x07; /* P1.0-P1.2 */ unsigned char key = 0; if (now != last) { cnt = 0; last = now; } else if (cnt < 3) { cnt++; } else { if (now != 0x07) { if ((now & 0x01) == 0) key = 1; /* 取号 */ else if ((now & 0x02) == 0) key = 2; /* 叫号 */ else if ((now & 0x04) == 0) key = 3; /* 过号 */ } } return key; } void timer0_init(void) { TMOD &= 0xF0; TMOD |= 0x01; /* T0 模式 1,16 位定时 */ TH0 = (65536 - 20000) / 256; /* 20ms @ 11.0592MHz, 12T */ TL0 = (65536 - 20000) % 256; ET0 = 1; EA = 1; TR0 = 1; }key_scan 在定时器中断里每 20ms 调用一次,连续 3 次读到同一状态才确认,等效 60ms 去抖。返回值 1/2/3 分别交给取号、叫号、过号函数处理。timer0_init 使用 16 位定时,11.0592MHz 晶振、12T 模式下 20ms 计数初值约 65536-18432,代码用公式表达,方便换晶振。参数说明:若用 1T 的 STC单片机,定时初值要按实际机器周期重算;LCD 刷新、串口发送不要放在定时器中断里,避免显示闪烁和丢字节。
4. 在 Proteus 里把排队叫号系统跑通:联调与排错
Proteus 仿真电路图能把硬件问题提前暴露,特别是 LCD 数据线、按键电平和串口波特率。先跑最小系统,再接蜂鸣器和上位机,画面动起来后再加语音或上位机界面。
4.1 Proteus 排队叫号系统最小仿真电路搭建步骤
| 元件 | Proteus 关键字 | 参数 | 连接 |
|---|---|---|---|
| MCU | AT89C51 | 11.0592MHz | 最小系统 |
| 晶振 | CRYSTAL | 11.0592MHz | XTAL1/XTAL2 |
| 电容 | CAP | 30pF | 晶振到地 |
| 复位 | RES | 10k + 10uF | RST |
| LCD | LM016L | 16x2 | P0 数据,P2 控制 |
| 按键 | BUTTON | 3 个 | P1.0-P1.2,另一端地 |
| 蜂鸣器 | BUZZER | 有源 | 三极管驱动 |
放置 AT89C51 后双击设置 Clock Frequency 11.0592MHz;连接晶振和复位;LCD 的 RS/RW/EN 接 P2.0-P2.2,数据线接 P0;P0 加排阻;按键接 P1.0-P1.2,按下接地;蜂鸣器接 P1.3 经 NPN 三极管。LM016L 对比度 VEE 要接电位器或固定电阻,否则只亮不显。
4.2 Keil 输出 HEX 与 Proteus 加载参数
Keil 设置:Project -> Options for Target -> Target 晶振填 11.0592MHz,Output 勾选 Create HEX File。C51 代码中串口初始化如下。
void uart_init(void) { SCON = 0x50; /* 模式 1,8 位 UART,允许接收 */ TMOD &= 0x0F; TMOD |= 0x20; /* T1 模式 2,自动重装 */ TH1 = 0xFD; /* 9600bps @ 11.0592MHz */ TL1 = 0xFD; TR1 = 1; ES = 1; EA = 1; } void uart_send_byte(unsigned char dat) { SBUF = dat; while (TI == 0); TI = 0; }SCON=0x50 把串口设为模式 1,REN 置 1 允许接收;T1 工作在模式 2 自动重装,TH1 和 TL1 都填 0xFD,对应 11.0592MHz 晶振下 9600bps。发送一个字节后等待 TI 置位,再手动清零。参数说明:如果晶振换成 12MHz,9600bps 的 TH1 不是 0xFD,误差会变大;Proteus 里的 Virtual Terminal 波特率也要设 9600,数据位 8,停止位 1,无校验。加载 HEX 时双击 MCU,在 Program File 选择 Keil 生成的 .hex,Clock Frequency 与 Keil 保持一致。
4.3 排队叫号系统仿真故障排查:不显示、乱叫、串口乱码
| 现象 | 常见原因 | 处理 |
|---|---|---|
| LCD 只亮不显示 | 对比度没调,RW 悬空 | VEE 接 1k-2k 到地,RW 接地 |
| 按键一次跳多个号 | 没去抖,按键抖动 | 20ms 定时扫描,连续 3 次确认 |
| 叫号重复或漏号 | q_head/q_tail 更新顺序错 | 先判空,再移动 head,再减 count |
| 串口乱码 | 晶振与波特率不匹配 | 统一 11.0592MHz 和 TH1=0xFD |
| 蜂鸣器常响 | 驱动电平写反 | 查 NPN/PNP,空闲输出关断电平 |
| 程序不跑 | EA 没开,复位脚悬空 | EA 接高,RST 接复位电路 |
注意:Proteus 仿真里 P0 口必须接上拉排阻,否则 LCD 数据口读不到有效高电平;真实 STC单片机部分型号 P0 也需上拉,不要省略。
5. 排队叫号系统的进阶技巧:掉电保存与串口扩展
单窗口排队叫号系统做完基础功能后,课程设计答辩常被问“掉电后号码还在吗”“能不能把队列接到电脑上”。这两个需求用 STC单片机内部 EEPROM 和串口帧协议就能解决,不必加 24C02 也能演示。若要做多窗口,把叫号键和窗口号编码后发到同一串口总线,主控轮询分配。
5.1 用 STC 单片机内部 EEPROM 保存当前号码
#include <stc12c5a60s2.h> /* 以带 IAP 的 STC 型号为例,头文件按实际替换 */ #define IAP_ADDR 0x0000 void eeprom_write_byte(unsigned int addr, unsigned char dat) { ISP_DATA = dat; ISP_ADDRH = (unsigned char)(addr >> 8); ISP_ADDRL = (unsigned char)(addr & 0xFF); ISP_CMD = 0x02; /* 字节写命令 */ ISP_TRIG = 0x46; ISP_TRIG = 0xB9; /* 实际工程中需等待 IAP 完成或关闭中断,按手册处理 */ }把当前号码、等待人数、队列头尾写入 EEPROM,上电时先读回,再恢复显示。写之前要关闭全局中断,写完再打开,避免 IAP 操作被打断。参数说明:不同 STC 型号的 ISP 寄存器和命令字可能不同,以对应头文件为准;写次数有限,不要每叫一个号就写,建议在过号、清零或定时 30 秒后写一次。
5.2 串口回传队列状态给上位机:帧头、长度、校验
| 字节 | 含义 | 示例 |
|---|---|---|
| 0 | 帧头 1 | 0xAA |
| 1 | 帧头 2 | 0x55 |
| 2 | 数据长度 | 0x04 |
| 3 | 命令字 | 0x01 状态 |
| 4 | 当前叫号 | 0x08 |
| 5 | 等待人数 | 0x03 |
| 6 | 异或校验 | 0x?? |
void send_queue_status(unsigned char current, unsigned char waiting) { unsigned char sum; uart_send_byte(0xAA); uart_send_byte(0x55); uart_send_byte(0x04); uart_send_byte(0x01); uart_send_byte(current); uart_send_byte(waiting); sum = 0x04 ^ 0x01 ^ current ^ waiting; uart_send_byte(sum); }上位机收到 0xAA 0x55 后开始取长度,按长度读取负载,最后用异或校验判断数据是否被干扰。当前叫号可用 0 表示无号,等待人数用 q_count。参数说明:串口中断里不要直接调用 LCD 刷新,收到上位机下发的清零、暂停叫号命令后,置标志位交给主循环处理。若做多窗口,把窗口号放进命令字高 4 位,低 4 位表示动作,主控按窗口号维护独立队列。
本文还有配套的精品资源,点击获取