找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5529|回复: 2
打印 上一主题 下一主题
收起左侧

基于FPGA的交通灯设计-含源码

[复制链接]
跳转到指定楼层
楼主
主要利用FPGA作为主控。

以FPGA为核心,设计一个交通灯控制器,每个路口都有红、黄、绿三盏灯。该交通信号灯控制器由一条车道A和一条车道B汇合成十字路口,在每个入口处设置红、绿、黄三色信号灯,红灯亮禁止通行,绿灯亮允许通行,黄灯亮则给行驶中的车辆有时间停在禁行线外。用红、绿、黄发光二极管作信号灯。


1.2要求

(1)东西、南北两个方向的信号灯必须交替工作且两个方向通行时间不同;

(2)显示采用LED光柱或数码管倒计时的方式。

(3)遇有紧急情况可人为将两个方向都置为红灯。

(4)每个路口用2个七段数码管倒计时显示。


2. FPGA模块方案论证及选择

各模块端口及信号连接如下图所示:

由上图可知,FPGA部分包括四个模块,顶层模块(top_traffic)、交通灯控制模块(traffic_light)、数码管显示模块(seg_led)、led灯控制模块(led)。在顶层模块中完 成对其它三个模块的例化,并实现各模块之间的数据传递。

顶层模块(top_traffic):顶层模块完成了对其它三个子模块的例化、实现了子模块间 的信号连接、并将led灯和数码管的驱动信号输出给外接设备(交通信号灯外设)。

交通灯控制模块(traffic_light):交通灯控制模块是本次实验的核心代码,这个模块 控制信号灯的状态转换,将实时的状态信号state[1:0]输出给led灯控制模块(led),同时将 东西和南北方向的实时时间数据ew_time[5:0]和sn_time[5:0]输出给数码管显示模块 (seg_led)。

数码管显示模块(seg_led):接收交通灯控制模块传递过来的东西和南北方向的实时时间数据ew_time[5:0]和sn_time[5:0],并以此驱动对应的数码管,将数据显示出来。

led灯控制模块(led):根据接收到的实时状态信号state[1:0],驱动东西和南北方向的led发光。


3. 原理设计
3.1
基本原理
点FPGA开发板上左边的P6扩展口可以用来外接交通信号灯扩展模块,交通信号
灯扩展模块的原理图如图 38.3.1所示。
图 38.3.1 交通信号灯原理图

由上图可知,交通信号灯扩展模块四个方向共12个LED灯,而我们使用6个LED控制信号来 驱动12个LED灯,这是因为东西方向或者南北方向LED灯的亮灭状态总是一致的,所以我们将东西方向或者南北方向颜色相同的LED灯并联在一起,这样设计的好处是减少了交通信号灯扩展模块LED控制信号的引脚。

上图中四个共阳型数码管分别对应四个路口,每个路口用两位数码管显示当前状态的剩余 时间。我们知道,在十字路口中,东西方向或者南北方向数码管显示的时间总是一样的。以东西方向为例,正因为这两个方向显示的时间一致,所以这两个方向的数码管,它们的十位可以用同一个位选信号来控制,个位用另一个位选信号来控制,这样的话,就可以实现两个位选信号控制东西方向共4位数码管的亮灭,南北方向的数码管同理。这样设计的好处是减少了交通信号灯扩展模块位选信号的引脚。

数码管由PNP型三极管驱动,当三极管的基极为低电平时,数码管相应的位被选通,所以交通信号灯扩展模块的位选信号是低电平有效的。

3.2系统组成框图

交通灯控制模块将需要显示的时间数据连接到数码管显示模块,同时将状态信号连接到led灯控制模块,然后数码管显示模块和led灯控制模块驱动交通信号灯外设工作。系统总体框架图如图 38.4.1所示,

      

3.3单元电路设计

3.3.1 FPGA最小系统

  FPGA最小系统包括:FPGA芯片、下载电路、外部时钟、复位电路和电源。

如果使用NIOS II软嵌入式处理器还要包括SDRAM和Flash。



     图3-3 FPGA最小系统

