简介:出租车计费计数字电路课程设计文档是一份面向电子信息工程及相关专业学生的完整课设参考,围绕行车里程计费、等候时间计费和起步费三部分,给出总额不超过99.99元的计费器设计方案,内容涵盖设计目的、总体框图、各单元电路详解、整机电路图、心得体会与参考文献等。文档对里程计费电路采用干簧继电器脉冲触发与一百八十进制计数器实现1.80元/km单价,等候计费电路以六百进制计数器配合一百五十进制计数器完成每10分钟1.50元计费,并借助74LS160、74LS273、74LS48等器件构建计数、锁存和显示链路,能帮助读者理解数字电路系统设计与调试的完整流程。资源包仅含1个doc文档,体积1.46MB,结构紧凑,便于直接阅读或对照修改。目前已有325人浏览学习,适合正在完成数字电路课程设计、需要设计思路与电路原理参考的学生使用。
1. 出租车计费计做课程设计,真正要解决的三个问题
先给一个反直觉的结论:出租车计价器里最难的步骤,不是菜单上“几块钱一跳”的算术,而是把车辆行驶的物理里程和等待时间,同时变成两个互不干扰的数字脉冲序列,再送到数码管上刷新。任何计费装置都必须回答三个问题:轮子转动时怎么稳定加价,停车等红灯时怎么按时间加价,乘客上下车触发的按键抖动怎么不加价。数字电路课程设计文档的核心价值,就是把这三个问题拆分到计数器、译码器、分频器和动态扫描这几类基础单元上,而不是直接用单片机固件把它一笔带过。适合读这篇文章的人有两类:一类是正在做课程设计并准备写文档的学生,另一类是评审或复核这类设计、想快速判断边界条件和验证流程是否完整的工程师。
2. 把计费规则换算成脉冲计数的边界条件
2.1 里程计费的本质是脉冲计数,不是模拟电压换算
出租车计费计标定算法的起点,是“一公里产生多少个脉冲”。常见的安装方式是在车轮上固定磁钢,用霍尔传感器或干簧管输出方波。假设轮胎周长为 1.8 米,车轮每转一圈输出 2 个脉冲,那么一公里脉冲数就是:
N_km = 1000 / 1.8 × 2 ≈ 1111这个数并不必须取整。课程设计里更常见的做法是先把传感器拆掉,用信号发生器直接给计数器一个可调频率,再把主机设定为“每 1000 个脉冲跳一次价”,这样整个电路可以用 1 kHz 方波快速验收。真正装到车轮上时,再引入校准参数把 1111 修正掉。
从数字电路的角度看,里程计费不用算任何乘法。显示器每一次跳价,对应的是距离计数器累计到某个固定值。这个固定值就是“每跳单位价”对应的脉冲数。比如 2 元一跳,每跳需要 100 个脉冲,那么每个脉冲代表的价格是 0.02 元。如果把价格设计成“每跳 0.1 元”,则跳价阈值变为 50 个脉冲。这里要注意,仪表显示位数有限,建议先用模拟信号发生器把“每跳 0.1 元”调通,再在文档里写清楚真实计价系数的换算关系。
2.2 起步价、里程价和等待价为什么要走两个独立计数器
起步价在课程设计里通常不是“起步后自动叠加”,而是通过置数端预置到 BCD 计数器中。常见做法是把 8.00 元拆成 800,预置到三位 BCD 加法器的初始值里。里程脉冲到来时,加法器每跳到某个进位阈值就加一次费用。预置操作可以用一个按键控制计数器的置数引脚,而不是在输入脉冲上做减法。
里程和等待必须分开计数。原因很简单:车辆低速蠕行时,里程脉冲可能还在一路断续到来,同时时间计费也仍在累计。如果设计成“里程计数和等待计数共用一个计数器”,计价结果会严重失真。正确结构是里程脉冲计数器与等待时间计数器完全并行,各自独立累计各自的阈值,最终都向同一个 BCD 金额寄存器累加。
学习文档时经常会出现一个误区:把“等待”信号当成里程计数器的使能。比如乘客上车后按下等待键,就把里程计数停掉,只用定时器计时。这个设计在真实计费规则里不完全对,因为车在绿灯起步瞬间也会输出脉冲。稳妥的写法是:
| 计费项目 | 输入信号 | 每跳阈值 | 计数方向 |
|---|---|---|---|
| 起步价 | 空车/重车开关 | 置数预置 | 预置到金额寄存器 |
| 里程价 | 霍尔脉冲 | 按每跳金额换算 | 加法计数 |
| 等待价 | 1 Hz 时基 | 按等待计费规则换算 | 加法计数 |
两个计数器并行工作,显示端通过多路选择器读取金额寄存器,三者之间不存在等待关系。
2.3 分频系数要和最大车速一起验算
如果等待计时用 1 秒时基,时基的来源可以是晶振加 CD4060 分频,也可以用 NE555 做自激多谐振荡器。NE555 的频率公式是:
f ≈ 1.44 / ((R1 + 2×R2) × C)取 R1=10kΩ、R2=68kΩ、C=0.1μF,频率大约是 98 Hz,想得到 1 Hz 还要接一个分频器。晶振方案更可控,32768 Hz 经过 15 级二分频后输出 1 Hz,误差主要来自晶振本身,基本不需要调电容。
但这里有一个容易被熟手忽略的约束:里程脉冲去抖宽度不能只看机械开关,还要按最高车速反推脉冲最小间隔。假设轮胎每转输出 4 个脉冲,最高车速 120 km/h 对应车轮转速约 16.7 rps,脉冲间隔约为 15 ms。如果去抖单稳态把脉宽设成 22 ms,高速状态下每个有效脉冲都会被吞掉。计费计单独跑静态测试没问题,装在车上一跑高速就少计费,问题几乎都出在这里。
| 车速 km/h | 轮速 rps | 4 脉冲/转的最小间隔 ms |
|---|---|---|
| 40 | 5.6 | 45 |
| 80 | 11.1 | 22.5 |
| 120 | 16.7 | 15 |
所以去抖参数不是照抄芯片手册的例程,而是先写出这条“最大车速对应最小脉冲间隔”的约束,再回选 RC 常数。
3. 用 Verilog 搭一个可仿真的计费计数核心
3.1 核心模块的端口与参数设计
用 Verilog 做数字电路课程设计时,我一般会先搭一个纯仿真可用的核心模块,把计费规则参数化,再用 testbench 快速观察波形。参数不写死,是后面写文档时最好解释的部分。
// 出租车计费计核心:里程脉冲 + 等待时间 -> BCD 金额 module taxi_meter_core #( parameter PULSE_PER_JUMP = 100, // 每 100 个里程脉冲跳一次计价单位 parameter WAIT_PER_JUMP = 30, // 等待模式下每 30 个时基跳一次 parameter SCAN_PERIOD = 500 // 显示扫描计数,决定动态刷新频率 )( input wire clk, input wire rst_n, input wire wait_key, // 等待/缓行档位,高电平有效 input wire dist_pulse, // 整形滤波后的里程脉冲 output wire [3:0] bit_sel, // 数码管位选 output wire [6:0] seg // 七段码输出 ); // 上升沿检测:保证一个脉冲只触发一次计数 reg pulse_d; always @(posedge clk or negedge rst_n) begin if (!rst_n) pulse_d <= 1'b0; else pulse_d <= dist_pulse; end wire pulse_rise = dist_pulse && !pulse_d; reg [9:0] dist_cnt; reg [4:0] wait_cnt; reg [15:0] fare_bcd; // BCD 金额:高 8 位存角/元,低 8 位存储分位 reg [9:0] scan_cnt; reg [1:0] scan_pos; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin dist_cnt <= 0; wait_cnt <= 0; fare_bcd <= 16'h0800; // 起步价预置 8.00 end else begin if (pulse_rise) begin dist_cnt <= dist_cnt + 1; if (dist_cnt == PULSE_PER_JUMP - 1) begin dist_cnt <= 0; // 金额低位 BCD 加 1,满 9 进位到高位 if (fare_bcd[3:0] < 4'h9) fare_bcd[3:0] <= fare_bcd[3:0] + 1; else begin fare_bcd[3:0] <= 0; fare_bcd[7:4] <= fare_bcd[7:4] + 1; end end end if (wait_key) begin wait_cnt <= wait_cnt + 1; if (wait_cnt == WAIT_PER_JUMP - 1) begin wait_cnt <= 0; // 等待计费的加法逻辑与里程相同 // 完整设计中应封装成进位函数,避免重复写 end end end end模块里的 PULSE_PER_JUMP 是计费规则中最关键的可调参数。仿真时把它改成 4 或 10,用少量脉冲就能观察到跳价行为;实际装车时改成按轮胎周长计算出的真实脉冲数。等待计费的 WAIT_PER_JUMP 是“多少个秒脉冲跳一次”,它不直接等于等待秒数,而是和时基频率联动。如果时基不是 1 Hz,而是 100 Hz,那么这个参数要相应放大。
3.2 BCD 进位和七段译码不要放在同一个进程里
BCD 金额寄存器适合用单独的 always 块维护,七段译码用组合逻辑实现。很多人喜欢把金额相加和显示扫描写在一个进程里,结果仿真时发现进位和消隐互相干扰。实际做法是拆成三块:一是计数与金额累加,二是动态扫描位选,三是七段译码。
// 动态扫描:每 SCAN_PERIOD 个时钟切换一次显示位 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin scan_cnt <= 0; scan_pos <= 0; end else begin scan_cnt <= scan_cnt + 1; if (scan_cnt == SCAN_PERIOD - 1) begin scan_cnt <= 0; scan_pos <= scan_pos + 1; end end end reg [3:0] cur_digit; always @(*) begin case (scan_pos) 2'd0: cur_digit = fare_bcd[3:0]; 2'd1: cur_digit = fare_bcd[7:4]; 2'd2: cur_digit = fare_bcd[11:8]; default: cur_digit = 4'hF; // 最高位暂时熄灭 endcase end位选信号 bit_sel 接的是 74HC138 一类译码器,或者直接接三极管的基极。显示频率要避开人眼闪烁频率,但也别太高,否则三极管开关损耗和电源纹波会变大。扫描周期取 1 kHz 左右比较合适,也就是每个位每秒刷新 250 次左右。参数 SCAN_PERIOD 要按主时钟频率换算,比如主时钟 50 MHz 时,SCAN_PERIOD 取 50000 才能得到 1 kHz 扫描。
七段译码表推荐直接用 case 写,不要用 if-else 串。以共阴极数码管为例,段码 a 到 g 的顺序从 bit0 到 bit6,数字 0 到 9 的常用段码依次是:0=0x3F,1=0x06,2=0x5B,3=0x4F,4=0x66,5=0x6D,6=0x7D,7=0x07,8=0x7F,9=0x6F。如果电路里用的是共阳数码管,取反即可。组合逻辑里不要出现锁存器,case 语句一定要写 default,否则综合工具会给你补一个不想要的 latch。
3.3 用最小 testbench 验证跳价阈值
写 testbench 时,不一定要把真实速度模型仿真出来。课程设计文档里最实用的验证方法是把 PULSE_PER_JUMP 覆写成一个很小的值,比如 4,然后手动产生 4 个脉冲,观察金额是否正好增加一次。
module tb_taxi_meter_core; reg clk = 1'b0; reg rst_n = 1'b0; reg wait_key = 1'b0; reg dist_pulse = 1'b0; wire [3:0] bit_sel; wire [6:0] seg; taxi_meter_core #( .PULSE_PER_JUMP(4), .WAIT_PER_JUMP(3) ) dut ( .clk(clk), .rst_n(rst_n), .wait_key(wait_key), .dist_pulse(dist_pulse), .bit_sel(bit_sel), .seg(seg) ); always #10 clk = ~clk; // 20ns 周期,典型 50MHz 时钟 initial begin #40 rst_n = 1'b1; // 产生连续 20 个里程脉冲,每个脉冲宽度 2 个时钟周期 repeat (20) begin @(posedge clk); dist_pulse = 1'b1; @(posedge clk); @(posedge clk); dist_pulse = 1'b0; @(posedge clk); end // 拉高等待档位,观察等待计数是否按阈值跳价 wait_key = 1'b1; #2000; wait_key = 1'b0; #1000; $finish; end endmodule仿真时要在波形窗口里同时观察 dist_cnt、wait_cnt、fare_bcd 三个信号。里程脉冲传入后,dist_cnt 应逐周期递增;达到阈值时,fare_bcd 的低四位加 1 并回零。如果金额一次跳了两位数,说明 BCD 进位不完整。还有一种常见错误是 dist_pulse 持续为高电平时,同一个脉冲被反复计数,这就要回到上升沿检测信号 pulse_rise 上检查。
4. 从仿真落到 TTL 芯片的拼搭与排错
4.1 典型芯片选型与接线要点
如果课程设计要求用 74 系列 TTL 或 4000 系列 CMOS 芯片在面包板上搭,最常用的一组器件是:CD4060 做晶振分频,CD4510 做 BCD 十进制加减计数器,CD4511 做 BCD 到七段锁存译码,74HC138 做位选扫描。需要说明的是,CD4510 是加法计数,出租车的起步价预置可以用它的置数端完成,不用额外设计减法器。
| 模块 | 推荐器件 | 接线要点 |
|---|---|---|
| 秒时基 | CD4060 + 32768Hz 晶振 | 晶振接 OSC_IN,分频输出接到计数时钟 |
| 里程去抖整形 | 74HC14 施密特反相器 | 输入先过 RC 低通,再进施密特反相器 |
| 等待计数 | CD4510 或 CD4020 | 秒脉冲接时钟,溢出进位作为跳价标志 |
| BCD 译码 | CD4511 | 段输出接限流电阻到数码管,注意 LT、BL、LE 引脚 |
| 位选驱动 | 74HC138 + PNP 三极管 | 138 的 Y 输出控制三极管基极,再接到公共端 |
CD4511 的 LE 端要接低电平,让它随时刷新;LT 端接高平,避免测试模式把待显示内容拉灭。前导零的消隐可以靠控制位选来实现,而不是在 CD4511 上做复杂逻辑,因为 CD4511 的 RBI 和 RBO 只在多片级联时才需要仔细处理。
4.2 去抖参数按轮速反向设置
机械开关和霍尔传感器输出的波形差别很大。干簧管在磁钢靠近时会有 10 ms 量级的机械抖动,直接接计数器会出现一次闭合算好几次的问题。常见做法是先做 RC 低通,再接施密特触发器整形。RC 时间常数选 1 ms 左右,既能滤掉细窄毛刺,又不会严重拖慢最高车速时的脉冲。
不要看到芯片手册的单稳态电路就照抄。单稳态宽度公式是 T=1.1RC,比如 R=20kΩ、C=1μF 时 T=22ms,这个宽度在静态测试中看起来很完美,但代入 120 km/h 的脉冲间隔 15ms 后,会发现每个脉冲还没结束就被单稳态复位,计数器直接丢脉冲。比较实用的计算路径是:先确定传感器每转脉冲数,再算出最高车速对应的最短间隔,最后把单稳态宽度设成最短间隔的三分之一以内。课程设计文档里能写出这一步推导,比贴再多样例都有说服力。
4.3 面包板走线和电源旁路的常见陷阱
多个计数芯片共用时钟时,连接线要尽量短,且每两个芯片之间避免跨过太长并排的电源线。TTL 芯片的扇出能力有限,一个 74HC 系列反相器可以直接驱动同系列计数器的时钟端,但要驱动四个 CD4511 就不行,需要通过缓冲器或三极管扩流。电源端的去耦电容每片芯片都加 0.1μF,靠近电源引脚放置;如果面板上还有数码管动态扫描,总线上会有较大纹波,建议再加一个 100μF 电解电容。
排错顺序也有讲究。先断开数码管,用示波器看计数时钟是否有上升沿;再用手动按键逐个送入脉冲,确认 CD4510 的 Q 输出按 BCD 码变化;最后再接 CD4511。不要把示波器探头直接夹在晶振输出端来验证分频结果,探头电容会改变振荡频率。正确做法是量 CD4060 的 Q14 引脚,看到稳定的方波后再向下游查。
5. 标定、回环测试和一张能签字的验收表
5.1 转圈法和示波器测速结合
实际装轮标定时,人工数脉冲是最可靠的参照。把车轮悬空,在轮毂上一个固定位置贴反光标记,每转一圈都间隔性地确认。转动 50 圈后,用示波器数出传感器输出的脉冲总数,再除以圈数得到每转脉冲数。这个数乘以轮胎周长,才是计费计真正使用的“每公里脉冲数”。只按霍尔手册标的“每转两个脉冲”直接写参数,会因为磁钢距离和安装偏心产生明显误差。
示波器测量时用上升沿触发,把时基调到能看到相邻两个脉冲间隔即可。记录脉冲间隔后,用 1 除以间隔得到当前轮速,再根据轮胎周长换算成车速。这一项数据同时用来校验去抖宽度是否合理,也是验收表里的关键原始记录。
5.2 用信号发生器做回环测试
回环测试是把里程脉冲改成信号发生器的方波输出,频率从 1 Hz 到 1 kHz 连续可调。信号发生器输出阻抗通常为 50Ω,接到 TTL 电路时要先串一个 1kΩ 电阻限流,避免负电平损坏 CMOS 输入。频率设成 100 Hz,持续发送 100 秒,总计 10000 个脉冲。如果计费计设定的每跳阈值为 100,最终显示金额应增加 100 个计价单位,偏差不超过 1。
这个测试不能用“看一眼跳动正常”来验收,一定要记录开始和结束金额。等待计费部分用同样方法,把秒时基接到计数器,持续运行 5 分钟,对比最终跳动次数和理论值。回环测试把传感器、机械安装、计费逻辑三者分开,定位问题时会很省时间。
5.3 验收表至少要有四列原始数据
课程设计文档最后附一张表,比一大段文字描述更有用。表里必须包含四列:测试动作、输入脉冲数或等待秒数、显示期望值、实测值。遇到偏差时再加一列“误差原因”,不要直接在原数据上修改。
| 序号 | 测试动作 | 输入条件 | 期望显示 | 实测显示 |
|---|---|---|---|---|
| 1 | 上电复位 | 置数端动作 | 8.00 | 8.03 |
| 2 | 里程 100 脉冲 | PULSE_PER_JUMP=100 | 8.01 | 8.01 |
| 3 | 等待 30 秒 | WAIT_PER_JUMP=30 | 8.02 | 8.02 |
| 4 | 连续 10000 脉冲 | 1 kHz 方波 | 9.00 | 9.01 |
填表时注意一个额外参数:晶振实际频率并不等于标称频率,用示波器数出每秒脉冲后回填到分频系数,表里就会多出一列“频率修正量”。把修正量和显示器实测值放在一起,课程设计的验收才算真正覆盖了数字电路里的时序问题。
本文还有配套的精品资源,点击获取