差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
9._呼吸灯 [2017/03/22 23:47]
zhijun
9._呼吸灯 [2019/09/06 11:56] (当前版本)
gongyu
行 1: 行 1:
-=====呼吸灯=====+#### 呼吸灯 
 + 
 +---
  
 本节,我们将通过脉宽调制技术来实现“呼吸灯”,实现LED的亮度由最暗逐渐增加到最亮,再逐渐变暗的过程。 本节,我们将通过脉宽调制技术来实现“呼吸灯”,实现LED的亮度由最暗逐渐增加到最亮,再逐渐变暗的过程。
 脉冲宽度调制(PWM:​Pulse Width Modulation),简称脉宽调制。它是利用微控制器的数字输出调制实现,是对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等众多领域。 脉冲宽度调制(PWM:​Pulse Width Modulation),简称脉宽调制。它是利用微控制器的数字输出调制实现,是对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等众多领域。
 +
 \\ \\
-====硬件说明==== + 
--------+####硬件说明 
 + 
 +---
 呼吸灯的设计较为简单,我们使用12MHz的系统时钟作为高频信号做分频处理,调整占空比实现PWM,通过LED灯LD1指示输出状态。 呼吸灯的设计较为简单,我们使用12MHz的系统时钟作为高频信号做分频处理,调整占空比实现PWM,通过LED灯LD1指示输出状态。
  
行 18: 行 23:
  
 结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s 结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s
 +{{ :​呼吸灯程序设计.jpg |呼吸灯程序设计}}
  
-\\   +呼吸灯设计要求呼吸周期为2s是说LED灯从最亮状态开始秒时间内逐渐第二秒的间内再逐渐变亮依次进行
-1,模块化设计:在之前实验中我们做了[[3. 3-8译码器|3-8译码器]]和[[5. 时钟分频|时钟分频]]如果把这两个结合起来,我们能搭建一个自动操作的流水LED显示。框图如下: +
-\\ +
-{{ ::​flashled.png |}} +
-\\   +
-2,循环赋值:这是一种很简洁实现流水灯效果逻辑就是定义个8位的在每个钟上升沿将最低位赋值给最高位其他位右移一位,这就实现了循环赋值。这8位输出到LED就能实现流水灯 +
-\\   +
  
-====Verilog代码==== +设计中需要两个计器cnt1和cnt2,cnt1随系统时钟同步数(系统时钟上升沿时cnt1自加1)范围为0~Tcnt2随cnt1周期同步数(cnt1等于T时,cnt2自加1)范围是0~T,样每次cnt1在0~T的计数时,cnt2为一个固定值,相邻cnt1计数周期对应的cnt2的值逐渐增大,我们将cnt1数0~T时间作为脉冲周期cnt2的值作为脉冲宽度,则占空比 = cnt2/​T,​占空比从0%100%的时间 = cnt2*cnt1 = T^2 = 1s = 12M系统时钟,T = 2400,我们定义CNT_NUM = 2400作为两个计数器的计数最大值
------- +
-模块化设计是用硬件描述语言进行字电路设的精髓代码可重复利用。而且模块化使得程序的结构很清晰。我们首先看看流水灯的模块化设。利用了之前3-8译码器和分频器你需要把这两个程序也拷贝工程 +
-<code verilog>+
  
-// ******************************************************************** +{{ ::呼吸灯pwm原理.jpg |PWM呼吸原理}}
-// >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ +
-// ******************************************************************** +
-// File name    ​flashled.v +
-// Module name  ​flashled +
-// Author ​      : STEP +
-// Description ​ : segment initial +
-// Web          : www.stepfpga.com +
-//  +
-// -------------------------------------------------------------------- +
-// Code Revision History :  +
-// -------------------------------------------------------------------- +
-// Version: ​|Mod. Date:   ​|Changes Made: +
-// V1.0     ​|2017/​03/​02 ​  ​|Initial ver +
-// -------------------------------------------------------------------- +
-// Module Function:​流水的模块化设计+
  
-module flashled (clk,​rst,​led);​+####​Verilog代码
  
- input clk,​rst;​  +---
- output [7:0] led;  +
- +
- +
-        reg   [2:0] cnt ;                               //​定义了一个3位的计数器,输出可以作为3-8译码器的输入 +
-         +
-        wire clk1h; ​                                    //​定义一个中间变量,表示分频得到的时钟,用作计数器的触发 ​        +
- +
-        //​例化module decode38,相当于调用 +
-        decode38 u1 (                                    +
- .sw(cnt), ​                      //​例化的输入端口连接到cnt,输出端口连接到led ​  +
- .led(led) +
- ); +
-  +
-        //​例化分频器模块,产生一个1Hz时钟信号  +
-        divide #​(.WIDTH(32),​.N(12000000)) u2 (         //​传递参数 +
- .clk(clk),​ +
- .rst_n(rst), ​                  //​例化的端口信号都连接到定义好的信号 +
- .clkout(clk1h) +
- );                              +
-  +
-        //​1Hz时钟上升沿触发计数器,循环计数  +
-        always @(posedge clk1h or negedge rst) +
-      if (!rst) +
- cnt <= 0; +
-      ​else +
- cnt <= cnt +1; +
-  +
-        endmodule +
-         +
- </​code>​ +
-\\ +
-\\ +
- +
-模块化设计结构清晰,verilog语言是很灵活的。对于流水灯还有一种很简洁的实现方法。+
  
 <code verilog> <code verilog>
行 92: 行 40:
 // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​
 // ******************************************************************** // ********************************************************************
