EDA出租车计费器设计
1. 出租车计费器的总体设计
1.1出租车计费设计
该出租车计费器按下开关S1后开始计费和计里程数,分为白天和夜晚。当拨动开关K2为0时,系统使用程序设置的起步价,白天起步价是3元,准行2公里,以后2元/公里;夜晚起步价是9元,准行2公里,以后3元/公里。当拨动开关K2为1时,可由矩阵键盘输入起步价0~9元。当路程大于200公里时,价格会在原来的基础上加50元。
1.2基本设计思想
时钟输入为一个1KHz的系统时钟,直流电机模块每转一圈输出一个脉冲信号给CPU,另外用按键模块的S1 来作为整个系统的复位按钮,每复位一次,计费器从头开始计费。直流电机模块用来模拟出租车的车轮子,每转动一圈认为是行走1 米,所以每旋转1000 圈,认为车子前进1 公里。系统设计是需要检测电机的转动情况,每转1000圈,分频模块输出一个下降沿信号。车费和里程数在一个8位7段数码管上显示,前4位显示里程,后4位显示费用。路程的单价由16*16点阵显示,拨动开关K1为0时,2元/公里,点阵显示2;拨动开关K2为1时,3元/公里,点阵显示3。
2. 出租车计费器的总体实现
2.1系统总体框图
该出租车计费器由一个VHDL程序构成,不同功能的实现分别是多个进程控制,主要进程有:
分频模块进程:将每1000个电机脉冲转化为1个输出脉冲; 计程模块进程:记录已行里程; 计费模块进程:计算应付车费;
4*4矩阵键盘进程:设置起步价;
数码管显示进程:将已行里程和应付车费显示在数码管上; 16*16点阵显示进程:显示当前状态的每公里单价。
图2-1系统框图
2.2 程序流程图
(2) 计程模块
图2-3计程模块
(3)计费模块
图2-4计费模块
2.3出租车计费器各功能的实现
(1)分频模块:直流电机motor每输出1000个脉冲,分频器glclk输出一个下降沿脉冲,表示电机已走1公里,meter1加1.
if rst='0' then
count
elsif (motor'event and motor='1') then
if count>499 then
count
else
count
end if;
end if; glclk
(2)计程模块:glclk的下降沿来临时,路程的个位加1,满9往高位进一,同时低位归0。
process(glclk) begin if(Rst='0') then Meter1
if(Meter100=9) then Meter100
Meter1K
Meter100
Meter10
Meter1
lucheng
(3)计费模块:路程小于等于2公里时,费用为起步价;路程大于2公里,小于200公里,费用为(起步价+(路程-2)*单价);路程大于200公里时费用为(起步价+(路程-2)*单价+50)。
process(clk,rst) begin
if((Rst='0') or (lucheng
elsif(clk'event and clk='0') then if lucheng>200 then jiage
money1000
money10
mod
1000)-((jiage
mod
1000)mod
money1
jiage
money1000
money100
money10
money1
(4)4*4矩阵键盘:有键按下时为低电平,脉冲扫描时先判断行,再判断列。
process(clk)
begin
if(clk'event and clk='1') then if(Krow="1111") then kflag1
if(kcount=0) then Kcol
Kcol
kflag1
if(clk'event and clk='1') then if(kflag1='1') then if(keyrow="0111") then case keycol is
when "0111"=>buffbuffbuff
when others=>buff
when "0111"=>buffbuffbuffbuff
when others=>buff
when "1101"=>buffbuffbuffbuff
end if; qibujia
end if; end process;
qibujia_d
qibujia
else
qibujia
end if;
(5)数码管显示:通过位选端控制八位数码管的显示,每次显示一位,通过提高时钟的频率,达到显示的效果。
process(SEG_SEL) begin
case (SEG_SEL+1) is
when "000"=>Disp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_Temp
process(Disp_Temp) begin
case Disp_Temp is
when 0=>Disp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_Decode
(6)16*16点阵显示:点阵扫描时,先扫描列,再扫描行,点阵是自下往上、从左到右显示,提高时钟频率达到显示效果。
process(cdount)
begin
case cdount is
when "0000"=>ledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcol
end case;
end process;
3系统调试与仿真
从图中可看出,给一个复位信号后,费用的最低位为“0011”,即3,里程数的最低位为“0000”,即0,每当temp信号出现一个下降沿,里程数的最低位各加1,费用增加相应的单价,符合课题要求。
图3-1系统仿真图
4总结与体会
为期两周的实训已经过去了,对于我来说这两周周的实训赋予了我太多实用的东西了,不仅让我更深层次的对课本的理论知识深入了理解,而且还让我对分析事物的逻辑思维能力得到了锻炼,提高了实际动手能力。
刚开始看到这次的题目“出租车计费器”,感觉应该不难,但真正开始动手编程的时候,感觉有点无从下手,最后老师的指导和同学们的帮助下,慢慢克服了一个又一个困难。在实验室中,我熟悉了对Quartus Ⅱ软件的一般项目的操作和学到了处理简单问题的基本方法,更重要的是掌握了VHDL语言的基本设计思路和方法,我想这些会对我今后的学习起到很大的助推作用。此外,还要在今后的课本理论知识学习过程中要一步一个脚印的扎实学习,灵活的掌握和运用专业理论知识这样才能在以后出去工作的实践过程中有所成果。
最后还要感谢学校为我们提供这样专业的实践平台还有老师在实训以来的不断指导和同学的热情帮助。总的来说,这次实训我收获很大。
附录A出租车计费器VHDL源程序
library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity dianzhen is
port( Clk : in std_logic; --时钟输入 k1,k2 : in std_logic; --danjiaxuanze Rst : in std_logic; --复位输入
Motor : in std_logic; --电机脉冲输入 Krow : in std_logic_vector(3 downto 0); Kcol : buffer std_logic_vector(3 downto 0);
Display : out std_logic_vector(7 downto 0); --七段码管显示输出
SEG_SEL : buffer std_logic_vector(2 downto 0); --七段码管扫描驱动
ledcol:outstd_logic_vector(3 downto 0); --点阵列控制 ledrow:outstd_logic_vector(15 downto 0)); --点阵行显示 end dianzhen;
architecture behave of dianzhen is signal Disp_Temp : integer range 0 to 15;
signal Disp_Decode: std_logic_vector(7 downto 0);
signal Meter1,Meter10,Meter100,Meter1K : integer range 0 to 9; signal Money1,Money10,Money100,Money1000 : integer range 0 to 9; signal danjia,day,night,qibujia,qibujia_d,qibujia_n: integer range 0 to 9; signal temp,glclk:std_logic; signal count:integer range 0 to 500;
signal lucheng,jiage:integer range 0 to 100000; signal cdount : std_logic_vector(3 downto 0); signal buff :integer range 0 to 15;
signal keyrow,keycol:std_logic_vector(3 downto 0); signal kcount:std_logic_vector(2 downto 0);
signal kflag1:std_logic; begin
process(motor,rst) begin
day
danjia
else danjia
count
elsif (motor'event and motor='1') then
if count>499 then
count
else
count
end if;
end if; glclk
end process; process(clk)
begin
if(clk'event and clk='1') then if(Krow="1111") then kflag1
if(kcount=0) then Kcol
elsif(kcount=1) then Kcol
kflag1
if(clk'event and clk='1') then if(kflag1='1') then if(keyrow="0111") then case keycol is
when "0111"=>buffbuffbuff
when others=>buff
when "0111"=>buff
when "1011"=>buffbuffbuffbuff
when "1101"=>buffbuffbuffbuff
end if; qibujia
end if; end process; process(glclk) begin
qibujia_d
qibujia
else
qibujia
end if;
if(Rst='0') then Meter1
Meter1K
Meter100
Meter10
Meter1
lucheng
begin
if((Rst='0') or (lucheng200 then jiage
money1000
money10
mod
1000)-((jiage
mod
1000)mod
money1
jiage
money1000
money100
money10
money1
if clk'event and clk='1' then
if cdount
cdount
process(SEG_SEL) begin
case (SEG_SEL+1) is
when "000"=>Disp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_TempDisp_Temp
if(Clk'event and Clk='1') then --扫描累加 SEG_SEL
end if; end process;
process(Disp_Temp) --显示转换 begin
case Disp_Temp is
when 0=>Disp_DecodeDisp_Decode
when 2=>Disp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_DecodeDisp_Decodeledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcolledcol
when "1111"=>ledcol
--全灭
when others=>ledcol
end case;
end process;
process(danjia) begin
if danjia=0 then case cdount is
when "0000"=>ledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrowledrow
when "0000"=>ledrowledrowledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=2 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=3 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=4 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=5 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=6 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=7 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=8 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
elsifdanjia=9 then
case cdount is
when "0000"=>ledrowledrow
when "0010"=>ledrow
when "0011"=>ledrow
when "0100"=>ledrow
when "0101"=>ledrow
when "0110"=>ledrow
when "0111"=>ledrow
when "1000"=>ledrow
when "1001"=>ledrow
when "1010"=>ledrow
when "1011"=>ledrow
when "1100"=>ledrow
when "1101"=>ledrow
when "1110"=>ledrow
when "1111"=>ledrow
when others=>ledrow
end case;
end if;
end process;
end behave;
附录B总电路原理图