多功能出租车运营控制器.docx
《多功能出租车运营控制器.docx》由会员分享,可在线阅读,更多相关《多功能出租车运营控制器.docx(44页珍藏版)》请在冰豆网上搜索。
![多功能出租车运营控制器.docx](https://file1.bdocx.com/fileroot1/2022-11/24/62de42c2-8067-4532-bb36-7d587c78b268/62de42c2-8067-4532-bb36-7d587c78b2681.gif)
多功能出租车运营控制器
多功能出租车运营控制器
学号:
61007211
姓名:
洪立俊
1、申请题目:
多功能出租车运营控制器
这是一个以出租车计费为主要功能的基于FPGA的全数字系统,同时此系统还附加有一些相关的其他功能,比如计时,自动收费,管理员操作等。
2、课题背景:
出租车是人们日常生活中不可或缺的交通工具,但就目前的出租车运营状况来看,仍存在许多问题,比如司机乱收费,不打表现象较多,出租车公司对于运营信息的管理不到位,另外在客运安全方面仍存在较大漏洞,针对以上提到的问题,我觉得开发一个能够高效管理出租车运营的系统。
3、项目规划:
⏹系统功能:
此系统的功能主要有计时(附有闹钟和日期),运营计价,自动收费,运营信息保存,管理员操作等。
⏹指标及规模:
时间显示包括时,分,秒,日期显示包括日,月(分大小月,二月假设为29天),闹钟设置精确到秒,闹铃长达30s。
收费标准:
白天(6时到夜间23点)起步价为9元,3~15公里每公里1元,15公里以上每公里1.5元,每等待1分钟加收2元,夜间起步价10元,超过3公里每公里1.8元,每等待1分钟3元。
计价按每100米计价,里程增加。
里程最大为99公里,收费最大999.99元,自动收费接受10,5元,1元,自动找零找都是1元。
系统涉及密码为6位。
⏹面板(显示):
6个8段数码管,4×4小键盘,开关若干,LED灯
⏹操作及规则:
复位后进入计时,按C修改时间,中途按B可退出,完成六位修改后按E确认,按6进入设置闹钟状态,类似于时间的修改。
闹钟时间到或者按0关闭,或者30s后自动关闭。
按4显示日期,按C修改日期,类似时间修改。
按B回到时间显示。
按A进入登陆过程,输入6为密码,登录成功进入,管理员操作程序,按D修改里程分配参数,按F可阅读运营记录。
按B退出管理员操作,按F键进入运营过程,按方向键可切换里程和费用的显示,按2进入等待。
按3保存记录,进入自动收费,通过拨开关进行收费。
收完费进入自动找零至零。
按E回到时间显示。
⏹输入、输出接口:
键盘有扫描译码模块,数码管有译码模块及显示驱动模块,相当于数据选择器。
4、实现方案:
⏹核心问题:
状态的控制及转移,数据处理模块的设计,以及若干显示的分时显示模块的设计。
⏹解决方案:
FPGA设计顶层文件采用图形化设计,状态机及相关数据处理单元,附加模块部分采用VHDL语言设计,部分采用图形化设计。
由于显示部分也是比较复杂的,所以也引进状态的概念对显示内容进行控制。
存储器采用数组的形式存储二进制信息,数组元素即为逻辑值向量。
5、系统结构:
⏹系统框图:
⏹模块功能描述:
输入接口用于译码产生相关的控制信号,状态机用于控制不同时刻的相关操作,数据处理单元用来处理相关信号,包括计时模块,相关寄存模块,计费,收费,计程模块,存储器模块等,输出驱动模块用于控制不同时候的输出。
⏹模块接口标注:
输入模块接口有4位键盘码keyvalue输出,握手信号pressed,以及一些经消抖同步的外部输入,如复位reset,闹钟开关控制alarm_on,收费脉冲输入f10,f5,f1,状态机产生控制信号,修改时间,日期使能timeload,dateload,修改密码使能,存储记录使能store,运营控制信号showXX,阅读记录信号readXX,找零信号等。
数据处理模块产生时间time,日期date,密码code,里程kilo,收费charge,存储器记录输出record等。
输出模块输入包括显示状态控制信号ss,各数据处理单元的显示输出内容,输出为6个8段数码管的信号,和一个闹钟到信号alarmsignal。
6、状态流程图:
⏹系统工作状态流程
由于系统比较庞大,操作过程比较多,所以涉及的状态控制也比较多,为了更加清楚地表示各状态间的控制转移,以及不同状态对应的控制输出信号,现采用多状态机的描述方法。
包括主流程图,各子流程图,其中一些具有类似功能的流程就省略了,比如校准日期,设置闹钟,设置参数的流程就和校准时间的流程类似。
1.总流程图:
2.出租车运营流程图
3.校准时间流程图:
4.管理员登录流程:
5.管理员修改密码流程
6.管理员阅读运营记录流程图:
7、程序清单
由于本系统的复杂性,所以程序比较多,这里仅列出主要的程序,同一个程序中类似的代码则省略,具有类似功能的代码仅举其一。
--键盘译码,按键动作标志生成模块--
libraryieee;
useieee.std_logic_1164.all;
entitykey_decoderis
port(col3,col2,col1,col0:
instd_logic;
row3,row2,row1,row0:
instd_logic;
clk,scan_clk:
instd_logic;
keyvalue:
outstd_logic_vector(3downto0);
pressed,stop:
outstd_logic);
endkey_decoder;
architecturertlofkey_decoderis
signaltemp:
std_logic_vector(7downto0);
signaltemp_pressed:
std_logic;
signalq1,q2,q3,q4,q5,q6:
std_logic;
signalkeypressed_asy:
std_logic;
begin
temp<=row3&row2&row1&row0&col3&col2&col1&col0;
process(temp)--键盘译码
begin
casetempis
when"11101110"=>keyvalue<="0000";
temp_pressed<='1';
when"11101101"=>keyvalue<="0001";
temp_pressed<='1';
省略部分
when"01111101"=>keyvalue<="1101";
temp_pressed<='1';
when"01111011"=>keyvalue<="1110";
temp_pressed<='1';
when"01110111"=>keyvalue<="1111";
temp_pressed<='1';
whenothers=>temp_pressed<='0';
endcase;
endprocess;
process(scan_clk)--按键动作标志消抖
begin
if(scan_clk'eventandscan_clk='1')then
q1<=temp_pressed;
q2<=q1;
q3<=q2;
q4<=q3;
endif;
keypressed_asy<=q1orq2orq3orq4;
endprocess;
process(clk)--按键动作标志与全局时钟同步化
begin
if(clk'eventandclk='1')then
q5<=keypressed_asy;
q6<=q5;
endif;
pressed<=q5andnot(q6);
endprocess;
stop<=col3andcol2andcol1andcol0;
endrtl;
--里程计数模块--
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entitykilocounteris
port(start,mile,pause:
instd_logic;--开始计数,里程脉冲输入,暂停使能输入端
kilo:
outstd_logic_vector(11downto0);--公里数输出端
high_3,high_15:
outstd_logic);--大于三公里,大于15公里的使能输出端
endkilocounter;
architecturertlofkilocounteris
signalk1,k0,k00:
std_logic_vector(3downto0);
begin
process(start,pause,mile)
begin
ifstart='0'then--未进入里程计数时里程数始终保持为零
k1<="0000";k0<="0000";k00<="0000";
high_3<='0';high_15<='0';
else
ifpause='1'then--等待状态下保持里程数
k1<=k1;k0<=k0;k00<=k00;
elsifrising_edge(mile)then--在里程脉冲下正常计数
ifk00="1001"then
k00<="0000";
ifk0="1001"then
k0<="0000";
ifk1="1001"then
k1<="0000";
else
k1<=k1+1;
endif;
else
k0<=k0+1;
endif;
else
k00<=k00+1;
endif;
endif;
endif;
ifk0>="0011"then--达到里程要求时标志信号有效
high_3<='1';
endif;
ifk1>="0010"or(k1="0001"andk0>="0101")then
high_15<='1';
endif;
endprocess;
kilo(11downto8)<=k1;kilo(7downto4)<=k0;kilo(3downto0)<=k00;
endrtl;
--计时模块--
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitytime_counteris
port(clk,reset,timeload:
instd_logic;--全局时钟输入,开机复位端,修改时间置数端
buffertime:
instd_logic_vector(23downto0);--时间并行输入端
time:
outstd_logic_vector(23downto0);--时间输出端
ci:
outstd_logic);--时间进位进日月模块
endtime_counter;
architecturertloftime_counteris
signalclk1s:
std_logic;
signaltemp_time5,temp_time4,temp_time3,temp_time2,temp_time1,temp_time0:
std_logic_vector(3downto0);
componentdivider_1s--500分频器说明
port(clk:
instd_logic;
clk1s:
outstd_logic);
endcomponent;
begin
divider1s:
divider_1s--500分频器实例化
portmap(clk=>clk,
clk1s=>clk1s);
process(clk1s,clk,reset,timeload)
begin
ifreset='0'then--复位清零
temp_time5<="0000";temp_time4<="0000";temp_time3<="0000";temp_time2<="0000";temp_time1<="0000";temp_time0<="0000";
elsifrising_edge(clk)then
iftimeload='1'then--修改时间时置数
temp_time5<=buffertime(23downto20);
temp_time4<=buffertime(19downto16);
temp_time3<=buffertime(15downto12);
temp_time2<=buffertime(11downto8);
temp_time1<=buffertime(7downto4);
temp_time0<=buffertime(3downto0);
else--正常计时
ifclk1s='1'then
iftemp_time0="1001"then
temp_time0<="0000";
iftemp_time1="0101"then
temp_time1<="0000";
iftemp_time2="1001"then
temp_time2<="0000";
iftemp_time3="0101"then
temp_time3<="0000";
iftemp_time4="1001"andtemp_time5="0000"then
temp_time4<="0000";temp_time5<="0001";
elsiftemp_time4="1001"andtemp_time5="0001"then
temp_time4<="0000";temp_time5<="0010";
elsiftemp_time4="0011"andtemp_time5="0010"then
temp_time4<="0000";temp_time5<="0000";
else
temp_time4<=temp_time4+1;
endif;
else
temp_time3<=temp_time3+1;
endif;
else
temp_time2<=temp_time2+1;
endif;
else
temp_time1<=temp_time1+1;
endif;
else
temp_time0<=temp_time0+1;
endif;
endif;
endif;
endif;
--当计到23:
59:
59出现进位信号至日月模块--
iftemp_time5&temp_time4&temp_time3&temp_time2&temp_time1&temp_time0="001000110101100101011001"then
ci<='1';
else
ci<='0';
endif;
endprocess;
time(23downto20)<=temp_time5;time(19downto16)<=temp_time4;time(15downto12)<=temp_time3;time(11downto8)<=temp_time2;time(7downto4)<=temp_time1;time(3downto0)<=temp_time0;
endrtl;
--计费模块--
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitytotal_chargeis
port(start,pause,mile,f_wait:
instd_logic;--未运营状态,等待暂停状态,里程脉冲,等待时间脉冲
high_3,high_15:
instd_logic;--里程标志输入
time:
instd_logic_vector(23downto0);--时间输入
charge:
outstd_logic_vector(19downto0));--计费总价输出,分别为百,十,个,十分,百分位
endtotal_charge;
architecturertloftotal_chargeis
signalc4,c3,c2,c1,c0:
std_logic_vector(3downto0);
begin
process(time,pause,start,mile,f_wait,high_3,high_15)
variablehour_h,hour_l:
std_logic_vector(3downto0);
begin
hour_h:
=time(23downto20);
hour_l:
=time(19downto16);
ifstart='0'then--未运营时价格总为零
c4<="0000";c3<="0000";c2<="0000";c1<="0000";c0<="0000";
else
if(hour_h="0000"andhour_l>="0110")orhour_h="0001"or(hour_h="0010"andhour_l<="0010")then--白天运营
ifpause='1'then--等待下的计费
ifrising_edge(f_wait)then--即pause='1'进入等待状态
ifc2="1001"orc2="1000"then
ifc2="1001"then
c2<="0001";
else
c2<="0000";
endif;
ifc3="1001"then
c3<="0000";
ifc4="1001"then
c4<="0000";
else
c4<=c4+1;
endif;
else
c3<=c3+1;
endif;
else
c2<=c2+2;
endif;
endif;
else
ifrising_edge(mile)then--正常运营
ifhigh_3='0'then
c4<="0000";c3<="0000";c2<="1001";c1<="0000";c0<="0000";
elsifhigh_15='0'then
ifc1="1001"then
c1<="0000";
ifc2="1001"then
c2<="0000";
ifc3="1001"then
c3<="0000";
ifc4="1001"then
c4<="0000";
elsec4<=c4+1;
endif;
elsec3<=c3+1;
endif;
elsec2<=c2+1;
endif;
elsec1<=c1+1;
endif;
elsifhigh_3='1'andhigh_15='1'then
if(c0="0101"andc1="1000")orc1="1001"then
ifc1="1001"andc0="0101"then
c0<="0000";c1<="0001";
elsifc1="1001"andc0="0000"then
c0<="0101";c1<="0000";
elsifc1="1000"andc0="0101"then
c0<="0000";c1<="0000";
endif;
ifc2="1001"then
c2<="0000";
ifc3="1001"then
c3<="0000";
ifc4="1001"then
c4<="0000";
elsec4<=c4+1;
endif;
elsec3<=c3+1;
endif;
elsec2<=c2+1;
endif;
elsifc0="0000"then
c0<="0101";c1<=c1+1;
else
c0<="0000";c1<=c1+"0010";
endif;
endif;
endif;
endif;
else--夜间运营模式
ifpause='1'then
ifrising_edge(f_wait)then
省略部分
endprocess;
charge(19downto16)<=c4;charge(15downto12)<=c3;charge(11downto8)<=c2;charge(7downto4)<=c1;charge(3downto0)<=c0;
endrtl;
--铃声产生模块--
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitybell_prois
port(alarm_on,clk,alarm_load,pressed:
instd_logic;--闹钟开关,时钟,修改置数,键盘响应
buffertime:
instd_logic_vector(15downto0);--修改时间并行输入端
time:
instd_logic_vector(23downto0);--当前时间并行输入
keyvalue:
instd_logic_vector(3downto0);--键盘值输入端
alarm_signal:
outstd_logic);--闹铃信号输出端
endbell_pro;
architecturertlofbell_prois
signalalarm:
std_logic;
typestateis(s0,s1,s2,s3);
signalpre_state:
state:
=s0;
signalnext_state:
state:
=s0;
signaliner_ala_time:
std_logic_vector(15downto0);
begin
process(clk)--修改置数进程
begin
ifrising_edge(clk)then
ifalarm_load='1'then
iner_ala_time<=buffertime;
endif;
endif;
endprocess;
process(clk,alarm_on)--状态转移进程
begin
ifalarm_on='0'then
pre_state<=s0;
elsifrising_edge(clk)then
pre_state<=next_state;
endif;
endprocess;
process(pre_state,time,iner_ala_time,pr