-// File name    : flashled.v +// File name    : breath_led.v 
-// Module name  : flashled+// Module name  : breath_led
 // Author ​      : STEP // Author ​      : STEP
-// Description ​ : segment initial+// Description ​ : 
 // Web          : www.stepfpga.com // Web          : www.stepfpga.com
 //  // 
行 104: 行 52:
 // V1.0     ​|2017/​03/​02 ​  ​|Initial ver // V1.0     ​|2017/​03/​02 ​  ​|Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module Function:流水灯的模块化设+// Module Function:呼吸 
 +module breath_led(clk,​rst,​led);​ 
 +  
 + input clk;             //​系统时钟输入 
 + input rst;             //​复位输出 
 + output led;            //​led输出 
 +  
 + reg [24:0] cnt1;       //​计数器1 
 + reg [24:0] cnt2;       //​计数器2 
 + reg flag;              //​呼吸灯变亮和变暗标志位 
 +  
 + parameter ​  ​CNT_NUM = 2400; //数器的最大值 period = (2400^2)*2 = 24000000 = 2s 
 + //​产生计数器cnt1 
 + always@(posedge clk or negedge rst) begin  
 + if(!rst) begin 
 + cnt1<​=13'​d0;​ 
 + end  
 +        else if(cnt1>​=CNT_NUM-1)  
 + cnt1<​=1'​b0;​ 
 +      else  
 +                cnt1<​=cnt1+1'​b1;​  
 + end 
 +  
 + //​产生计数器cnt2 
 + always@(posedge clk or negedge rst) begin  
 + if(!rst) begin 
 + cnt2<​=13'​d0;​ 
 + flag<​=1'​b0;​ 
 + end  
 +        else if(cnt1==CNT_NUM-1) begin //​当计数器1计满时计数器2开始计数加一或减一 
 + if(!flag) begin            //​当标志位为0时计数器2递增计数,表示呼吸灯效果由暗变亮 
 + if(cnt2>​=CNT_NUM-1) ​   //​计数器2计满时,表示亮度已最大,标志位变高,之后计数器2开始递减 
 + flag<​=1'​b1;​ 
 + else 
 + cnt2<​=cnt2+1'​b1;​ 
 + end 
 + else begin 
 + if(cnt2<​=0) ​     //​当标志位为高时计数器2递减计数 
 + flag<​=1'​b0;​  ​  //​计数器2级到0,表示亮度已最小,标志位变低,之后计数器2开始递增 
 + else  
 + cnt2<​=cnt2-1'​b1;​ 
 + end  
 +  
 + end 
 + else  
 + cnt2<​=cnt2; ​               //​计数器1在计数过程中计数器2保持不变 
 + end 
 +  
 + //​比较计数器1和计数器2的值产生自动调整占空比输出的信号,输出到led产生呼吸灯效果 
 + assign led = (cnt1<​cnt2)?​1'​b0:​1'​b1;​ 
 +  
 +endmodule
  
-module flashled (clk,​rst,​led);​ 
  
- input clk,​rst;​  +</code>
- output [7:0] led;  +
-         +
-        wire clk1h; ​                                    //​定义一个中间变量,表示分频得到的时钟,用作计数器的触发 ​       ​+
  
-        //​例化分频器模块,产生一个1Hz时钟信号  +####引脚分配
-        divide ​#(.WIDTH(32),​.N(12000000)) u2 (         //​传递参数 +
- .clk(clk),​ +
- .rst_n(rst), ​                  //​例化的端口信号都连接到定义好的信号 +
- .clkout(clk1h) +
- );                              +
-  +
-        //​1Hz时钟上升沿触发循环赋值  +
-        always@(posedge clk1h or negedge rst) +
- begin +
- if(!rst) +
- led <= 8'​b11111110; ​           // <​=为非阻塞赋值 +
- else  +
- led <= {led[0],​led[7:​1]}; ​     //​当时钟上升沿来一次,执行一次赋值,赋值内容是led[0]与led[7:​1]重新拼接成8位赋给led,相当于循环右移 +
- end  +
-         +
- </​code> ​  +
-\\   +
-====引脚分配==== +
------- +
-按照下面表格定义输入输出信号 +
-\\ +
-^信号 ​           ^引脚 ​           ^信号 ​             ^引脚 ​   ^    +
-|clk   ​|C1 ​             |led[3] ​   |M11     ^ +
-|rst   ​|L14 ​             |led[4] ​   |P11     ^ +
-|led[0] ​  ​|N13 ​             |led[5] ​   |N10    ^ +
-|led[1] ​  ​|M12 ​            ​|led[6] ​   |N9     ^ +
-|led[2] ​  ​|P12 ​            ​|led[7] ​   |p9     ^  +
-\\ +
-\\+
  
-置好以后编译载程序。可以调整例化分频器时传递的参数来调整流水灯的速度。 +--- 
-\\+ 
 +引脚分: 
 + 
 +^ 管脚名称 | clk| rst| led| 
 +^ FPGA管脚 | C1    | L14     | N13       |
  
-====小结==== 
------- 
-掌握了verilog里面例化module的用法,采用模块化设计程序。模块化设计是非常重要的FPGA设计思想。在下一节我们会学习按键的另外用法[[7. 按键消抖|按键消抖]]。 
  
 +####小结
  
 +---
  
 +脉宽调制是一种值得广大工程师在许多应用设计中使用的有效技术,你也可以根据本节介绍的流水灯程序,实现RGB三色灯的呼吸。在下一小节我们会学习状态机的使用方法:[[10. 交通灯|交通灯的设计]]。