基于FPGA的出租车计费器的设计

博主福利:100G+电子设计学习资源包!

http://mp.weixin.qq.com/mp/homepage?__biz=MzU3OTczMzk5Mg==&hid=7&sn=ad5d5d0f15df84f4a92ebf72f88d4ee8&scene=18#wechat_redirect
--------------------------------------------------------------------------------------------------------------------------

 

1  概述

EDA(Electronic Design Automation)即电子设计自动化,是电子设计技术的核心,它的系统级高层次电子设计方法,对整个系统进行方案设计和功能划分,无须通过门级原理图描述电路,而是针对设计目标进行功能描述。
 
FPGA 是现场可编程门阵列的简称。它结合了微电子技术、电路技术和EDA技术,使设计者可以集中精力进行所需逻辑功能的设计,缩短设计周期,提高设计质量。FPGA的开发系统包括软件和硬件两个部分,开发系统软件指专用的编程语言和相应的汇编程序或编译程序。开发系统硬件部分包括计算机和编程器。编程器是对FPGA进行写入和擦除的专用装置,能够供写入或擦除操作所需要的电源电压和控制信号,并通过串行接口从计算机接收编程数据,最终写进FPGA之中。
 
基于FPGA的计费器系统利用Verilog HDL语言,采用模块化程序设计,自顶向下、由粗到细、逐步求精的方法,将基于FPGA的计费器系统的整体逐步分解各个模块。它不需要专门的硬件,只通过软件编程即可实现计费器系统的逻辑功能、电路结构和连接形式。Verilog HDL语言类似C语言,可读性强、更易理解,这种语言几乎覆盖了以往各种硬件描述语言的功能,在编程的过程中一般采用自顶向下的电路设计过程。
 
本设计利用Verilog HDL语言,在QuartusⅡ13.0软件中将出租车计费器基本结构分成6个模块对其进行程序汇编。将各块程序生成的.v文件组合在一起,生成数字钟源代码的.bdf 图形文件,最后下载到CycloneⅡ系列芯片EP20C8Q208C8N中,验证试验结果。
 

 

1.1 设计要求

1.1.1 设计任务

设计并制作一台出租车计费器。
 

1.1.2 性能指标要求

① 用EDA实训仪的I/O设备和PLD芯片实现出租车计费器的设计。
② 出租车起步开始计程和计费,计程系统按实际公里数计程,计费系统首先显示起步价(如7.0),车行驶2km以内,只收起步价7元。
③ 出租车行驶超过2km后,按每公里1.6元在7.0元的基础上增加。
④ 出租车行驶超过10km后(或超过20元路费),每公里加收50%的车费,即车费变为每公里2.4元。
⑤ 出租车达到目的地后,(用一个按钮)计程和计费数据清零,为下一次计费开始。
 
 

1.2 总体设计基本原理及框图

1.2.1 基本原理

该出租车计费器的基本原理方框图如图1所示,由时钟模块、控制模块、计程模块、音乐模块、LCD显示模块、计费模块6部分组成。该计费系统通过分频模块将20MHz的时钟信号通过分频器变成1Hz的时钟信号和50Hz的显示输出信号。该出租车计费的标准是起步价是6元,2公里之内费用不变,当超过2公里时,每行驶1公里,费用加收50%元;由peo信号来控制有人或者没人,高电平有人,低电平显示空车,出租车计费显示模块显示相应的费用和行驶的里程。当res为低电平时,计费系统复位。该计费系统的显示费用是0~999.9元
 
 

1.2.2 总体框图

图1  总体框图
 
 

2 系统软件设计分析

整个系统由6个模块组成:
 
 

2.1时钟模块

时钟模块,提供实时时间,并可以通过按键调节分钟和小时并由其qs、qm、qh分别输出秒、分、时,clk20m输入20Mhz,clrn清零,fj和hj为调分和调时。用于区分白天与夜间计费,白天时间6:00~00:00、夜间时间00:00~6:00,由两个60进制计数器和一个24进制计数器组成,生成一个元件符号。
 
图2-1    时钟模块元件符号图
 
