PWM控制灯亮暗的verilog实现

PWM的全称为Pulse-Width Modulation(脉冲宽度调制),即调节脉冲的占空比。当输出的脉冲频率一定时,输出的脉冲占空比越大,相当于输出的有效电平越大,这样也就简单实现了由FPGA来控制模拟量。

设计原理框图:

按键消抖,首先采用状态机实现,用状态机做键盘消抖,很好用,不必等待延时,当检测到有按键按下或弹起时能发出相应的键盘消息。设置状态机有 4中状态,A0,A1,A2,A3状态转换图如下:

检测这几个管脚是否为低电平,来判断按键是否被按下

AO: 初始时位于A0状态,当扫描发现有按键按下时,转入到A1状态。当处于A1状态时,当扫描有按键按下并且键值等于A1状态下的键值时,转入到A2状态,否则转入A0状态。当处于A2状态时,当扫描发现有按键按下并且键值等于A3状态下的键值时,转入到A3状态,否则转入A0状态,当处于A3状态时,当扫描发现无键按下时,转入A0状态,同时发出键弹起消息或弹起键的键值入队。

always @(posedge clk)
 begin
    case (state)
     s0:
      begin
       key_out<=1‘b1;
       if(key==1‘b0)
          state<=s1;
       else
          state<=s0;
      end
     s1:
      begin
       if(key==1‘b0)
         state<=s2;
       else
         state<=s0;
       end
     s2:
      begin
       if(key==1‘b0)
         state<=s3;
       else
         state<=s0;
       end
     s3:
       begin
        if(key==1‘b0)
         begin
         key_out<=1‘b0;
         state<=s3;
         end
        else
         begin
         key_out<=1‘b1;
         state<=s0;
         end
       end
     default:
         state<=s0;
    endcase
 end

计数器按键消抖:1.检测管教电平是否拉低;2.若检测到低电平,启动计数器,延时20ms左右的时间;3.再次检测管脚是否低电平;4.若还是低电平,确定按键被按下,输出控制信号。在此例程中,最终LED控制实现的功能:按键 Key2 连接到 rst_n 信号,key1 连接到 key1 信号。最终的结果是:当按下 key2 键的时候,系统复位,只有一个 LED 点亮。松开 key2,没有键按下的时候, 四个 LED 交替两灭, 流水灯操作。 当按下 key1 键时, 执行下面语句 else if(key_low) led_r <= 4‘b0;四个灯全亮。

module led (
clk,rst_n,key1,
led
);
input clk;                  //时钟信号输入
input rst_n;               //复位信号输入
input key1;               //按键按下
output[3:0] led;         //LED灯点亮
//------------------------键盘消抖程序---------------------------------------------------
reg reg0_key;
reg reg1_key;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
reg0_key <= 1‘b1;     //将1‘b1赋值给reg0_key寄存器
reg1_key <= 1‘b1;     //将1’b1赋值给reg1_key寄存器
end
else begin
reg0_key <= key1;         //将按键输入赋值给reg0_key
reg1_key <= reg0_key; //根据非阻塞赋值的原理,reg1_key 存储的值是
reg0_key 上一个时钟的值
end
end
//当寄存器 key1 由 1 变为 0 时,led_an 的值变为高,维持一个时钟周期
wire key_an;
assign key_an = reg1_key & ( ~reg0_key);   //用来检测下降沿的典型程序
//---------------------------------------------------------------------------
reg[19:0] cnt_key; //计数寄存器                //检测完下降沿,启动计时器,延时20ms
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
cnt_key <= 20‘d0;  //异步复位
else if(key_an)
cnt_key <=20‘d0;
else
cnt_key <= cnt_key + 1‘b1;
end
reg reg_low;
reg reg1_low;
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
reg_low <= 1‘b1;
end
else if(cnt_key == 20‘hfffff)
begin
reg_low <= key1; //cnt == 20‘hfffff,20ms
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
reg1_low <= 1‘b1;
else
reg1_low <= reg_low;
end
//---------------------------------------------------------------------------
//当寄存器 reg_low 由 1 变为 0 时,key_low 的值变为高,维持一个时钟周期
wire key_low = reg1_low & ( ~reg_low);
//===============LED 控制==================================
reg[21:0] cnt; //
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 22‘b0;
else
cnt <= cnt + 1‘b1;
end
reg enable_r;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
enable_r <= 1‘b0;
else
if (cnt == 22‘h3fffff) enable_r <= 1‘b1;
else
enable_r <= 1‘b0;
end
wire enable;
assign enable = enable_r;
reg[3:0] led_r;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
led_r <= 4‘b0111;
else if(key_low)
led_r <= 4‘b0;
else if(enable && !key_low)
led_r <= {led_r[0],led_r[3:1]};
else ;
end
wire[3:0] led;
assign led = led_r;
endmodule