3.3.2 数码管显示电路

采用简单的4组2位共阳极数码管数码管由PNP型三极管驱动,当三极管的基极为低电平时,数码管相应的位被选通,所以交通信号灯扩展模块的位选信号是低电平有效的。


图3-4数码管显示电路

3.4总体电路图

交通灯控制模块将需要显示的时间数据连接到数码管显示模块,同时将状态信号连接到led灯控制模块,然后数码管显示模块和 led灯控制模块驱动交通信号灯外设工作。

总体电路图如下图所示:



          图3-6整体电路
3.5 程序设计
                  
3-7 系统软件流程图
3.6元件列表
发光二极管(红绿黄)
12个
2.54单排针1*40
2排
三极管8550
4个
排母
2排
数码管2位共阳
4组
FPGA模块
1块

4.方案实现与测试(或调试)
实现题上已给要求,在程序调试花费时间较多。
交通灯成品及实验现象


课题二:电梯
1、设计的目的与要求
1.1目的

设计以8952单片机、AVR或ARM和步进电机为核心,设计电梯控制器。假设电梯安装一个楼层为4楼的楼上。其人机接口包括显示器、键盘、喇叭、指示灯。

1.2要求
    每层楼电梯口都有上楼、下楼两个按钮,一个7段数码显示器作为电梯当前层指示灯。两个发光二极管作为电梯运行方向的指示灯;进入电梯里面,按数字键选择要去的楼层,一个7段数码管显示当前层显示,两个发光二极管作为电梯上行和下行指示灯。步进电机正转,上行,反转,表示下行。启动按钮按下去表示电梯控制系统可以运行。紧急停止按钮按下,电机停止运动。报警按钮按下,启动蜂鸣器和闪烁红色报警灯。
1.3 分工
马浩宁:电路设计、程序调试
    张晓涵:刻板、焊电路
    王春燕:写论文、查找资料
2、方案论证及选择
2.1 总体设计方案
设计的基本思想是采用STM32F103C8T6单片机作为核心采用8位LED静态显示来实时显示电梯所在楼层。采用行列式键盘矩阵作为外呼内选电路,由于是4层楼,故选用4×4矩阵键盘,键盘矩阵共16个按键,其中6个按键是各层楼外呼按键,2个表示电梯启动和停止的控制按键,电梯状态是通过3个发光二极管显示的,绿灯亮表示电梯在向上运行,黄灯亮表示电梯在向下运行,红灯亮表示电梯故障急停状态总体方框图如图2-1所示:
总体方框下图所示:


2.2  主控芯片选择   
方案一:多片单片机控制方案。这种方案是使用多片单片机,其中一片是作为主控制器,另外设置了轿厢控制系统,每层的控制系统分别由一个单片机控制,然后通过主控制器和副控制器之间的通讯,实现电梯系统的控制。这种方案的控制系统的结构简单明了,各个系统之间相互独立便于维护和修检。所以根据功能要求需要选用1片STM32单片机就能可以实现该电梯的功能。不过单片机之间的通讯较多,在目前通讯是个难点,可能导致电梯运行过程不稳定。
方案二:一片单片机为主控制器的方案。MCU采用一个单片机控制所有的按键、屏幕显示、电动机的转动等,并对以上所有信号进行处理。这种方案的控制系统相对复杂,只适用于较简单的电梯控制系统,因为这次的设计是四层电梯控制系统,所以选用这种方案。单片机技术目前较为成熟,自身资源丰富,硬件设计简单,成本低,可靠性高,结合软件完全可以实现电梯运行状况的简单模拟。
    权衡以上二种方案方案分析,采用方案二。
2.3  楼层显示选择
方案一:采用点阵式的液晶显示器(LCD)来显示各种相关的数据以及相关的信息。点阵式的液晶显示器虽然属于低功耗的器件,但其价格比较贵。
方案二:采用传统的八段数码管(LED)显示电梯实时所到的楼层。虽功耗大,但其软件驱动相对比较简单,硬件电路调试也比较方便,价格便宜,亮度大,能满足本设计的要求。
    以上两种方案中,选择方案一。
