PWM 呼吸灯实验

这篇具有很好参考价值的文章主要介绍了PWM 呼吸灯实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PWM 呼吸灯实验

FPGA实现一个PWM模块(硬件)来控制灯的亮灭。

实验原理

PWM本质上就是一个输出脉冲的硬件,通过改变一个周期高电平(占空比)的时间来对其他的硬件进行控制,比如电机。
呼吸灯的实现利用了人眼的视觉特性,控制灯亮和暗的间隔时间就形成了对灯亮度的调节。
通过一个N比特的计数器(溢出相当于从0开始)和一个值就可以实现一个占空比可调的脉冲输出。

实验步骤

  1. 设计PWM模块
  2. 用硬件描述语言实现设计
  3. 查看硬件设计,添加管脚约束和时钟约束
  4. 本地仿真
  5. 上板验证

实验记录

  1. 设计PWM模块
信号名称 方向 说明
clk in 时钟输入
rst in 异步输入复位,高有效
period in PWM 脉宽周期(频率)控制。实际是每次计数的步进值,根据系统输入时钟可以计算出pwm输出频率
duty in 占空比,小于该值时输出低电平,否则输出高电平
pwm_out out pwm输出
  1. 用硬件描述语言实现设计
    ax_pwm.v
`timescale 1ns / 1ps
module ax_pwm
#(
    parameter N = 16
)
(
    input clk,
    input rst,
    input [N-1:0] period,
    input [N-1:0] duty,
    output pwm_out
);


reg[N-1:0] period_r;
reg[N-1:0] duty_r;
reg[N-1:0] period_cnt;
reg pwm_r;

assign pwm_out = pwm_r;

always @(posedge clk or posedge rst)
begin
    if(rst==1)
    begin
        period_r <= {N{1'b0}};
        duty_r <= {N{1'b0}};
    end
    else
    begin
        period_r <= period;
        duty_r <= duty;
    end
end
    
always @(posedge clk or posedge rst)
begin
    if(rst==1)
        period_cnt <= {N{1'b0}};
    else
        period_cnt <= period_cnt + period_r;
end

always @(posedge clk or posedge rst)
begin
    if(rst==1)
    begin
        pwm_r <= 1'b0;
    end
    else
    begin
        if(period_cnt >= duty_r)
            pwm_r <= 1'b1;
       else
            pwm_r <= 1'b0;
    end
end

endmodule

PWM测试模块

`timescale 1ns / 1ps

module pwm_test(
    input  sys_clk_p,    // 时钟是一个200MHz的差分时钟
    input  sys_clk_n,
    input  rst_n,        // 复位由一个按键来控制,按键默认状态为高,所以低复位
    output wire led          // 输出给led
);
localparam CLK_FREQ = 200 ; //200MHz,周期为 1s/200MHz = 1/200 us
localparam US_COUNT = CLK_FREQ ; //1 us counter,200个时钟周期是1us 
localparam MS_COUNT = CLK_FREQ*1000 ; //1 ms counter  1个ms的周期计数

localparam DUTY_STEP = 32'd100000 ; //duty step, 占空比调整大小,单次调整 100000/2^32 = 0.000000000232
localparam DUTY_MIN_VALUE = 32'h6fffffff ; //duty minimum value, 最小占空比 0.437
localparam DUTY_MAX_VALUE = 32'hffffffff ; //duty maximum value, 最大占空比 0.999

localparam IDLE = 0; //IDLE state 
localparam PWM_PLUS = 1; //PWM duty plus state 
localparam PWM_MINUS = 2; //PWM duty minus state 
localparam PWM_GAP = 3; //PWM duty adjustment gap

wire pwm_out; //pwm output 
reg[31:0] period; //pwm step value 
reg[31:0] duty; //duty value 
reg pwm_flag ; //duty value plus and minus flag, 0: plus; 1: minus

reg[3:0] state; 
reg[31:0] timer; //duty adjustment counter 该测试模块计数的

assign led = ~pwm_out ; //led low active

wire clk;
// 差分转单端
IBUFDS IBUFDS_inst(
    .O(clk),
    .I(sys_clk_p),
    .IB(sys_clk_n)
);