回到PWM控制灯光亮暗,通过时钟计时器的计数与脉宽的计数比较大小,去定义灯光的亮暗。当时钟计数器到达设定的数值时,如果脉宽加满则溢出清0,并在此时判断按键有无按下,若按下,则调节脉宽的宽度,来进行下一轮的占空比比较,若脉宽未满,亦将其加满。对应的程序为:

module pwm(clk,reset,key,led);
input clk,reset,key;
output led;

reg pwm_out;

reg key_out;
parameter s0=2‘b00,s1=2‘b01,s2=2‘b10,s3=2‘b11;
reg [1:0] state;

reg [31:0] clk_counter;
reg [9:0]  pwm_counter;
reg flag;
/******************按键消抖**************************/
always @(posedge clk)
 begin
    case (state)
     s0:
      begin
       key_out<=1‘b1;
       if(key==1‘b0)
          state<=s1;
       else
          state<=s0;
      end
     s1:
      begin
       if(key==1‘b0)
         state<=s2;
       else
         state<=s0;
       end
     s2:
      begin
       if(key==1‘b0)
         state<=s3;
       else
         state<=s0;
       end
     s3:
       begin
        if(key==1‘b0)
         begin
         key_out<=1‘b0;
         state<=s3;
         end
        else
         begin
         key_out<=1‘b1;
         state<=s0;
         end
       end
     default:
         state<=s0;
    endcase
 end
always @(posedge clk)
 begin
   clk_counter<=clk_counter+1‘b1;
    if (clk_counter[13:4]<pwm_counter)
        pwm_out=1;
    else
        pwm_out=0;

    if (clk_counter[15]==1‘b1)
    begin
        if (flag==1‘b1)
        begin
            flag<=1‘b0;
            if (key_out==1‘b0)
                pwm_counter<=(pwm_counter+10‘b0000000011);
            else
                pwm_counter<=pwm_counter;
        end
    end
    else
    flag<=1‘b1;
 end
assign led=pwm_out;
endmodule

最后板子亮灯,显示平均电压。

时间: 2024-10-13 02:16:29

PWM控制灯亮暗的verilog实现的相关文章

socket通信——多角度控制LED灯亮灭

今天以物联网网关(网关链接)以服务器,在多个客户端就做一个非常简单的功能:点亮或熄灭网关上的LED灯.目前想到了三种方式,分别是:TCP&UDP测试工具.自编Java客户端和Mono Android客户端.相信这会很有意思的. 1.服务器端 在使用或编写客户端之前,首先来看看服务器端代码,其专门通过串口烧进网关内部 OutputPort led = new OutputPort((Cpu.Pin)GPIO_NAMES.PF8, false); Socket sc; Socket ss = new

四、按键控制LED灯亮灭

材料: 1.SAGOO UNO 1块: 2.按键模块 1块: 3.杜邦线若干. 步骤: 1.按照下图连接按键模块和UNO: SAGOO UNO引脚                                      按键模块引脚 3V3  <------------------------------------>    V(电源) GND <------------------------------------>    G(电源) Pin2  <----------

[ZigBee] 3、ZigBee基础实验——GPIO输出控制实验-控制Led亮灭

1.CC2530的IO口概述 CC2530芯片有21 个数字输入/输出引脚,可以配置为通用数字I/O 或外设I/O 信号,配置为连接到ADC.定时器或USART外设.这些I/O 口的用途可以通过一系列寄存器配置,由用户软件加以实现. I/O 端口具备如下重要特性:    ?? 21 个数字I/O 引脚 ?? 可以配置为通用I/O 或外部设备I/O ?? 输入口具备上拉或下拉能力 ?? 具有外部中断能力. 21 个I/O 引脚都可以用作于外部中断源输入口.因此如果需要外部设备可以产生中断.外部中断