2.4  电动机驱动模块选择
方案一:步进电机作为设计的执行部件,在定位性能的步进电机是非常优越的。步进电机和普通电机的区别主要在于其脉冲驱动形式,步进电机不需要A/D 转换,能够直接将数字脉冲信号转化为角位移。常用的步进电机每转一步,角度转1.8°,在应用中,步进电机可以同时来完成两个工作,一个是传递转矩,第二个是传递信息,在本设计中作为传递信息用。
方案二:直流电机作为执行元件的设计,直流电机的功能是让线圈总是交替地处于稳定状态和不稳定的平衡状态,通过两个半圆环形电枢将稳定平衡线圈消除。这样一个载流线圈总是降低磁场。直流电机中常用的系统,高转矩,高扭矩,低惯量。
    以上两种方案采用方案一。
    利用DXP画图软件构建原理图如下图所示:
   

3、 原理设计
3.1 STM32F103C8T6功能简介
STM32F103C8T6是一款基于ARM Cortex-M 内核STM32系列的32位的微控制器,程序存储器容量是64KB,需要电压2V~3.6V,具有高达1MB的Flash、电机控制、USB和CAN,该系列利用一流的外设和低功耗、低压操作实现了高性能,同时还以可接受的价格、利用简单的架构和简便易用的工具实现了高集成度。从以上3种方案,很容易看出,采用方案3,电路设计比较简洁,软件设计也比较简单,故采用方案3。STM32F103C8T6实物图以及引脚结构图如图:


                          图3-1  STM32原理图


   
图 3-1 STM32F103C8T6实物图


3.2 单片机最小系统
最小系统包括复位电路和时钟电路两部分,其中复位电路采用上电自动复位,如图3-2所示:
                            图3-2 单片机最小系统



3.3  按键电路
本电路采用了13个按键。分别利用了P2和P3 端口,单片机采用行和列扫描法来判别这些按键中哪个键按下, S1-S13为微动按键,分别控制电梯的启动、停止、急停及电梯楼层呼叫开关,然后可根据每个按键的功能来通过单片机控制电梯的运行。                                 

         
图 3-3  矩阵按键原理图

图3-4  矩阵按键

各按钮开关说明:
电梯内:K4:紧急停止     K5:终止停止                 K14:关门
K9:选择一楼    K10:选择二楼                   K11:选择三楼     K12:选择四楼
电梯外:K1:一楼电梯上行 K2:二楼电梯上行 K3:三楼电梯上行
K6:二楼电梯下行 K7:三楼电梯下行 K8:四楼电梯下行
K15:启动         K16:停止
3.4报警电路设计

报警电路接单片机P35口,当端口变成低电平时, VCC电压加载到蜂鸣器使其发声、报警发光二极管亮,如图3-5。

图3-5   报警电路
3.5显示电路设计

采用点阵式的液晶显示器(LCD12864)来显示各种相关的数据以及相关的信息。点阵式的液晶显示器属于低功耗的器件,显示清晰便利

如图3.7,采用LCD12864显示电路,VCC接3.3V,RS接单片机A5,RW接单片机A6, EN接单片机A7口,当有输出时,直接在lcd 屏幕上进行显示。



图3-6  显示电路设计