always@(posedge clk or negedge rst_n) 
begin 
    if(rst_n == 1'b0) 
    begin  // 复位,设置初始值
        period <= 32'd0; 
        timer <= 32'd0; 
        duty <= 32'd0; 
        pwm_flag <= 1'b0 ; 
        state <= IDLE; 
    end
    else 
    case(state) 
        IDLE: 
        begin 
            // N位计数器,CLK Hz的时钟(周期1/CLK s),要输出n Hz的PWM波,PWM周期为1/n s,要在一个PWM周期计数完一轮,而一个周期会计数((1/n)/(1/CLK))次
            //  2^N/((1/n)/(1/CLK)) = 2^32*n/CLK  
            //  这个地方的时钟写的50M,PWM是800Hz的,周期0.00125s。
            period <= 32'd17179; //The pwm step value, pwm 200Hz(period = 200*2^32/50000000) 
            state <= PWM_PLUS; 
            duty <= DUTY_MIN_VALUE; 
        end 
        PWM_PLUS : 
        begin 
            if (duty > DUTY_MAX_VALUE - DUTY_STEP) //if duty is bigger than DUTY MAX VALUE minus DUTY_STEP , begin to minus duty value 
            begin 
                pwm_flag <= 1'b1 ; 
                duty <= duty - DUTY_STEP ; 
            end 
            else 
            begin 
                pwm_flag <= 1'b0 ; 
                duty <= duty + DUTY_STEP ; 
            end 
            state <= PWM_GAP ; 
        end
        PWM_MINUS : 
        begin 
            if (duty < DUTY_MIN_VALUE + DUTY_STEP) //if duty is little than DUTY MIN VALUE plus duty step, begin to add duty value 
            begin 
                pwm_flag <= 1'b0 ; 
                duty <= duty + DUTY_STEP ; 
            end 
            else 
            begin 
                pwm_flag <= 1'b1 ;
                duty <= duty - DUTY_STEP ; 
            end 
            state <= PWM_GAP ; 
        end 
        PWM_GAP: 
        begin 
            if(timer >= US_COUNT*100) //adjustment gap is 100us 
            begin 
                if (pwm_flag) 
                    state <= PWM_MINUS ; 
                else 
                    state <= PWM_PLUS ; 
                timer <= 32'd0; 
            end 
            else 
                begin 
                    timer <= timer + 32'd1; 
                end 
        end
        default: 
        begin 
            state <= IDLE; 
        end 
    endcase
end

ax_pwm
#(
.N(32)
)
ax_pwm_m0(
    .clk(clk),
    .rst(~rst_n),
    .period(period),
    .duty(duty),
    .pwm_out(pwm_out)
);

endmodule

  1. 查看硬件设计,添加管脚约束和时钟约束
    约束文件
set_property PACKAGE_PIN AE15 [get_ports led]
set_property PACKAGE_PIN AE14 [get_ports rst_n]
set_property PACKAGE_PIN AE5 [get_ports sys_clk_p]
set_property IOSTANDARD LVCMOS33 [get_ports led]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property IOSTANDARD DIFF_SSTL12 [get_ports sys_clk_p]
create_clock -period 5.000 -name sys_clk_p -waveform {0.000 2.500} [get_ports sys_clk_p]
  1. 本地仿真
    激励文件
