接收PID输出的可调占空比PWM

发布于:2025-08-09 ⋅ 阅读:(21) ⋅ 点赞:(0)

1. PWM波原理非常简单, 核心是精度控制, 原定占空比输入为百分比, 导致精度只能到1%, 现在直接引入pid输入, 在module计算占空比, 精度可以到0.01%

2. 四舍五入的两种技巧

`timescale 1ns / 1ps
//****************************************VSCODE PLUG-IN**********************************//
//----------------------------------------------------------------------------------------
// IDE :                   VSCODE     
// VSCODE plug-in version: Verilog-Hdl-Format-3.7.20250728
// VSCODE plug-in author : Jiang Percy
//----------------------------------------------------------------------------------------
//****************************************Copyright (c)***********************************//
// Copyright(C)            Please Write Company name
// All rights reserved     
// File name:              
// Last modified Date:     2025/08/07 11:50:51
// Last Version:           V1.0
// Descriptions:           
//----------------------------------------------------------------------------------------
// Created by:             Please Write You Name 
// Created date:           2025/08/07 11:50:51
// mail      :             Please Write mail 
// Version:                V1.0
// TEXT NAME:              pwm.v
// PATH:                   C:\Users\Administrator\Desktop\工作记录\vivado\PWM\PWM.srcs\sources_1\new\pwm.v
// Descriptions:           
//  频率生成、占空比精度均为万一                       
//----------------------------------------------------------------------------------------
//****************************************************************************************//

module pwm(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               enable                     ,//enable 为0输出默认值
    input                [  17: 0]      Freq_wave                  ,
    input                [  15: 0]      Duty_cycle                 ,//由pid产生 max 为65535--》100%
    output                              pwm_out_p                  ,
    output                              pwm_out_n                   
);

    //---------------------------------------------------------------------------------------
    // PWM Parameters  
    //我们使用锯齿波和直流比较生成pwm 
    //  1. sys_clk_freq_hz 生成PWM的系统时钟频率
    //  2. Freq_wave 决定锯齿波的频率,同时也是pwm的频率
    //  3. duty_cycle 定义pwm波的占空比  单位为百分比
    //  4  thres为锯齿波的比较值,大于时pwm为0;小于时pwm为1                                                                              
    //---------------------------------------------------------------------------------------
    parameter                           sys_clk_freq_hz             = 400_000_000          ;
    //parameter                           Freq_wave                   = 100_000              ;    
    //parameter                           Duty_cycle                  = 50                   ;

    //parameter                           max_cnt_wave                = sys_clk_freq_hz/Freq_wave;
    //parameter                           thres                       = Duty_cycle * max_cnt_wave /100;
    //---------------------------------------------------------------------------------------
    // 内部变量定义                                                                                    
    //---------------------------------------------------------------------------------------   
    reg                [  17: 0]        r_Freq_wave                 ;
    reg                [   6: 0]        r_Duty_cycle                ;
    reg                [  11: 0]        cnt_wave                    ;
    reg                                 out_pwm                     ;
    wire               [  11: 0]        max_cnt_wave                ;
    wire               [  10: 0]        thres                       ;
    wire               [  27: 0]        duty_temp                   ;

    //---------------------------------------------------------------------------------------
    // 时序与组合逻辑定义                                                                                    
    //---------------------------------------------------------------------------------------
     // 1. 频率计算(带四舍五入,降低频率误差)
    assign                              max_cnt_wave                = (sys_clk_freq_hz+ r_Freq_wave/2) / r_Freq_wave;
        // 2. 占空比计算(基于PID输出,无比例误差)
    // 公式:duty_threshold = (pid_output * max_cnt_wave) / MAX_DUTY
    //assign                              thres                       = r_Duty_cycle * max_cnt_wave/100;
    assign                              duty_temp                   = r_Duty_cycle * max_cnt_wave;
    assign                              thres                       = duty_temp[27:16] + (duty_temp[15] ? 1'b1 : 1'b0);// 四舍五入
        
        // 输入数据打拍
        always @(posedge clk or negedge rst_n)
            begin
                if(!rst_n)
                    begin
                    r_Freq_wave <= 100_000;
                    r_Duty_cycle <= 37268;
                    end
                else if(enable)
                    begin
                    r_Freq_wave  <= Freq_wave;
                    r_Duty_cycle <= Duty_cycle;
                    end
                
            end
        //

        always @(posedge clk or negedge rst_n)
            begin
                if(!rst_n)
                    cnt_wave <= 0;
                else if(cnt_wave == max_cnt_wave-1)
                    cnt_wave <= 0;
                else cnt_wave <= cnt_wave + 1;
            end

       always @(posedge clk or negedge rst_n)
           begin
               if(!rst_n)
                    out_pwm <= 0;
               else if(cnt_wave <= thres-1)
                    out_pwm <= 1;
               else
                    out_pwm <= 0;
           end
    assign                              pwm_out_p                   = out_pwm              ;
    assign                              pwm_out_n                   = ~out_pwm             ;

                                                                   
                                                                   
endmodule


网站公告

今日签到

点亮在社区的每一天
去签到