4、方案实现与调试
4.1  软件设计思想
设计采用微动按键来代替外呼按钮,而电梯的运行方向和电梯启动和停止是根据这些呼叫按键和选择按键来决定的,所以单片机通过扫描键盘来获取各层呼叫状态,从而控制电梯的运行。故按键扫描是本系统软件设计中的重要一部分,另外要把键盘扫描到的各层的按键信息存储起来,然后和电梯的运行状态比较,判断是否响应各层呼叫,当电梯到达目的楼层时电机停止,可随意选择去哪一层,然后电梯选择判断去哪一层,继续运行。
由于本设计采用单片机实现自动控制,主要完成了整个系统系统如数码管的显示,按键的响应,转动电机的控制,延时等均由相应的子程序来完成。
软件设计思想:使用模块化的C语言编程,软件系统的功能层次化设计方法,包括多个单一功能的子程序的。通过调用不同的子程序,实现复杂的控制功能。这是方便调试,修改。软件编程是一种多功能,智能化,操作简便。在本设计中,可以把程序的各部分相互结合起来,达到完成各项设计的功能。
4.2  电梯主程序
根据任务要求,电梯的程序应满足以下要求:
(1)初始化程序使LCD显示“1”表示电梯处在一楼,等待人进入电梯;
(2)主程序主要包括:
①判断电梯选择去哪一层,根据判断情况来控制电梯运行,相应的指示灯显示运行方向,到达目标楼层后相应的数码管显示电梯所在楼层;
②电梯在运行过程中要不断的扫描键盘,从而来判断各楼层是否有其他呼叫请求;
③设置电梯启动、停止及紧急功能按键;
④实时显示电梯所在位置及运行状态(上行/下行);
⑤紧急按钮是用于电梯出现意外时,用来报警求救;
图4-1  主程序流程图
电梯的整个软件设计包括一下几部分:电梯逻辑控制模块、电梯运行模块、键盘模块、楼层显示模块。

电梯的整个软件设计包括一下几部分:电梯逻辑控制模块、电梯运行模块、键盘模块、楼层显示模块。
4.3  按键方式
键盘是独立按键,采用的是查询方式,即外接独立按键的时候,是按键的一端接地,另一端与I/O引脚相连,当按键按下的时候,引脚输入的是低电平,而按键未按下的时候,引脚输入的是高电平[6]。利用C语言编程时只要用检测高低电平来判断是否有按键按下就可以了。其程序源代码见附录1。
4.4  显示系统
    显示屏12864显示全部
4.5  电机演示系统
采用步进电机作为本设计的执行元件,步进电机在定位性能方面十分优越。步进电机和普通电机的区别主要就在于其脉冲驱动的形式,步进电机不需要A/D 转换,能够直接将数字脉冲信号转化为角位移。常用的步进电机每转一步,角度转1.8°,在应用中,步进电机可以同时完成两个工作,其一是传递转矩,其二是传递信息,在本设计中作为传递信息用,步进电机使用的是28BYJ-5V。电梯运行前按启动按钮,步进电机8个节拍循环旋转,电梯每上升或下降一层电机顺时针或者逆时针转动40度。
4.6软件编译调试
在软件调试中,采用keil仿真软件进行程序调试。首先分别调试各个功能程序,再对整个程序进行调试,以便修改错误码。具体的调试方法如下:
首先在keil软件中选择AT89C52作为CPU,因为该软件中没有STC89C52RC,但是基本功能和之差不多,将晶振频率设置为11.0592MHZ,然后新建一个文件,将各个功能程序录入,先检查程序有无明显错误,保存过后编译程序,如果有错误时就根据提示加以修改,当各个功能程序编译完成后,再对整个程序全速执行,查看程序有哪些地方出现错误,对应错误的提示来调整程序,纠正错误直到程序正确无误,调试结束后软件调试界面如下图5-1所示:
        图5-1  软件调试界面
4.7  实物制作及系统测试
   在原理图及原材料确定好的基础上直接进行实物制作,进行各部件在电路板上的组配和焊接。

                            

图3-9  矩阵按键实物图

            

图4-1  报警电路实物图

         

图4-2   电机驱动电路实物图


对系统进行测试,首先启动电机运行,电梯位于一楼,按下二楼按键,上行灯点亮,步进电机转动,到达目标楼层停下,此时数码管显示当前楼层。然后再一次按下三、四楼的按键,电梯先后在三楼、四楼停下。最后再按下二楼按钮,电机逆时针旋转停在二楼,最后在一楼停下。而且各指示灯和数码管显示都正常。
通过上电测试,电梯在上升或者下降过程中先响应上升或者下降楼层的信号,并对最近楼层呼叫有优先级的响应。系统具有方向优先、距离优先的功能,基本模拟了实际电梯运行,完成题目设计要求。
4.8 元器件清单

序号

名称

型号及规格

数量

1

单片机

STM32

1

2

