资讯动态

基于74芯片的1-9层电梯控制器:从仿真到FPGA改造

发布时间:2026/10/26 6:51:28 来源:尧图企业网站定制
简介这份《高楼电梯自动控制系统》课程设计资料面向数字逻辑与计算机相关专业学生及电子设计初学者围绕1-9层电梯的自动控制展开解决楼层比较、电机正反转与状态显示等典型设计问题。资源包内含1个doc文档约719KB以课程设计报告形式呈现涵盖设计任务、主要器件选型、模块划分与实验总结便于直接参考或二次整理。资料以74LS85数值比较器、74LS192可逆计数器、七段译码显示系统及十进制至二进制编码器为核心完整梳理了输入编码、数值比较、可逆计数与方向指示等模块的实现思路并附有引脚功能与真值表说明。目前已有1304人学习下载适合需要完成同类课设、巩固组合与时序逻辑设计方法、或借助EDA工具进行仿真与硬件测试的读者参考借鉴。1. 从一堆 74 芯片开始这个 1-9 层电梯控制器到底能跑出什么效果如果你手头正好有一份《数字逻辑》课程设计的资料包里面躺着 74LS85、74LS192、74LS48 这几片芯片的引脚图和真值表却不知道怎么把它们串成一个能演示的电梯控制系统那这份资源就是冲着你来的。它实现的是一套 1-9 层高楼电梯自动控制逻辑乘客用开关手动输入目标楼层 A系统实时显示电梯当前楼层 B然后自动判断 A 和 B 的大小关系——A 大于 B 就输出正转时序让电梯上升A 小于 B 就输出反转时序让电梯下降A 等于 B 就停机开门。整套逻辑不依赖单片机纯靠组合逻辑加时序逻辑搭出来非常适合拿来理解数值比较器、可逆计数器和七段译码显示是怎么协同工作的。下面我就按“先看懂结构、再跑通仿真、最后动手改”的顺序把这份资料拆一遍。2. 系统架构拆解输入编码、数值比较、可逆计数三条链路怎么咬合2.1 三个模块的职责边界这份设计最值得先看清楚的地方是它没有一上来就画一张大图而是把系统切成了三个职责清晰的模块。第一个是输入编码模块负责把乘客拨动的楼层选择开关转换成十进制数字再送到七段译码显示系统上直观呈现。第二个是数值比较模块核心是一片 74LS85把目标楼层 A 和当前楼层 B 做四位二进制比较输出三种状态信号。第三个是可逆计数模块用 74LS192 实现楼层数的递增和递减同时把当前楼层值反馈给比较器。这三个模块之间的信号流向是单向闭环的输入编码模块产生 A 值可逆计数模块产生 B 值两者同时进入比较器比较器输出的升降停信号又反过来控制计数器的计数方向。换句话说比较器是大脑计数器是执行机构编码显示是人机接口。很多同学第一次做这个题的时候会把比较器和计数器直接硬连忽略了显示译码的独立供电和限流电阻结果数码管要么不亮要么烧段这是后话后面避坑章节会细说。2.2 数值比较器 74LS85 的级联处理74LS85 是四位数值比较器比较原理是从最高位 A3 和 B3 开始逐位往下比如果最高位就能分出大小后面的位就不再影响结果。资料里特别强调了一个容易被忽略的点当只比较四位数而不做级联扩展时低位比较结果输入端 IAB、IAB 必须接 0IAB 必须接 1。这个处理如果漏掉比较器输出会处于不确定状态电梯逻辑就会乱跳。// 74LS85 四位比较器行为级描述用于仿真验证 module comparator_74LS85( input [3:0] A, // 目标楼层 A来自输入编码模块 input [3:0] B, // 当前楼层 B来自可逆计数器 input IA_GT, // 低位比较结果AB单片段接 0 input IA_LT, // 低位比较结果AB单片段接 0 input IA_EQ, // 低位比较结果AB单片段接 1 output reg A_GT_B, // AB 输出对应电梯上升 output reg A_LT_B, // AB 输出对应电梯下降 output reg A_EQ_B // AB 输出对应停机开门 ); always (*) begin if (A B) begin A_GT_B 1; A_LT_B 0; A_EQ_B 0; end else if (A B) begin A_GT_B 0; A_LT_B 1; A_EQ_B 0; end else begin // 相等时还要看低位级联输入 A_GT_B IA_GT; A_LT_B IA_LT; A_EQ_B IA_EQ; end end endmodule这段代码里 A 和 B 都是四位宽对应 1-9 层只需要用到 0 到 9 的二进制范围四位刚好够。IA_GT、IA_LT、IA_EQ 这三个输入在单片段使用时按资料要求固定接 0、0、1仿真时如果忘了这个约束A 等于 B 的情况下输出会直接跟随这三个引脚而不是稳定输出 A_EQ_B 为高。实际搭电路时这三个脚要分别通过下拉电阻接地和上拉电阻接 VCC不能悬空。2.3 可逆计数器 74LS192 的升降控制74LS192 是十进制可逆计数器资料里给出的真值表把它的工作模式讲得很清楚MR 高电平异步清零PL 低电平异步预置CPU 上升沿加计数CPD 上升沿减计数。在电梯系统里比较器输出的上升信号接到 CPU下降信号接到 CPD停机信号则用来封锁时钟或者触发开门指示。// 74LS192 可逆计数器简化模型 module counter_74LS192( input CLK_UP, // 加计数时钟接比较器 AB 输出 input CLK_DOWN, // 减计数时钟接比较器 AB 输出 input MR, // 异步复位高有效 input PL, // 异步预置低有效 input [3:0] DIN, // 预置楼层数 output reg [3:0] Q, // 当前楼层 B output TCU, // 进位输出到 9 层时有效 output TCD // 借位输出到 0 层时有效 ); always (posedge CLK_UP or posedge CLK_DOWN or posedge MR) begin if (MR) Q 4b0000; // 复位到 0 层 else if (CLK_UP) Q (Q 4d9) ? 4d9 : Q 1; // 上限锁死 9 层 else if (CLK_DOWN) Q (Q 4d0) ? 4d0 : Q - 1; // 下限锁死 0 层 end assign TCU (Q 4d9); assign TCD (Q 4d0); endmodule这里我加了上下限锁死逻辑因为实际电梯不可能跑到 9 层以上或者 0 层以下。资料里没有明确写这个保护但如果你不加计数器会在 9 和 0 之间循环翻转电梯逻辑就变成永动机了。CLK_UP 和 CLK_DOWN 不能同时有效否则计数器行为不确定所以比较器的三个输出最好经过一个优先编码或者互锁电路再接到计数器。2.4 七段译码显示链路显示部分用的是 74LS48 加共阴极数码管 BS201A。74LS48 是七段译码驱动器输入四位 BCD 码输出七段驱动信号。资料里提到楼层选择开关的高低位直接接到七段显示系统这里要注意 74LS48 的输出是高电平有效配共阴极数码管刚好匹配。如果你手头只有共阳极数码管那就得换 74LS47 或者加反相器否则显示出来是反的。// 74LS48 七段译码器行为描述共阴极 module decoder_74LS48( input [3:0] BCD, // 来自输入编码或计数器输出 output reg [6:0] SEG // a~g 段高电平点亮 ); always (*) begin case (BCD) 4d0: SEG 7b1111110; 4d1: SEG 7b0110000; 4d2: SEG 7b1101101; 4d3: SEG 7b1111001; 4d4: SEG 7b0110011; 4d5: SEG 7b1011011; 4d6: SEG 7b1011111; 4d7: SEG 7b1110000; 4d8: SEG 7b1111111; 4d9: SEG 7b1111011; default: SEG 7b0000000; endcase end endmodule这段译码逻辑和 74LS48 的真值表一致仿真时可以直接替换实际芯片做功能验证。实际搭电路时每个段要串一个限流电阻阻值一般在 220 欧到 470 欧之间具体看数码管的额定电流。资料里没有写电阻值但这是硬件调试必踩的坑后面会展开。3. 从零跑通仿真EDA 工具里的设计输入、编译与波形验证3.1 建立工程与文件组织不管你用的是哪款 EDA 工具第一步都是建一个干净的工程目录。我一般会按功能把文件分成三个子目录src 放 Verilog 或原理图源文件sim 放测试平台doc 放引脚分配和真值表截图。这样后面改逻辑的时候不会把仿真文件误编译进综合流程。# 工程目录结构示例 elevator_ctrl/ ├── src/ │ ├── comparator_74LS85.v │ ├── counter_74LS192.v │ ├── decoder_74LS48.v │ └── top_elevator.v ├── sim/ │ └── tb_elevator.v └── doc/ └── pin_assignment.txt顶层模块 top_elevator.v 负责把三个子模块例化并连线。比较器的 A 输入接编码开关B 输入接计数器输出比较器的三个输出分别接计数器的 CLK_UP、CLK_DOWN 和停机指示。译码器则分别接 A 值和 B 值驱动两个数码管。3.2 测试平台怎么写才能覆盖边界测试平台不能只跑一个 A5、B3 就完事要把 A 大于 B、A 小于 B、A 等于 B、A 等于 9、B 等于 0 这些边界都覆盖到。下面这个测试平台用任务封装了单次比较方便你改参数重复调用。timescale 1ns/1ps module tb_elevator; reg [3:0] A, B; reg IA_GT, IA_LT, IA_EQ; wire A_GT_B, A_LT_B, A_EQ_B; comparator_74LS85 uut( .A(A), .B(B), .IA_GT(IA_GT), .IA_LT(IA_LT), .IA_EQ(IA_EQ), .A_GT_B(A_GT_B), .A_LT_B(A_LT_B), .A_EQ_B(A_EQ_B) ); task check; input [3:0] ta, tb; begin A ta; B tb; #10; $display(A%d B%d - GT%b LT%b EQ%b, A, B, A_GT_B, A_LT_B, A_EQ_B); end endtask initial begin IA_GT 0; IA_LT 0; IA_EQ 1; // 单片段固定接法 check(5, 3); // 上升 check(2, 7); // 下降 check(4, 4); // 相等停机 check(9, 1); // 上限附近 check(1, 9); // 下限附近 $finish; end endmodule跑完仿真后看波形重点确认 A_EQ_B 在 A 等于 B 时是否为高以及 A_GT_B 和 A_LT_B 是否互斥。如果发现 A 等于 B 时三个输出都不对八成是 IA_EQ 没接高回去检查测试平台里的初始赋值。3.3 引脚分配与硬件下载仿真通过之后下一步是引脚分配。这一步要把顶层模块的输入输出端口映射到实际芯片的管脚上。资料里没有给出具体的引脚号因为不同实验箱的布局不一样。我一般会先翻实验箱的说明书找到数码管段选、位选、拨码开关和 LED 灯的对应管脚然后在 EDA 工具的引脚约束文件里逐条写进去。# 引脚约束示例具体管脚号以实验箱为准 set_location_assignment PIN_23 -to A[0] set_location_assignment PIN_24 -to A[1] set_location_assignment PIN_25 -to A[2] set_location_assignment PIN_26 -to A[3] set_location_assignment PIN_32 -to B[0] set_location_assignment PIN_33 -to B[1] set_location_assignment PIN_34 -to B[2] set_location_assignment PIN_35 -to B[3] set_location_assignment PIN_40 -to SEG_A[6:0]下载之前务必确认电平标准实验箱上的数码管如果是共阴极74LS48 输出高电平点亮直接连就行如果是共阳极中间要加反相器或者改用 74LS47。这一步搞错下载后数码管要么全亮要么全灭很容易误判成逻辑错误。4. 避坑与排查调试 74 系列芯片时最容易翻车的五个点4.1 数码管不亮或者显示乱码现象是下载后数码管完全不亮或者显示的数字缺段、多段。原因通常是限流电阻没加或者阻值太小导致段电流过大烧了数码管也可能是 74LS48 和数码管极性不匹配。解决办法是每个段串一个 330 欧左右的电阻先用万用表测数码管好坏再确认共阴共阳类型。如果显示乱码检查 BCD 输入线有没有接反高位低位是不是颠倒了。4.2 比较器输出一直为高或一直为低现象是 A_GT_B、A_LT_B、A_EQ_B 三个输出里总有一个恒为高不随 A、B 变化。原因多半是 IA_GT、IA_LT、IA_EQ 三个级联输入悬空了。74LS85 的这三个脚不能悬空单片段使用时必须 IA_GT 接 0、IA_LT 接 0、IA_EQ 接 1。解决办法是在 PCB 或面包板上给这三个脚分别加下拉和上拉电阻确保电平稳定。4.3 计数器不计数或者计数方向反了现象是给时钟信号后计数器不动或者该加的时候减了。原因是 CPU 和 CPD 接反了或者时钟信号没有经过施密特触发器整形边沿太缓导致芯片识别不到。解决办法是对调 CPU 和 CPD 的接线然后在时钟源和计数器之间加一个 74LS14 施密特触发器做整形。另外注意 74LS192 的 MR 和 PL 不能同时有效否则芯片进入不确定状态。4.4 电梯到层不停或者冲过目标楼层现象是计数器到达目标楼层后还在继续计数电梯逻辑停不下来。原因是比较器的 A_EQ_B 输出没有正确反馈到计数器的时钟使能端或者反馈路径上有多余的毛刺。解决办法是在比较器输出和计数器时钟之间加一个 D 触发器做同步用系统时钟采样 A_EQ_B 信号消掉组合逻辑的毛刺。这个坑我在第一次搭电路时踩过波形上看 A_EQ_B 有窄脉冲计数器会多计一个数。4.5 复位后楼层显示不是 0现象是按复位键后数码管显示的不是 0 而是其他数字。原因是 74LS192 的 MR 只复位计数器本身但译码器或者输入编码模块没有同步复位。解决办法是把 MR 信号同时接到输入编码模块的复位端或者用一个全局复位信号统一控制所有时序单元。如果用的是拨码开关输入 A 值复位后还要手动把开关拨回 0否则 A 值会保持复位前的状态。5. 二次开发与改造把这套逻辑变成可扩展的电梯控制器5.1 从 1-9 层扩展到 1-16 层当前设计用四位比较器和十进制计数器楼层范围卡在 0 到 9。如果你想扩展到 16 层最直接的办法是把 74LS85 级联两片低四位的 IA_GT、IA_LT、IA_EQ 接到高四位的对应输入高四位的输出就是最终比较结果。计数器换成 74LS193 四位二进制可逆计数器译码器换成 74LS47 或者直接用 FPGA 内部的 LUT 实现七段译码。这样改动量不大但楼层显示要从一位数码管变成两位需要多一路位选控制。// 16 层比较器级联示例 module comparator_16floor( input [7:0] A, B, output A_GT_B, A_LT_B, A_EQ_B ); wire gt_low, lt_low, eq_low; // 低四位比较级联输入固定 0,0,1 comparator_74LS85 low( .A(A[3:0]), .B(B[3:0]), .IA_GT(1b0), .IA_LT(1b0), .IA_EQ(1b1), .A_GT_B(gt_low), .A_LT_B(lt_low), .A_EQ_B(eq_low) ); // 高四位比较级联输入接低四位结果 comparator_74LS85 high( .A(A[7:4]), .B(B[7:4]), .IA_GT(gt_low), .IA_LT(lt_low), .IA_EQ(eq_low), .A_GT_B(A_GT_B), .A_LT_B(A_LT_B), .A_EQ_B(A_EQ_B) ); endmodule级联的关键是低位的比较结果要正确接到高位的级联输入顺序不能反。如果接反了高四位相等时低位的结果会被忽略比较逻辑就错了。5.2 加入数据寄存和多人请求排队资料总结里提到这个设计没有数据寄存系统本质上是一人电梯。要改成多人电梯需要加一个请求队列。最简单的做法是用一片 74LS373 八 D 锁存器存住每个楼层的请求信号然后用优先编码器 74LS148 选出最高优先级的请求楼层再送到比较器。这样电梯就能记住多个乘客的目标楼层按顺序逐个停靠。// 请求队列简化模型 module request_queue( input clk, input [8:0] floor_req, // 9 个楼层的请求按钮 output reg [3:0] next_floor, output reg has_request ); reg [8:0] pending; always (posedge clk) begin pending pending | floor_req; // 锁存请求 if (pending 9b0) begin has_request 0; next_floor 4d0; end else begin has_request 1; // 简单优先从低层到高层扫描 if (pending[0]) next_floor 4d1; else if (pending[1]) next_floor 4d2; // ... 依次类推 end end endmodule这个队列模型只是示意实际做的时候还要考虑电梯运行方向上的顺路停靠不能简单地按楼层高低排队。我一般会用一个状态机来管理上行和下行两个方向的请求上行时只响应比当前楼层高的请求下行时只响应比当前楼层低的请求全部响应完再换向。5.3 用 FPGA 替代 74 芯片的改造路径如果你手头有 FPGA 开发板完全可以把这套 74 芯片逻辑全部搬到 FPGA 内部用 Verilog 重新实现。好处是引脚数量不受限可以轻松扩展到 16 层甚至 32 层还能加数码管动态扫描、按键消抖、蜂鸣器到站提示这些外围功能。改造的时候把前面写的 comparator_74LS85、counter_74LS192、decoder_74LS48 三个模块直接例化到顶层把物理引脚约束改成 FPGA 的 IO 约束就行。// FPGA 顶层例化示例 module top_fpga_elevator( input clk_50m, // 50MHz 板载时钟 input [3:0] floor_sel, // 拨码开关输入目标楼层 input reset_n, // 复位按键低有效 output [6:0] seg_a, // 目标楼层数码管 output [6:0] seg_b, // 当前楼层数码管 output [2:0] lamp // 上升、下降、停机指示灯 ); wire [3:0] A, B; wire A_GT_B, A_LT_B, A_EQ_B; wire clk_up, clk_down; // 按键消抖和时钟分频省略直接例化核心模块 comparator_74LS85 cmp( .A(A), .B(B), .IA_GT(1b0), .IA_LT(1b0), .IA_EQ(1b1), .A_GT_B(A_GT_B), .A_LT_B(A_LT_B), .A_EQ_B(A_EQ_B) ); counter_74LS192 cnt( .CLK_UP(clk_up), .CLK_DOWN(clk_down), .MR(~reset_n), .PL(1b1), .DIN(4d0), .Q(B), .TCU(), .TCD() ); decoder_74LS48 dec_a(.BCD(A), .SEG(seg_a)); decoder_74LS48 dec_b(.BCD(B), .SEG(seg_b)); assign lamp {A_GT_B, A_LT_B, A_EQ_B}; assign clk_up A_GT_B clk_50m; assign clk_down A_LT_B clk_50m; assign A floor_sel; endmodule这段代码里 clk_up 和 clk_down 直接用 50MHz 时钟和比较结果相与实际跑起来计数器会飞掉因为 50MHz 太快了。我一般会加一个分频器把时钟降到 1Hz 左右或者用按键手动产生单步脉冲。这个细节在 FPGA 改造时特别重要血泪经验就是第一次跑的时候没加分频数码管数字跳得根本看不清。从那以后我每次做这种逻辑迁移都强制先把时钟分频和复位电路单独验证一遍再接核心逻辑。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