`timescale 1ns / 1ps

module pwm_test_tb;
// Inputs
reg sys_clk_p;
wire sys_clk_n;
reg rst_n;
wire led ;

// Instantiate the Unit Under Test (UUT)
pwm_test uut (
	.sys_clk_p(sys_clk_p), 		
	.sys_clk_n(sys_clk_n), 	
	.rst_n		(rst_n),
	.led       (led)
);

initial begin
	// Initialize Inputs
	sys_clk_p = 0;
	rst_n = 0;

	// Wait 100 ns for global reset to finish
	#100;
      rst_n = 1;      

 end

always #2.5 sys_clk_p = ~ sys_clk_p;   //5ns一个周期,产生200MHz时钟源

assign sys_clk_n = ~ sys_clk_p;
   
endmodule

这里的PWM周期为1.25ms,和前面的分析相符。
PWM 呼吸灯实验文章来源地址https://www.toymoban.com/news/detail-426911.html

  1. 上板验证
    加载后会产生类似流水灯的效果。

实验总结

  1. 时钟很重要,是硬件系统的心跳,有了时钟硬件才可以动起来。如果PWM模块没有时钟输入的话,就无法被驱动,无法正常工作。另外设计的时候不考虑时钟,将会无从下手。
  2. 逻辑调试和软件调试虽然形式有所不一样,但本质都是相同的,需要一级一级的分析问题出在哪里,不能慌张。
  3. 本地调试很有必要,可以看到更详细的信号,有利于找出问题。

问题记录

  1. 时序约束没让添加时钟的约束,不知道什么原因,手动添加。
  2. 上板的时候流水灯没亮,本地仿真发现led是一个蓝色的线,发现原因是少了一行assign语句,没把pwm的输出接出去。

参考资料

  1. PWM原理 PWM频率与占空比详解
  2. Xilinx 7系列SelectIO结构之IO标准和端接匹配(三)
  3. XILINX 原语的使用之 IBUFDS 差分转单端、OBUFDS 单端转差分

到了这里,关于PWM 呼吸灯实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何用51单片机实现pwm调光+呼吸灯(超详细+源码)

    在工控行业,PWM信号可以用来调节电机转速、调节变频器以及BLDC电机驱动等;在LED照明行业,可以通过PWM来控制LED灯的亮暗变化;还可以通过PWM信号来控制无源蜂鸣器发出简单的声音以及实现功率继电器的线圈节能等。 PWM(Pulse Width Modulation,脉冲宽度调制)为脉冲周期固定

    2024年02月14日
    浏览(64)
  • 嵌入式-stm32-用PWM点亮LED实现呼吸灯

    答:LED需要低电平才能亮,高电平是灯灭。 答:这是用到不同占空比来实现的,控制LED实现呼吸灯,就是通过占空比的高低电平和其持续时间来实现。 ①例如,要定时500ms,则:PSC=7199,ARR=4999,Tclk=72Mhz。 ②假如频率为 2kHz ,则:PSC=71,ARR=499, 频率和周期是描述波形的两个基

    2024年02月03日
    浏览(83)
  • 嵌入式系统开发13——STM32输出PWM实现呼吸灯

    本文主要介绍在STM32F103C8T6上,利用定时器输出PWM波形,进而驱动LED实现呼吸灯。 使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。 脉冲宽度调制(PWM) ,是

    2023年04月08日
    浏览(61)
  • STM32实现PWM输出频率1kHz占空比50%的方波和呼吸灯

    板子:野火指南者 芯片:STM32f103VET6 PWM通道:TIM3的通道1和通道3 GPIO:PA6和PB0 本文主要讲需要怎么做,简要讲解原理,提供全部代码,有利于快速上手。 打开STM32f103VET6的芯片数据手册,打开目录Pinouts and pindescriptions——High-density STM32F103xC/D/E pin definitions,如图所示。 这里选

    2024年02月05日
    浏览(37)
  • 【FPGA】用Verilog语言实现呼吸灯实验

    包含两个输入信号:系统时钟(sys_clk)以及复位信号(sys_rst_n)。 一个输出信号:led_out 通过PWN来控制呼吸灯的亮、灭程度 前一周期为:完全熄灭 —— 完全点亮 后一周期为:完全点亮 —— 完全熄灭 完全熄灭 —— 完全点亮 、 完全点亮 —— 完全熄灭 时间均为1s 由板子频

    2024年02月11日
    浏览(41)
  • PWM的驱动使用(呼吸灯)

    目录 一、初始化步骤 二、PWM所需函数  三、PWM初始化与引脚使用 1、输出比较模式 2、极性的选择 3、初始化: 怎么给结构体赋初始值 4、引脚的使用(引脚定义表) 四、代码(PWM呼吸灯) 1、PWM.c 2、PWM.h 3、main.c 4、模式的选择(复用推挽输出)  5、PWM参数的计算  6、效果

    2024年02月02日
    浏览(31)
  • PWM呼吸灯+流水灯设计

    完成任务: 在流水灯基础上加入pwm呼吸灯设计,关于pwm呼吸灯设计可以看博主上一篇博客PWM呼吸灯设计 ,开发板上灯每两秒进行一次切换,每一个的亮灭间隔为一秒。 代码参考: 测试文件: 我们通过modelsim仿真结果如下: 结果展示:

    2024年02月16日
    浏览(26)
  • stm32之PWM呼吸灯

            呼吸灯是灯从渐亮到渐灭周而复始形成的一个效果。由于51没有PWM所以需要定时器模拟PWM才能实现呼吸灯的效果,但是stm32的通用定时器是有PWM模式的,所以不需要再用软件模拟,精准度也高。 本实验用的基于stm32f103C8t6。在PB8引脚上接了一个led, led的另一端接到

    2024年02月05日
    浏览(25)
  • stm32定时器输出pwm&IO口模拟pwm——呼吸灯

    什么是pwm波?pwm就是脉冲宽度调制,就是占空比可变的脉冲波形,通过改变占空比,输出不同的pwm波,就能实现许多有趣的功能,比如说我们生活中常见的呼吸灯就是通过这样实现的。接下来我们就以呼吸灯为例,学习stm32通过定时器输出pwm波和io口模拟输出pwm波。 控制方式就

    2024年01月18日
    浏览(37)
  • STM32自学☞PWM驱动LED呼吸灯

    常用函数简单说明 ①用来配置输出比较模块  TIM_OC1Init()     (初始化)             TIM_OC2Init()                               TIM_OC3Init()                               TIM_OC4Init() ②TIM_OCStructInit();用来给输出比较结构体赋一个默认值 ③用来配置强制输出模式  TIM

    2024年02月19日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包