通过linux命令来控制板上GP_LED灯亮灭

通过linux命令来控制板上GP_LED灯亮灭 下图是在某网站找到的,这里我们可以看到GP_LED 是跟GPIO3相连.至于GPIO13,在此图上看,跟GP_LED没有啥关系,但为什么在blink草案中,却能控制GP_LED,这个留在下一帖.这里主要是通过对GPIO3的控制来实现GP_LED的亮灭. 下图是从开机到控制GP_LED亮灭的过程. 1.进入gpio的目录 2.通过ls指令可以看到在gpio目录下各个gpio口,这里找到gpio3 3.进入gpio3的目录 4.cat directio

阅读笔记之《你的灯亮着吗》第三、四章

三.什么是真正的问题? 一家计算机生产商开发的新型打印机打印速度快,但精准度却非常不理想.这个工作组里最年轻的工程师丹研制出一种方法:改变下面显示的铝条,上面嵌着小针,可以很精确地在指定的点上扎出小洞来.丹的老板非常高兴,却在无意间被小针扎到了.也就是说,丹解决了一个问题,但这个解决方法又带来了新的问题.我们永远都不能消灭问题,但我们可以通过将产生的问题的影响变小来优化这个解决方法.即把问题放在“别人家的后院儿里”.这种技巧叫做转嫁问题.无疑是一种比较有效的方式.而后,作者又接连举出了几个实例来

你的灯亮着吗--随笔1

<你的灯亮着吗>是著名思想家温伯格的一本定义分析和解决问题的书籍.问题解决的第一步应该是描述问题.问题是你期望和和你体验间的差别,要分析和解决问题时候首先需要搞清楚什么是真正的问题,问题从哪里来是谁的问题等内容.在工作和生活中常犯的毛病是扭曲问题定义,自己人为的去解释和翻译问题从而导致把问题的解决方法做为问题的定义. 从而导致后续一连串的错误. 我认为本书的一个重要的点就是告诉大家如何去正确的认识问题,去定义一个问题.

《你的灯亮着吗》第五篇、第六篇总结

第五篇讲的是问题是从哪儿来的?由一个叫珍妮特去波兰拜访她的祖母在旅途中遇到的麻烦引出主题.一开始她把问题推到“官僚主义”上,她感觉这似乎是最恰当的.但是最后她发现她十分倾向于把整件事归咎于“官僚主义”,之后她提出了一个至关重要的问题:问题是从哪儿来的?从这点出发,她成功找到乐各种备选答案.后来,珍妮特想这个问题的根源也许是她自己.她开始以正常的心态面对曾被她称作灰脸先生的人,他们顺利的交谈,最后事情的到了解决.一切都正常的进行着,一旦你确定问题真正从哪来,尤其是因为问题的根源常常在你自己身上.

8_陀螺仪MPU6050和PWM控制在STM32F4-Discovery开发板上的实现

很早以前就把圆点博士的程序从STM32F103移植到STM32F4-Discovery(STM32F407),battery,陀螺仪和PWM电机控制的程序都已经测试完毕,运行有一段时间,正常.下面展示几张图片,都是用杜邦线连接起来的,陀螺仪,串口等外设,此外还有nRF24L01,不过nRF24L01的程序读写寄存器可以了,没有尝试过与别的nRF24L01通信.下面一张是正面照片: 下面这张是背面的连接线: 下面这张来个更清晰一些的: 下面这张是圆点博士的上位机软件: 同时我也录制了一些视频,上传

你的灯亮着么阅读笔记1

你的灯亮着么事这并不是一本关于程序员如何编程的书,而是教我们在面对问题时如何思考.解决问题,让我们在生活中变得聪明,智慧的处理问题. 第一章问题是什么.这章通过电梯的问题,告诉我们分析和解决问题时,首先要明确的定义问题.书中说到:“问题其实就是你期望的东西跟你体验的东西之间的差别”.这句话我十分赞同,这也正是软件开发中客户的需求与程序员做出软件之间的差别. 第二章这个问题什么.比利的故事告诉我们,不要把解决方案当成问题的定义..“你永远也不能肯定你有了个正确定义,但是永远不要放弃寻求它的努力“,