60进制计数器程序:
module cont60(clk,clrn,q,cout,j);
                            input j,clrn,clk;
                            output reg [7:0] q;
                            output reg cout;
                                          always @(  posedge clk^j or posedge clrn  )
                                                        begin
                                                        if(clrn) q=0;
                                                        else
                                                        begin
                                                                                    q = q+1; if(q[3:0] >= 10)
                                                                                    begin q[3:0] = 0;q[7:4] = q[7:4]+1;
                                                                                         if(q[7:4] >= 6) q[7:4] = 0;
                                                                                    end            
                                                                                    if( q == 'h00 ) cout = 1;else  cout = 0;
                                                        end
                                          end
              endmodule
24进制计数器程序:
module cont24(clk,clrn,q,cout,j);
                 input j,clk,clrn;
                            output reg [7:0] q;
                 output reg cout;
                                          always@(  posedge clk^j or posedge clrn  )
                                                        begin
                                                        if(clrn)begin q=0;cout = 0;end
                                                        else
                                                        begin
                                                                      q = q+1; if(q[3:0] >= 10)
                                                                      begin q[3:0] = 0; q[7:4] = q[7:4]+1;            
                                                                      end            
                                                                      if( q >= 'h24 )
                                                                      begin q = 0; cout = 1; end
                                                                      else  cout = 0; end               
end               
endmodule

 

图2-2   时钟仿真图
 
 

2.2控制模块

控制模块是用于控制车速的模块clk输入20Mhz,res清零作用,key_up是加速、key_down是减速,对应速度有0km/h、20km/h、40km/h——260km/h、280km/h、300km/h共15个速度调节来产生不同的频率由clk_speed输出,20km/h即11.1m每秒,所以20km/h要产生一秒为11100个上升沿,20Mhz/(2*11100),而gear输出不同的档位,通过对20MHz分频来产生不同的频率对应不同的速度,1秒内10000个上升沿表示1秒行驶了1m,改变频率即改变了1秒内上升沿的个数,就改变了速度。
 
图2-3    按键控制模块元件符号图
 
控制模块程序:
module key(clk,
          key_up,
                                          gear,
                                          res,
                                          key_down,
                                          clk_speed,
                                          people);
input res,people;
input key_up,clk,key_down;
output reg clk_speed;
reg [29:0] clk_sp_reg;
output reg[3:0]gear;
reg [29:0]up_c,down_c,n;
initial begin
gear='b1000;up_c=0;down_c=0;n=0;
clk_sp_reg=0;
end
always@( posedge clk or posedge res)//加速减速控制
begin
  if(res) begin  down_c=0;up_c=0;end
  else if(!people)begin  up_c=0;  down_c =0;   end else
  begin
                                          if(key_up)
                                                        begin
                                                                      up_c=up_c+1'b1;
                                                        end
                                                        else
                                                        begin
                                                                      up_c=0;
                                                        end
                                          if(key_down)
                                                        begin
                                                                      down_c=down_c+1'b1;
                                                        end
                                                        else
                                                        begin
                                                                      down_c=0;
                                                        end
  end
end
always @(posedge clk or posedge res)//速度对应的分频数,
begin
    if(res) begin  gear=0;  end
              else if(!people)begin  gear=0; clk_sp_reg=0;  end else
              begin
                  if(key_up ^ key_down )
                            begin
                                if(key_up==1)
                                begin
                                             if(up_c==5 && gear<='b1110)//200000)
                                                        gear=gear+1;
                                                        if(gear>='b1111)
                                                        gear='b1111;
                                          end
                                          if(key_down==1)
                                begin
                                             if(down_c==5)//200000)
                                                        if(gear=='b0)
                                                        gear='b0;else gear=gear-1;
                                          end
       end            
        case (gear)
                                          0 :  ;                                                                                                                              //速度为0
                                          1       :       clk_sp_reg=909;
                                          2       :       clk_sp_reg=454;
                                          3       :       clk_sp_reg=303;
                                          4       :       clk_sp_reg=227;
                                          5       :       clk_sp_reg=181;
                                          6       :       clk_sp_reg=151;
                                          7       :       clk_sp_reg=129;
                                          8       :       clk_sp_reg=113;
                                          9       :       clk_sp_reg=101;
                                          10      :       clk_sp_reg=90;
                                          11      :       clk_sp_reg=82;
                                          12      :       clk_sp_reg=75;
                                          13      :       clk_sp_reg=69;
                                          14      :       clk_sp_reg=64;
                                          15      :       clk_sp_reg=60;
          endcase
              end
end
always @( posedge  clk  or  posedge res) //把20MHz分频,产生相对应速度的频率
begin
                                          if(res)begin n<=0;clk_speed<=0;end
                                          else  if(!people)begin  n<=0;clk_speed<=0;  end else
                                          begin
                                                        if (n>=clk_sp_reg && gear!=0)            
                                                        begin n<=0;clk_speed<=~clk_speed; end
                                             else
                                                        begin              n<=n+1; clk_speed<=clk_speed;end
                                          end
end  
endmodule

 

图2-4                            控制模块仿真图


2.3计程模块

计程模块由五个100进制的计数器组成,clk输入控制模块分频出来的频率,然后在计程模块进行计数,只显示qshiwan到qshiyi的计程其中qshiwan[7:4]是百米计程,这样能使计费精确到分以下,所以计程用1000个上升沿记为1米,
 
图2-5                            计程模块元件符号图
 
计程模块程序:
module counter0_99(clk,clr,q,cout,people);
                            input clk,clr,people;
                            output reg [7:0] q;
                            output reg cout;
                            reg one='b1;
                            initial q='h99;
                                          always@(  posedge clk or posedge clr or  negedge people )
                                                        begin
                                                        if(clr ) q=0;
                                                        else
                                                        begin    if(!people) q=0;
                                                                    else
                                                                                                                begin
                                                                                                                q = q+1;
                                                                                                                if(q[3:0] >= 10)
                                                                                                                begin
                                                                                                                              q[3:0] = 0;
                                                                                                                              q[7:4] = q[7:4]+one;
                                                                                                                              if(q[7:4] >= 10)
                                                                                                                              q[7:4] = 0;
                                                                                                                end            
                                                                                                                if( q == 0 )
                                                                                                                cout = 1;
                                                                                                                else
                                                                                                                cout = 0;
                                                                                                                end                end                                          end              endmodule

 

图2-6                            计程模块仿真图
 

2.4音乐模块

音乐模块的clk是时钟输入,people是有人和没人的状态标志,beep外接蜂鸣器,并设定了两个音乐《送别》和《起风了》,作为乘客上车下车时播放的音乐,播放音乐的原理是通过改变频率来改变音高,改变延时时间来确定一小节拍的时间是240ms,通过分频产生。
//音高与频率的对应关系
//| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
//|低音 |261.6Hz |293.7Hz |329.6Hz |349.2Hz | 392Hz | 440Hz |493.9Hz |
//|中音 |523.3Hz |587.3Hz |659.3Hz |698.5Hz | 784Hz | 880Hz |987.8Hz |
//|高音 |1045.5Hz|1174.7Hz|1318.5Hz|1396.9Hz| 1568Hz | 1760Hz |1975.5Hz|
//乐谱参数:D=F/2K (D:参数,F:时钟频率,K:音高频率)
图2-7                            音乐模块元件符号图
音乐模块程序:
  1. module music( clk,people,  beep);
  2. input clk,people;
  3. output reg  beep;
  4. reg flag ,flag1;
  5. reg[7:0] state,state1; //乐谱状态机
  6. reg[16:0]count,count_end;
  7. reg[23:0]count1,count2;  //乐谱参数:D=F/2K (D:参数,F:时钟频率,K:音高频率)
  8. parameter   S_0=8'd20000000,   
  9.             L_1 = 17'd38226, M_1 = 17'd19109, H_1 = 17'd09564, //音1
  10.                                                         L_2 = 17'd34048, M_2 = 17'd17027, H_2 = 17'd08512, //音2
  11.                                                         L_3 = 17'd30339, M_3 = 17'd15167, H_3 = 17'd07584, //音3
  12.                                                         L_4 = 17'd28636, M_4 = 17'd14316, H_4 = 17'd07158, //音4
  13.                                                         L_5 = 17'd25510, M_5 = 17'd13368, H_5 = 17'd06377, //音5
  14.                                                         L_6 = 17'd22727, M_6 = 17'd11363, H_6 = 17'd05681, //音6
  15.                                                         L_7 = 17'd20247, M_7 = 17'd10123, H_7 = 17'd05062; //音7
  16. parameter TIME = 2400000; //控制每一个音的长短(480ms)
  17. parameter TIME1 = 4800000; //控制每一个音的长短(240ms)
  18.                                                         always @(posedge clk)
  19.                                                         begin
  20.                                                         if(people==0)
  21.                                                         begin
  22.                                                               flag=1; state1 =0;count2=0;
  23.                                                              if(flag1==1)
  24.                                                               begin
  25.                                                                                         count = count + 1'b1; //计数器加1
  26.                                                                                         if(count == count_end && count_end!=S_0)
  27.                                                                                                   begin count = 17'h0; //计数器清零
  28.                                                                                                                     beep = !beep;end  //输出取反                  
  29.                                                                                                   if(count1 < TIME) count1 = count1 + 1'b1;
  30.                                                                                                   //一个节拍240mS  data=F/2/ms   T=2*N*Tc        
  31.                                                                                                   else  begin  count1 = 24'd0;
  32.                                                                                                                   if(state == 8'd127)
  33.                                                                                                                   begin flag = 0;state=8'd0;  end
  34.                                                                                                                   else  state = state + 1'b1;
  35.                                                                                                                   case(state)
  36.                                                                                                                   8'd0,8'd1,8'd2,8'd3: count_end = M_5;//低音"3",4个节拍
  37.                                                                                                                   8'd4,8'd5: count_end = M_3;//低音"5",持续2个节拍
  38.                                                                                                                   8'd6,8'd7: count_end = M_5;//低音"6",持续2个节拍
  39.                                                                                                                   8'd8,8'd9,8'd10,8'd11,
  40.                                                                                                                   8'd12,8'd13,8'd14,8'd15: count_end = H_1;//高音"1",8拍
  41.                                                                                                                   8'd16,8'd17,8'd18,8'd19: count_end = M_6;//中音"6",4拍
  42.                                                                                                                   8'd20,8'd21,8'd22,8'd23: count_end = H_1;//高音"1",4拍
  43.                                                                                                                   8'd24,8'd25,8'd26,8'd27,
  44.                                                                                                                   8'd28,8'd29,8'd30,8'd31,
  45.                                                                                                                   8'd32,8'd33,8'd34,8'd35: count_end = M_5;//中音"5",8拍
  46.                                                                                                                   8'd36,8'd37: flag1=0;//count_end = M_1;//低音"5",2拍
  47.                                                                                                                   endcase
  48.                                                                                                                               end
  49.                                                                                                   end
  50.                                                                       end
  51.                                                                       else
  52.                                                                       if(people==1)
  53.                                                                       begin
  54.                                                               flag1=1; state =0;count1=0;
  55.                                                               if(flag==1)
  56.                                                               begin
  57.                                                                                         count = count + 1'b1; //计数器加1
  58.                                                                                         if(count == count_end)
  59.                                                                                                   begin count = 17'h0; //计数器清零
  60.                                                                                                                 beep = !beep;end  //输出取反                  
  61.                                                                                                   if(count2 < TIME1) count2 = count2 + 1'b1;
  62.                                                                                                   //一个节拍240mS  data=F/2/ms   T=2*N*Tc        
  63.                                                                                                   else  begin  count2 = 24'd0;
  64.                                                                                                                   if(state1 == 8'd229)
  65.                                                                                                                   begin flag = 0;state1=8'd0;  end
  66.                                                                                                                   else  state1 = state1 + 1'b1;
  67.                                                                                                                   case(state1)
  68.                                                                                                                               8'd0,8'd1 : count_end = M_1;
  69.                                                                                                                               8'd2,8'd3 : count_end = M_2;
  70.                                                                                                                               8'd4,8'd5 : count_end = M_3;
  71.                                                                                                                               8'd6,8'd7 : count_end = M_1;//
  72.                                                                                                                               8'd8,8'd9 : count_end = M_6;
  73.                                                                                                                               8'd10 : count_end = M_5;
  74.                                                                                                                               8'd11 : count_end = M_6;
  75.                                                                                                                               8'd12 : count_end = M_6;
  76.                                                                                                                               8'd13,8'd14 : flag=0;//count_end = S_0;
  77.                                                                                                                   endcase
  78.                                                                                                                               end
  79.                                                                                                   end
  80.                                                                       end              
  81.                                           end
  82. endmodul

复制代码

 

2.5 LCD显示模块

显示模块是使用LCD1602液晶屏,其中clk是时钟,people是有人和没人的状态为rstn是清零,in_data是档位输入,q0到q4是公里数输入,qs、qm、qh是时钟输入,cost_lcd_in是费用输入,显示界面可以显示时间、行驶路程、速度、费用,由于程序数据转换太多,这里只给出一部分程序,后面的程序在附录。
LCD1602主要技术参数:显示容量:16×2个字符、芯片工作电压:4.5—5.5V、工作电流:2.0mA(5.0V)、模块最佳工作电压:5.0V、字符尺寸:2.95×4.35(W×H)mm。
图2-8                            LCD1602模型图

 

编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
数据
2
VDD
电源正极
10
D3
数据
3
VL
液晶显示偏压
11
D4
数据
4
RS
数据/命令选择
12
D5
数据
5
R/W
读/写选择
13
D6
数据
6
E
使能信号
14
D7
数据
7
D0
数据
15
BLA
背光源正极
8
D1
数据
16
BLK
背光源负极

 

表1                            引脚接口说明表

 

序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清显示
0
0
0
0
0
0
0
0
0
1
2
光标返回
0
0
0
0
0
0
0
0
1
*
3
置输入模式
0
0
0
0
0
0
0
1
I/D
S
4
显示开/关控制
0
0
0
0
0
0
1
D
C
B
5
光标或字符移位
0
0
0
0
0
1
S/C
R/L
*
*
6
置功能
0
0
0
0
1
DL
N
F
*
*
7
置字符发生存贮器地址
0
0
0
1
字符发生存贮器地址
8
置数据存贮器地址
0
0
1
显示数据存贮器地址
9
读忙标志或地址
0
1
BF
计数器地址
10
写数到CGRAM或DDRAM)
1
0
要写的数据内容
11
从CGRAM或DDRAM读数
1
1
读出的数据内容

 

表2                            控制指令表
 
1602液晶模块的读写操作,屏幕和光标的操作都是通过指令编程来实现的。(说明1为高电平,0为低电平)
指令1:清显示,指令码01H,光标复位到地址00H位置
指令2:光标复位,光标返回到地址00H
指令3:光标和显示位置设置I/D,光标移动方向,高电平右移,低电平左移,S:屏幕上所有文字是否左移或右移,高电平表示有效,低电平表示无效。
指令4:显示开关控制。D:控制整体的显示开与关,高电平表示开显示,低电平表示关显示。C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位 S/C :高电平时显示移动的文字,低电平时移动光标
指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时为双行显示,F:低电平时显示5X7的点阵字符,高电平时显示5X10的显示字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址 BF:忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平表示不忙。
图2-9                            LCD显示模块元件符号图
LCD显示模块程序:
  1. module lcd1602(sys_clk    ,
  2.       sys_rstn   ,     
  3.                             lcd_rs     ,   
  4.                             lcd_rw     ,   
  5.                             lcd_en     ,
  6.                             lcd_data   ,  
  7.                  in_data,
  8.       q0,q1,q2,q3,q4,qs,qm,qh,people,
  9.                             cost_lcd_in
  10.               ); //输入输出信号定义
  11.                             input               [31:0]              cost_lcd_in;
  12.                             input  [7:0]  q0,q1,q2,q3,q4,qs,qm,qh;
  13.                             input  sys_clk    ;//系统时钟输入
  14.                             input    people,      sys_rstn   ;//系统复位信号,低电平有效
  15.                             input   [3:0] in_data;
  16.                             output         lcd_rs     ;//lcd的寄存器选择输出信号
  17.                             output         lcd_rw     ;//lcd的读、写操作选择输出信号
  18.                             output         lcd_en     ;//lcd使能信号
  19.                             output  [7:0]  lcd_data   ;//lcd的数据总线(不进行读操作,故为输出)
  20.                             reg            lcd_rs     ;
  21.                             reg            clk_div    ;
  22.                             reg [7:0]  q1h,q1l,q2h,q2l,q3h,q3l,q4l;
  23.                             reg [7:0]              sp_reg1,sp_reg2,sp_reg3;
  24.                             reg [7:0]              qsl,qsh,qml,qmh,qhl,qhh;
  25.                             reg [7:0] in_data_reg;
  26.                             reg [7:0]              cost_reg0,cost_reg1,cost_reg2,cost_reg3;
  27.                             reg     [17:0] delay_cnt  ;
  28.                             reg     [7:0]  lcd_data   ;
  29.                             reg     [4:0]  char_cnt   ;
  30.                             reg     [7:0]  data_disp  ;
  31.                             reg     [9:0]  state      ;
  32.                             parameter   
  33.                             idle                                                                         = 10'b000000000, //初始状态,下一个状态为CLEAR   
  34.                             clear                                                                        = 10'b000000001,  //清屏   
  35.                             set_function                                           = 10'b000000010,
  36.                             switch_mode                                           = 10'b000000100,
  37.                             set_mode                                              = 10'b000001000,
  38.                             shift                                                            = 10'b000010000,
  39.                             //光标、画面位移设置:光标向左平移一个字符位
  40.                             set_ddram1                                             = 10'b000100000,
  41.                             //设置DDRAM的地址:第一行起始为0x00(注意输出时DB7一定要为1)     
  42.                             set_ddram2                                             = 10'b001000000,  //设置DDRAM的地址:第二行为0x40                            write_ram1                                             = 10'b010000000,  //数据写入DDRAM相应的地址   
  43.                             write_ram2                                            = 10'b100000000;  //数据写入DDRAM相应的地址
  44.                             assign lcd_rw = 1'b0;      //没有读操作,R/W信号始终为低电平
  45.                             assign lcd_en = clk_div; //E信号出现高电平以及下降沿的时刻与LCD时钟相同              always@(posedge sys_clk or posedge sys_rstn) /分频
  46.               begin   if(sys_rstn)   begin    delay_cnt<=18'd0;    clk_div<=1'b0;
  47.               end  else if(delay_cnt==18'd200000)
  48.               begin
  49.               delay_cnt<=18'd0;    clk_div<=~clk_div;   end  else
  50.               begin    delay_cnt<=delay_cnt+1'b1;    clk_div<=clk_div;
  51.               end end
  52.               always@(posedge clk_div or posedge sys_rstn) //State Machine
  53.               begin  if(sys_rstn)
  54.               begin    state   <= idle;    lcd_data <= 8'b0;    char_cnt <= 5'd0;      
  55.               lcd_rs<=1'b0;//地址\数据
  56.    end  else   begin
  57.               case(state)
  58.               idle: begin      //初始状态     
  59.                          state <= clear;      lcd_data <= 8'b0;     end
  60.               clear: begin      //清屏   
  61.                                                         state <= set_function;   
  62.                                                         lcd_rs<=1'b0;   
  63.                                                         lcd_data <= 8'b00000001;     
  64.                                                         end  
  65.               set_function:      //功能设置(38H):8位数据接口/2行显示/5*8点阵字符  
  66.                                                                       begin      state <= switch_mode;      lcd_rs<=1'b0;
  67.                                                                       lcd_data <= 8'b00111000;         end  
  68.               switch_mode:       //显示开关控制(0CH):开显示,光标和闪烁关闭   
  69.                                                                       begin      state <= set_mode;      lcd_rs<=1'b0;   
  70.                                                                       lcd_data <= 8'b00001110;     end  
  71.               set_mode:begin   //输入方式设置(06H):数据读写操作后,地址自动加一/画面不动
  72.                            state <= shift;       lcd_rs<=1'b0;   
  73.                                                                       lcd_data <= 8'b00000110;     end
  74.               shift: begin      //光标、画面位移设置(10H):光标向左平移一个字符位
  75.                                                                       //(光标显示是关闭的,所以实际上设置是看不出效果的)  
  76.            state <= set_ddram1;      lcd_rs<=1'b0;   
  77.                                             lcd_data <= 8'b0001_0000;        end   
  78. set_ddram1: //设置DDRAM的地址:第一行起始为00H(注意输出时DB7一定要为1)     
  79.           begin      state <= write_ram1;   
  80.                                                                                     lcd_rs<=1'b0;      lcd_data <= 8'b1000_0000;//Line1
  81.                                           end
  82. set_ddram2:       //设置DDRAM的地址:第二行为40H(DB7一定要为1)
  83.                                                                       begin      state <= write_ram2;   
  84.                                                                       lcd_rs<=1'b0;      lcd_data <= 8'b1100_0000;//Line2   
  85.                                                                       end  
  86. write_ram1:        
  87.            begin              
  88.                                                                         if(char_cnt <=5'd15)
  89.                                                                         begin   char_cnt <= char_cnt + 1'b1;   
  90.                                                                                                     lcd_rs<=1'b1;  lcd_data <= data_disp;
  91.                                                                                                     state <= write_ram1;  end   
  92.                                                                         else   begin   state <= set_ddram2; end        
  93.                                             end
  94. write_ram2:
  95.             begin      
  96.                                                                                     if(char_cnt <=5'd30)
  97.                                                                                     begin char_cnt <= char_cnt + 1'b1;
  98.                                                                                                                 lcd_rs<=1'b1;   lcd_data <= data_disp;
  99.                                                                                                                 state <= write_ram2;    end     
  100.                                                                                     else   begin  char_cnt <=5'd0; state <= shift;     end      
  101.                                                         end
  102. default:  state <= idle;
  103. endcase  
  104. end
  105. end
复制代码

2.6计费模块

计费模块其中clk是20MHz输入,clrn清零,people是有人没人的状态位,q0到q4为里程输入,qh为小时输入,用于判断白天计程和夜间计费,其中又分0~2km不计程,2~10km加20%费用,且白天和夜间的四个计费阶段都有相对应的指示灯闪烁(L12到L15),白天:7元2km内7元,2km-10km每公里收费1.6元,10km以上每公里收费2.4元;夜间:起步价8元2km内8元,2km-10km每公里收费2元,10km以上每公里收费3元。cost_q输出费用。10km以上加收费用,1000个上升沿即为1米,则1km——1.6元,1000000个上升沿对应160分,1分即6250个上升沿,由于程序数据转换太多,这里只给出一部分程序,后面的程序在附录。
图2-10                            计费模块元件符号图
              计费模块程序:
  1.               module counter0_99_16(
  2.               clk,clr,cost_q,people,
  3.               q0,q1,q2,q3,q4,qh,
  4.               l12,l13,l14,l15
  5.               );
  6.                             input clk,clr,people;
  7.                             output              reg l12,l13,l14,l15;
  8.                             input [7:0] q0,q1,q2,q3,q4,qh;
  9.                             output reg [31:0] cost_q;
  10.                             reg [13:0] n;
  11.                             reg one='b1;
  12.                             initial              n=0;
  13.                             initial              cost_q='b0000_0000_0000_0000_0000_1000_0000_0000;
  14.                                           always@(  posedge clk or posedge clr or  negedge people )
  15.                                                         begin
  16.                                                         if(clr ) begin              l12=0;l13=0;l14=0;l15=0;cost_q=0;end
  17.                                                         else
  18.                                                         begin  if(!people)              begin l12=0;l13=0;l14=0;l15=0;
  19.               if(qh>'b00000110)cost_q='b0000_0000_0000_0000_0000_0111_0000_0000;
  20.                                                                                                   else              if(qh<='b00000110)cost_q='b0000_0000_0000_0000_0000_1000_0000_0000;              end
  21.                                                                     else
  22.                                                                                                   begin            
  23.                                                                                                   if(qh>8'b00000110)
  24.                                                                                                   begin
  25. if({q4,q3,q2,q0}<=32'b0000_0000_0001_0000_0000_0000_0000_0000
  26.                                                                                                   &&              {q4,q3,q2,q0}>32'b0000_0000_0000_0010_0000_0000_0000_0000              ) begin
  27.                                                                                                   //1000000电平除以160分,得出一分6250个上升沿
  28.                                                                                                                                             if(n              <              'd6250)              //1.6元
  29.                                                                                                                                             begin              n=n+'d1;              end            
  30.                                                                                                                                             if(n              >=              'd6250)
  31.                                                                                                                                             begin
  32.                                                                                                                                                           n<=0;            
  33.                                                                                                                                                           begin
  34.                                                                                                                                                           l12=~l12;l13=0;l14=0;l15=0;
  35.                                                                                                                                                           cost_q = cost_q+1;
  36.                                                                                                                                                           if(cost_q[3:0] >= 10)
  37.                                                                                                                                                           begin              cost_q[3:0] = 0;
  38.                                                                                                                                                           cost_q[7:4] = cost_q[7:4]+one;end            
  39.                                                                                                                                                           if(cost_q[7:4] >= 10)
  40.                                                                                                                                                           begin              cost_q[7:4] = 0;
  41.                                                                                                                                                           cost_q[11:8] = cost_q[11:8]+one;end            
  42.                                                                                                                                                           if(cost_q[11:8] >= 10)
  43.                                                                                                                                                           begin              cost_q[11:8] = 0;
  44.                                                                                                                                                           cost_q[15:12] = cost_q[15:12]+one;end
  45.                                                                                                                                                           if(cost_q[15:12] >= 10)
  46.                                                                                                                                                           begin              cost_q[15:12] = 0;
  47.                                                                                                                                                           cost_q[19:16] = cost_q[19:16]+one;end
  48.                                                                                                                                                           if(cost_q[19:16] >= 10)
  49.                                                                                                                                                           begin              cost_q[19:16] = 0;
  50.                                                                                                                                                           cost_q[23:20] = cost_q[23:20]+one;end
  51.                                                                                                                                                           if(cost_q[23:20] >= 10)
  52.                                                                                                                                                           begin              cost_q[23:20] = 0;
  53.                                                                                                                                                           cost_q[27:24] = cost_q[27:24]+one;end
  54.                                                                                                                                                           if(cost_q[27:24] >= 10)
  55.                                                                                                                                                           begin              cost_q[27:24] = 0;
  56.                                                                                                                                                           cost_q[31:28] = cost_q[31:28]+one;end
  57.                                                                                                                                                           end
  58.                                                                                                                                             end
  59.                                                                                                                               end else
  60.                                                                                     end
  61.                                                           end
  62.                         end                                                                                                  
  63.               end
  64.               endmodule
复制代码
图2-11                                          计费模块仿真图

3  系统测试(调试)3.1 测试仪器与设备

① EDA实验仪一台。
② 计算机一台(装有Quartus Ⅱ软件)

3.2 性能指标测试

把程序下载进实验箱,按键控制有人和没人的状态,蜂鸣器能正常播放音乐,然后运行计费器,通过计算的出的费用和路程相符合,白天和夜间的起步价、2km到10km计费标准和10km以上的计费标准都正确,且能显示正确的速度,时间,路程,四个收费阶段都有相对应的指示灯闪烁提示,速度的各档速也有相对应的灯点亮。
图3-1                            引脚锁定

 

图3-2                            白天计费测试图
图3-3                            夜间计费测试图

 

  • 23
    点赞
  • 185
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
摘 要 随着出租车行业的发展,对出租车计费的要求也越来越高。该系统主要是使用Mu ltisim10进行设计,运用计数、加法等进行电路设计与仿真。论文内容介绍了出租 车计费系统的组成及工作原理,简述了用数字电子件构成该数字系统的设计思想和 实现过程。 Along with the development of the taxi industry, the requirements of the message accounting device becoming higher than ever before. The system is mainly used Multisim10 design, using the counter, adding machines of circuit design and simulation. The essay introduces the message accounting device taxi system composition and working principle, the paper with digital electronic components of the digital system design idea and the implementation process. 关键词: Multisim10 计数 出租车计费 目录 Cotent 第1章 设计指标 3 1.1设计目的和意义 3 1.1.1目的 3 1.1.2意义 3 第2章 总体框图 3 2.1总体框图 3 第3章 各单元电路设计 4 3.1里程计费电路设计 4 3.2等候时间计费电路 5 3.3计数、锁存、显示电路 5 3.4 时钟电路 7 3.5置位电路和脉冲产生电路的设计 7 第4章 件选择及部分功能简介 9 4.1件选择 9 4.2部分功能简介 9 4.2.1 555定时 9 4.2.2 74LS160 11 第5章 总结 11 5.1结论 11 5.2优点与不足 12 5.3 心得与体会 12 第6章 参考文献 12 第1章 设计指标 1.1设计目的和意义 1.1.1目的 1. 自动计费具有行车里程计费、等候时间计费和起步费三部分,三项计费统一用4位数码 管显示,最大金额为99.99元。 2. 行车里程单价设为1.80元/km,等候时间计费设为1.5元/10分钟,起步费设为8.00元。要 求行车时,计费值每公里刷新一次;等候时每10分钟刷新一次;行车不到1km或等候不足 10分钟则忽略计费。 3. 在启动和停车时给出声音提示。 1.1.2意义 在我们是生活中,乘坐出租车是再常见不过的了,因此人们对出租车计费问题也是非 常的敏感的。随着出租车行业的发展,对出租车计费的要求也越来越高,用户不仅要 求计费性能稳定,计费准确,有防作弊功能;同时还要求其具有车票资料打印 、IC卡付费、语音报话、和电脑串行通信等功能。因此出租车计费在我们的生活中 也是很重要的。 第2章 总体框图 2.1总体框图 图1 出租车计费原理框图 分别将行车里程、等候时间都按相同的比价转换成脉冲信号,然后对这些脉冲进行计 数,而起价可以通过预置送入计数作为初值,如图1的原理框图所示。行车里程计数电 路每行车1km输出一个脉冲信号,启动行车单价计数输出与单价对应的脉冲数,例如单 价是1.80元/km,则设计一个一百八十进制计数,每公里输出180个脉冲到总费计数 ,即每个脉冲为0.01元。等候时间计数将来自时钟电路的秒脉冲作六百进制计数,得 到10分钟信号,用10分钟信号控制一个一百五十进制计数(等候10分钟单价计数) 向总费计数输入150个脉冲。这样,总费计数根据起步价所置的初值,加上里程脉冲 、等候时间脉冲即可得到总的用车费用。 上述方案中,如果将里程单价计数和10分钟等候单价计数用比例乘法完成,则 可以得到较简练的电路。它将里程脉冲乘以单价比例系数得到代表里程费用的脉冲信号 ,等候时间脉冲乘以单位时间的比例系数得到代表等候时间的时间费用脉冲,然后将这 两部分脉冲求和。 第3章 各单元电路设计 3.1里程计费电路设计 图2 里程计费电路 里程计费电路如图2所示。安装在与汽车轮相接的涡轮变速上的磁铁使干簧继电 在汽车每前进10m闭合一次,即输出一个脉冲信号。汽车每前进1km则输出100个脉冲。此 时,计费应累加1km的计费单价,本电路设为1.80元。在图3中,干簧继电产生的脉 冲信号经施密特触发整形得到CP0。CP0送入由两片74HC161构成的一百进制计数,当 计数计满100个脉冲时,一方面使计数清0,另一方面将基本RS触发的Q1置为1,使 74HC1
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值