1.所选题目:出租车计费器
2.设计要求:设计一个出租车计费器,能按路程计费,具体要求如下:
(1)实现计费功能,计费
为:按行驶里程计费,起步价为7.00元,并在汽车行驶2km后按1.2元/km计费,当里程数达到15km后,没千米加收50%的空驶费,车辆停止和暂停时不计费。
(2)现场模拟汽车的启动、停止、暂停和换挡等状态。
(3)设计数码管显示电路,将车费和路程显示出来,各有1位小数。
3.设计原理:设计该出租车有启动键、停止键、暂停键和档位键。启动键为脉冲触发信号,当其为一个脉冲时,表示汽车已启动,并根据车速的选择和基本车速发出相应频率的脉冲(计费脉冲)以此来实现车费和路程的计数,同时车费显示起步价;当停止键为高电平时,表示汽车熄火,同时停止发出脉冲,此时车费和路程计数清零;当暂停键为高电平时,表示汽车暂停并停止发出脉冲,此时车费和路程计数暂停;档位键用于改变车速,不同的档位对应着不同的车速,同时路程计数的速度也不同。
4.模块设计:出租车计费器可分为两大模块,即控制模块和译码显示模块。系统框图如下:
5.电路符号:出租车计费器的输入信号有:计费时钟脉冲clk;汽车启动键start;汽车停止键stop;档位speedup。输出信号:7段显示控制信号seg7;小数点dp。
6.具体设计流程:
(1) 根据出租车计费原理,将出租车计费部分由5个计数器来完成分别为counterA,counterB,counterC,counterD,counterE。①计数器A完成车费百位。②计数器B完成车费十位和个位。③计数器C完成车费角和分(显示时只显示角)。④计数器D完成计数到20(完成车费的起步价)。⑤计数器E完成模拟实现车行驶100 m的功能。
(2) 当超出起步价时就自动在起步价的基础上每增加一个100m脉冲就增加相应的费用,而当总里程达到或超过一定的数值时,能按新的收费标准进行收费。
(3)译码/动态扫描电路模块将路程与费用的数值译码后用动态扫描的方式驱动6只数码管,即所连接的数码管共用一个数据端,由片选信号依次选择输出,轮流显示。
(4)数码管显示将千米数和计费金额均用3位LED数码管显示(2位整数,1位小数)。
7.具体模块设计:
7.1车速控制模块
当启停键为启动状态(高电平时),模块根据车速选择和基本车速发出响应频率的脉冲驱动计费器和里程显示模块进行计数;当处于暂停状态,暂停发出脉冲,此时里程计数模块和计费模块相应地停止计数。当处于停止状态时,停止发出脉冲,此时计费器和里程显示模块数清零。如图所示。
程序代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY SPEED IS
PORT(
CLK,RESET,START,STOP: IN STD_LOGIC;
SPEEDUP : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
CLKOUT : OUT STD_LOGIC
);
END SPEED;
ARCHITECTURE A OF SPEED IS
SIGNAL COUNT1 :STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL TEMPCLK,CLKS:STD_LOGIC;
SIGNAL KINSIDE :STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
KINSIDE<="00000"-SPEEDUP;
CLKS_LABEL:
PROCESS(RESET,CLK)
VARIABLE COUNT2: STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
IF STOP='1' THEN TEMPCLK <='0';
ELSIF RESET = '1' and stop='0' THEN
COUNT2:="00000";
ELSIF CLK'EVENT AND CLK='1' AND STOP='0' THEN
IF START='1' THEN
IF COUNT2=KINSIDE THEN COUNT2:="00000";
END IF;
IF NOT (SPEEDUP="00000") THEN COUNT2:= COUNT2+1;
END IF;
IF COUNT2="00001" THEN TEMPCLK <= NOT TEMPCLK;
END IF;
END IF;
END IF;
END PROCESS CLKS_LABEL;
CLKOUT <= TEMPCLK;
END A;
仿真结果:
启动后(包括暂停)
复位后
停止后
7.2里程计数模块
由车速控制模块发出的脉冲作为计数脉冲,行驶里程大于3KM时,本模块中信号变为1,并将计数动态显示出来,每来一个脉冲,里程值加0.1(每收到一个脉冲代表运行了0.1公里)。程序中要将计数值从十六进制转换成十进制,即在十六进制的数上加7或6,同时产生了相应的进位信号。如图所示。
程序代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY jicheng IS
PORT (CLK,RESET,STOP: IN STD_LOGIC;
COUNT1:OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
COUNT2:OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
COUNT3:OUT STD_LOGIC_VECTOR (3 DOWNTO 0));
END jicheng;
ARCHITECTURE AA OF jicheng IS
BEGIN
PROCESS(CLK,RESET,STOP)
VARIABLE MM: STD_LOGIC_VECTOR (11 DOWNTO 0);
BEGIN
IF RESET ='1' THEN
MM:="000000000000";
ELSIF CLK='0' AND STOP='1' THEN MM:="000000000000";
ELSIF CLK'EVENT AND CLK='1' AND STOP='0' THEN
IF MM(3 DOWNTO 0)="1001" THEN
MM:=MM+7; ELSE MM:=MM+1; END IF;
IF MM(7 DOWNTO 4)="1010" THEN
MM:=MM+"01100000"; END IF;
END IF;
COUNT1 <=MM(3 DOWNTO 0);
COUNT2 <=MM(7 DOWNTO 4);
COUNT3 <=MM(11 DOWNTO 8);
END PROCESS;
END AA;
仿真结果:
开始计程
个位开始计数
十位开始计数
停止后
7.3计费模块
计费模块启动reset信号,根据输入的clk信号变化,调节费用的计数,用c1、c2、c3显示费用。其初值为6,当里程数超过2km后,才接受计数车速控制模块发出的脉冲的驱动,并且将计数显示动态显示出来,每一个脉冲其数值加0.12,当里程超过15km时数值加0.18。当启动键为启动状态(高电平时),模块根据车速选择和基本车速发出响应频率的脉冲驱动计费器和里程显示模块进行计数;当处于停止状态时,暂停发出脉冲,此时计费器和里程显示模块相应的停止计数,全部归零。如图所示。
程序代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY jifei IS
PORT(CLK,RESET,stop:IN STD_LOGIC;
JUDGE2:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
JUDGE3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
COUNT1:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COUNT2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COUNT3:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COUNT4:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END jifei;
ARCHITECTURE AA OF jifei IS
SIGNAL EN :STD_LOGIC;
SIGNAL MONEY :STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL MCOUNT :STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
MONEY<="00011000" WHEN ((MCOUNT(15)='1') OR (MCOUNT(14)='1') OR (MCOUNT(13)='1')) ELSE "00010010";
EN<='0' WHEN JUDGE3="0000" AND JUDGE2(3 DOWNTO 1)="000" ELSE '1';
PROCESS(clk,reset)
VARIABLE mm: std_logic_vector(15 downto 0);
BEGIN
if stop='1'and clk='0' THEN mm:="0000000000000000";
elsIF reset='1' and stop='0'THEN
mm:="0000011000000000"; --复位,计费显示为起步费6.00
ELSIF clk'event and clk='1' and stop='0' THEN
IF en='1' THEN mm:=mm+money; --里程超过2公里
IF (mm(1)='1'or(mm(3 downto 1)="000")or(mm(3 downto 2)="11"))THEN
mm:=mm+6;END IF; --十六进制转换成十进制
IF mm(7)='1'and (not(mm(6 downto 5)="00"))THEN
mm:=mm+"01100000";END IF;
IF mm(11)='1'and(not(mm(10 downto 9)="00"))THEN
mm:=mm+"011000000000";END IF;
END IF;
END IF;
count1<=mm(3 downto 0);
count2<=mm(7 downto 4);
count3<=mm(11 downto 8);
count4<=mm(15 downto 12);
mcount<=mm;
END PROCESS;
END aa;
仿真结果:
起步后开始计费
行驶2公里后
行驶15公里后
停止后
7.4 动态扫描模块
动态扫描电路将计数器A、B、C的计费状态用数码管显示出来,所连接的数码管共用一个数据端,由片选信号依次选择输出,轮流显示。该模块经过6选1选择器将计费数据(3位BCD码)、计程数据(3位BCD码)动态选择输出。其中计费数据送入显示译码模块进行译码,最后送至十元、元、角为单位对应的数码管上显示;计程数据送入显示译码模块进行译码,最后送至以公里为单位的数码管上显示。如图所示:
程序代码:
片选:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY pianxuan IS
PORT(CLK: IN STD_LOGIC;
A: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END pianxuan;
ARCHITECTURE RT1 OF pianxuan IS
BEGIN
PROCESS(CLK)
VARIABLE B:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
IF(B="101")THEN
B:="000";
ELSE
B:=B+1;
END IF;
END IF;
A<=B;
END PROCESS;
END RT1;
六选一:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY liuxuanyi IS
PORT(C:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
DP: OUT STD_LOGIC;
A1,A2,A3,B1,B2,B3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
D:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END liuxuanyi;
ARCHITECTURE RT1 OF liuxuanyi IS
BEGIN
PROCESS(C,A1,A2,A3,B1,B2,B3)
VARIABLE COMB:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
COMB:=C;
CASE COMB IS
WHEN"000"=>D<=A1;
DP<='0';
WHEN"001"=>D<=A2;
DP<='1';
WHEN"010"=>D<=A3;
DP<='0';
WHEN"011"=>D<=B1;
DP<='0';
WHEN"100"=>D<=B2;
DP<='1';
WHEN"101"=>D<=B3;
DP<='0';
WHEN OTHERS=>NULL;
END CASE;
END PROCESS;
END RT1;
译码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY yima IS
PORT(D:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END yima;
ARCHITECTURE RT1 OF yima IS
BEGIN
PROCESS(D)
BEGIN
CASE D IS
WHEN"0000"=>Q<="0111111";
WHEN"0001"=>Q<="0000110";
WHEN"0010"=>Q<="1011011";
WHEN"0011"=>Q<="1001111";
WHEN"0100"=>Q<="1100110";
WHEN"0101"=>Q<="1101101";
WHEN"0110"=>Q<="1111101";
WHEN"0111"=>Q<="0100111";
WHEN"1000"=>Q<="1111111";
WHEN OTHERS=>Q<="1101111";
END CASE;
END PROCESS;
END RT1;
仿真结果:
译码举例
7.5 顶层模块
将以上各模块的原理图对应的端口连接,如图所示。
仿真结果:
启动后
暂停
换挡
行驶超过2公里后
停止后
心得体会:
通过本次对于出租车计费系统的设计,我们进一步掌握了VHDL这一语言,熟悉了Quartus2操作环境,更进一步地熟悉了有关数字电路的知识和具体应用。
并能根据仿真结果来分析设计存在的问题及缺陷,从而能进行程序的调试和完善。总的来说,通过本次设计更进一步的增加了动手能力,对出租车计费系统的原理也有了更透彻的理解。
虽然出租车计费系统已经初步实现其功能,但还存在一定的缺陷和不足,我们也还有很多该努力的地方!以后的日子里,我们要更加努力学习,争取学有所用,把所学的知识用于实践,对社会做一些有益的事情!
附:
计费时钟
档位
启动
控制模块
显示模块
暂停
停止