步进电机驱动模块

SBT0811

1

3

发光二极管

LED

1

4

按键

微动

14

5

屏幕显示

12864

1

8

电阻

470

3

10

步进电机

28BYJ-48-5V

1

11

电解电容

105℃-50V-10uF±20%

1

12

蜂鸣器

电磁式

1




5、总结
经过这一段时间选择和设计,完成了一个具有基本功能的电梯控制系统。系统是一个四层楼电梯控制系统。它能实现一个电梯具有的基本功能,包括:电梯上下运行功能,电梯选层功能,楼层显示功能,电梯的启动和停止及紧急报警功能,智能初始化功能。并且加入了自我设计的电机模块,不仅基本达到了设计要求和目的,同时也不乏自我的创新设计。
通过这次设计,虽然遇到的困难重重,但是受益匪浅,对单片机在实物中应用的能力有一个很好的了解,这种开放式的设计,我从中学到的不仅仅是所设计方面的知识,更重要的是学习方法以及资料查找的技巧,学会了利用身边现有的资源和人缘,作为我去更好学习的一个阶梯,虽然这次设计时间并不长,但是我发现我们对自主学习能力有所提高。学无止境,在今后的学习生活中,我将把学到的知识灵活的运用到学习、工作和生活当中。而且在设计过程中,不仅是在学习新知识这一块上有了很大的提高,同时我的意志力也得到了很好的锻炼。只有你坚持,努力了,才能让自己学到和收获更多,才能更好的适应这个社会。


  1. module top_traffic(
  2.     input                  sys_clk   ,    //系统时钟信号
  3.     input                  sys_rst_n ,    //系统复位信号

  4.     output       [3:0]     sel       ,    //数码管位选信号
  5.     output       [7:0]     seg_led   ,    //数码管段选信号
  6.     output                   [5:0]                 led            //LED使能信号
  7. );

  8. //wire define   
  9. wire   [5:0]  ew_time;                    //东西方向状态剩余时间数据
  10. wire   [5:0]  sn_time;                    //南北方向状态剩余时间数据
  11. wire   [1:0]  state  ;                    //交通灯的状态,用于控制LED灯的点亮

  12. //*****************************************************
  13. //**                    main code                     
  14. //*****************************************************
  15. //交通灯控制模块   
  16. traffic_light u0_traffic_light(
  17.     .sys_clk                (sys_clk),  
  18.     .sys_rst_n              (sys_rst_n),     
  19.     .ew_time                (ew_time),
  20.     .sn_time                (sn_time),
  21.     .state                  (state)
  22. );

  23. //数码管显示模块            
  24. seg_led    u1_seg_led(
  25.     .sys_clk                (sys_clk)  ,
  26.     .sys_rst_n              (sys_rst_n),
  27.     .ew_time                (ew_time),
  28.     .sn_time                (sn_time),
  29.     .en                     (1'b1),  
  30.     .sel                    (sel),
  31.     .seg_led                (seg_led)
  32. );

  33. //led灯控制模块
  34. led   u2_led(
  35.     .sys_clk                (sys_clk  ),
  36.     .sys_rst_n              (sys_rst_n),
  37.     .state                  (state    ),
  38.     .led                    (led      )
  39. );

  40. endmodule
  41. module  traffic_light(
  42.     //input
  43.     input               sys_clk   ,        //系统时钟
  44.     input               sys_rst_n ,        //系统复位

  45.     output  reg  [1:0]  state     ,        //交通灯的状态,用于控制LED灯的点亮
  46.     output  reg  [5:0]  ew_time   ,        //交通灯东西向数码管要显示的时间数据
  47.     output  reg  [5:0]  sn_time            //交通灯南北向数码管要显示的时间数据
  48.     );

  49. //parameter define
  50. parameter  TIME_LED_Y    = 5'd3;              //黄灯发光的时间
  51. parameter  TIME_LED_R    = 5'd30;             //红灯发光的时间
  52. parameter  TIME_LED_G    = 5'd27;             //绿灯发光的时间
  53. parameter  WIDTH         = 25_000_000;     //产生频率为1hz的时钟

  54. //reg define
  55. reg    [4:0]     time_cnt;                 //产生数码管显示时间的计数器   
  56. reg    [24:0]    clk_cnt;                  //用于产生clk_1hz的计数器
  57. reg              clk_1hz;                  //1hz时钟

  58. //*****************************************************
  59. //**                    main code                     
  60. //*****************************************************
  61. //计数周期为0.5s的计数器
  62. always @ (posedge sys_clk or negedge sys_rst_n)begin
  63.     if(!sys_rst_n)
  64.         clk_cnt <= 25'b0;
  65.     else if (clk_cnt < WIDTH - 1'b1)
  66.         clk_cnt <= clk_cnt + 1'b1;
  67.     else
  68.         clk_cnt <= 25'b0;
  69. end

  70. //产生频率为1hz的时钟
  71. always @(posedge sys_clk or negedge sys_rst_n)begin
  72.     if(!sys_rst_n)
  73.         clk_1hz <= 1'b0;
  74.     else  if(clk_cnt == WIDTH - 1'b1)
  75.         clk_1hz <= ~ clk_1hz;
  76.     else
  77.         clk_1hz <=  clk_1hz;
  78. end

  79. //切换交通信号灯工作的4个状态,并产生数码管要显示的时间数据
  80. always @(posedge clk_1hz or negedge sys_rst_n)begin
  81.     if(!sys_rst_n)begin      
  82.         state <= 2'd0;
  83.         time_cnt <= TIME_LED_G ;            //状态1持续的时间
  84.     end
  85.     else begin
  86.         case (state)
  87.             2'b0:  begin                    //状态1
  88.                 ew_time <= time_cnt + TIME_LED_Y - 1'b1;//东西方向数码管要显示的时间数据
  89.                sn_time <= time_cnt - 1'b1;             //南北方向数码管要显示的时间数据
  90.                 if (time_cnt > 1)begin      //time_cnt等于1的时候切换状态
  91.                     time_cnt <= time_cnt - 1'b1;
  92.                     state <= state;
  93.                 end
  94.                 else begin
  95.                     time_cnt <= TIME_LED_Y; //状态2持续的时间
  96.                     state <= 2'b01;         //切换到状态2
  97.                 end
  98.             end
  99.             2'b01:  begin                   //状态2
  100.                 ew_time <= time_cnt  - 1'b1;
  101.                 sn_time <= time_cnt  - 1'b1;
  102.                 if (time_cnt > 1)begin
  103.                     time_cnt <= time_cnt - 1'b1;
  104.                     state <= state;
  105.                 end
  106.                 else begin
  107.                     time_cnt <= TIME_LED_G; //状态3持续的时间
  108.                     state <= 2'b10;         //切换到状态3
  109.                 end
  110.             end
  111.             2'b10:  begin                   //状态3
  112.                 ew_time <= time_cnt  - 1'b1;
  113.                 sn_time <= time_cnt + TIME_LED_Y - 1'b1;
  114.                 if (time_cnt > 1)begin
  115.                     time_cnt <= time_cnt - 1'b1;
  116.                     state <= state;
  117.                 end
  118.                 else begin
  119.                     time_cnt <= TIME_LED_Y; //状态4持续的时间
  120.                     state <= 2'b11;         //切换到转态4
  121.                 end
  122.             end
  123.             2'b11:  begin                   //状态4
  124.                 ew_time <= time_cnt  - 1'b1;
  125.                 sn_time <= time_cnt  - 1'b1;
  126.                 if (time_cnt > 1)begin
  127.                     time_cnt <= time_cnt - 1'b1;
  128.                     state <= state;
  129.                 end
  130.                 else begin
  131.                     time_cnt <= TIME_LED_G;
  132.                     state <= 2'b0;          //切换到状态1
  133.                 end
  134.             end        
  135.             default: begin
  136.                 state <= 2'b0;
  137.                 time_cnt <= TIME_LED_G;
  138.             end
  139.         endcase
  140.     end
  141. end               

  142. endmodule
  143.             
  144. module seg_led(
  145.     input                  sys_clk     ,     //系统时钟
  146.     input                  sys_rst_n   ,     //系统复位
  147.     input        [5:0]     ew_time     ,     //东西方向数码管要显示的数值
  148.     input        [5:0]     sn_time     ,     //南北方向数码管要显示数值
  149.     input                  en          ,     //数码管使能信号                                                            
  150.     output  reg  [3:0]     sel         ,     //数码管位选信号
  151.     output  reg  [7:0]     seg_led           //数码管段选信号,包含小数点
  152. );

  153. //parameter define
  154. parameter  WIDTH = 50_000;                   //计数1ms的计数深度

  155. //reg define
  156. reg    [15:0]             cnt_1ms;           //计数1ms的计数器
  157. reg    [1:0]              cnt_state;         //用于切换要点亮数码管
  158. reg    [5:0]              num;               //数码管要显示的数据

  159. //wire define
  160. wire   [5:0]              data_ew_0;         //东西方向数码管的十位
  161. wire   [5:0]              data_ew_1;         //东西方向数码管的各位
  162. wire   [5:0]              data_sn_0;         //南北方向数码管的十位
  163. wire   [5:0]              data_sn_1;         //南北方向数码管的各位

  164. //*****************************************************
  165. //**                    main code                     
  166. //*****************************************************
  167. assign  data_ew_0   = ew_time / 4'd10;          //取出东西向时间数据的十位
  168. assign  data_ew_1   = ew_time % 4'd10;          //取出东西向时间数据的个位
  169. assign  data_sn_0   = sn_time / 4'd10;          //取出南北向时间数据的十位
  170. assign  data_sn_1   = sn_time % 4'd10;          //取出南北向时间数据的个位

  171. //计数1ms
  172. always @ (posedge sys_clk or negedge sys_rst_n) begin
  173.     if (!sys_rst_n)
  174.         cnt_1ms <= 15'b0;
  175.     else if (cnt_1ms < WIDTH - 1'b1)
  176.         cnt_1ms <= cnt_1ms + 1'b1;
  177.     else
  178.         cnt_1ms <= 15'b0;
  179. end

  180. //计数器,用来切换数码管点亮的4个状态
  181. always @ (posedge sys_clk or negedge sys_rst_n) begin
  182.     if (!sys_rst_n)
  183.         cnt_state <= 2'd0;
  184.     else  if (cnt_1ms == WIDTH - 1'b1)
  185.         cnt_state <= cnt_state + 1'b1;
  186.     else
  187.         cnt_state <= cnt_state;
  188. end

  189. //先显示东西方向数码管的十位,然后是个位。再显示南北方向数码管的十位,然后个位
  190. always @ (posedge sys_clk or negedge sys_rst_n) begin
  191.     if(!sys_rst_n) begin
  192.         sel  <= 4'b1111;
  193.         num  <= 4'b0;
  194.     end
  195.     else if(en) begin      
  196.         case (cnt_state)
  197.             3'd0 : begin   
  198.                 sel <= 4'b1110;              //驱动东西方向数码管的十位
  199.                 num <= data_ew_0;
  200.             end      
  201.             3'd1 : begin   
  202.                 sel <= 4'b1101;              //驱动东西方向数码管的个位
  203.                 num <= data_ew_1;
  204.             end
  205.             3'd2 : begin
  206.                 sel <= 4'b1011;              //驱动南北方向数码管的十位
  207.                 num  <= data_sn_0;
  208.             end
  209.             3'd3 : begin
  210.                 sel <= 4'b0111;              //驱动南北方向数码管的个位
  211.                 num  <= data_sn_1 ;   
  212.             end
  213.             default : begin   
  214.                 sel <= 4'b1111;                    
  215.                 num <= 4'b0;
  216.             end
  217.         endcase
  218.     end
  219.     else  begin
  220.           sel <= 4'b1111;
  221.           num <= 4'b0;   
  222.     end
  223. end

  224. //数码管要显示的数值所对应的段选信号     
  225. always @ (posedge sys_clk or negedge sys_rst_n) begin
  226.     if (!sys_rst_n)
  227.         seg_led <= 8'b0;
  228.     else begin
  229.         case (num)            
  230.             4'd0 :     seg_led <= 8'b1100_0000;                                                      
  231.             4'd1 :     seg_led <= 8'b1111_1001;                           
  232.             4'd2 :     seg_led <= 8'b1010_0100;                           
  233.             4'd3 :     seg_led <= 8'b1011_0000;                           
  234.             4'd4 :     seg_led <= 8'b1001_1001;                           
  235.             4'd5 :     seg_led <= 8'b1001_0010;                           
  236.             4'd6 :     seg_led <= 8'b1000_0010;                           
  237.             4'd7 :     seg_led <= 8'b1111_1000;     
  238.             4'd8 :     seg_led <= 8'b1000_0000;     
  239.             4'd9 :     seg_led <= 8'b1001_0000;   
  240.             default :  seg_led <= 8'b1100_0000;
  241.         endcase
  242.     end
  243. end

  244. Endmodule

  245. module led (
  246.     input              sys_clk   ,       //系统时钟
  247.     input              sys_rst_n ,       //系统复位
  248.     input       [1:0]  state     ,       //交通灯的状态
  249.     output reg  [5:0]  led               //红黄绿LED灯发光使能
  250. );

  251. //parameter define
  252. parameter  TWINKLE_CNT = 25_000_000;     //让黄灯闪烁的计数次数

  253. //reg define
  254. reg    [24:0]     cnt;                   //让黄灯产生闪烁效果的计数器

  255. //计数时间为0.2s的计数器,用于让黄灯闪烁                                                            
  256. always @(posedge sys_clk or negedge sys_rst_n)begin                                 
  257.     if(!sys_rst_n)                                                                  
  258.         cnt <= 25'b0;                                                               
  259.     else if (cnt < TWINKLE_CNT - 1'b1)                                                                                                      
  260.         cnt <= cnt + 1'b1;                                                                                                                                                                                                                                                            
  261.     else                                                                           
  262.         cnt <= 25'b0;                                                               
  263. end                                                                                 

  264. //在交通灯的四个状态里,使相应的led灯发光                                                            
  265. always @(posedge sys_clk or negedge sys_rst_n)begin                                 
  266.     if(!sys_rst_n)                                                                  
  267.         led <= 6'b100100;                                                           
  268.     else begin                                                                     
  269.         case(state)                                                                  
  270.             2'b00:led<=6'b100010;        //led寄存器从高到低分别驱动:东西向                       
  271.                                          //红绿黄灯,南北向红绿黄灯                                          
  272.             2'b01: begin                                                            
  273.                 led[5:1]<=5'b10000;                                                
  274.                 if(cnt == TWINKLE_CNT - 1'b1)  //计数满0.2秒让黄灯的亮灭状况切换一次
  275.                                                //产生闪烁的效果                                
  276.                     led[0] <= ~led[0];                                             
  277.                 else                                                               
  278.                     led[0] <= led[0];                                               
  279.             end                                                                     
  280.             2'b10:led<=6'b010100;                                                   
  281.             2'b11: begin                                                            
  282.                 led[5:4]<=2'b00;                                                   
  283.                 led[2:0]<=3'b100;                                                   
  284.                 if(cnt == TWINKLE_CNT - 1'b1)                                          
  285.                     led[3] <= ~led[3];                                             
  286.                 else                                                               
  287.                     led[3] <= led[3];                                             
  288.             end                                                                     
  289.             default:led<=6'b100100;                                                
  290.         endcase                                                                     
  291.     end                                                                             
  292. end

  293. endmodule  
复制代码

完整的Word格式文档51黑下载地址:
基于FPGA的交通灯设计.7z (6.47 MB, 下载次数: 79)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:703622 发表于 2020-4-25 20:58 | 只看该作者
好资料谢谢分享
回复

使用道具 举报

板凳
ID:306846 发表于 2020-11-11 12:41 | 只看该作者
请问这程序是用啥软件打开的啊,下载了打不开啊,需要仿真测试
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表