用FPGA玩转直流电机:从PWM原理到Quartus II工程实战(附Verilog源码)
2026/6/11 10:53:05 网站建设 项目流程

用FPGA玩转直流电机:从PWM原理到Quartus II工程实战(附Verilog源码)

在嵌入式系统和自动化控制领域,直流电机因其结构简单、控制方便而广泛应用。但对于电子工程师和爱好者来说,如何用FPGA实现精准的电机控制却是一个充满挑战又极具成就感的课题。本文将带你从PWM基础原理出发,通过Quartus II平台,一步步构建完整的直流电机控制系统。

1. PWM控制与H桥驱动原理

直流电机的转速控制本质上是对平均电压的调节,而PWM(脉宽调制)技术正是实现这一目标的理想方案。当我们需要让一个12V的电机以6V的等效电压运行时,PWM可以通过快速切换全压(12V)和零电压来实现。

1.1 PWM参数解析

一个完整的PWM波形包含三个关键参数:

  • 频率:通常选择在1kHz-20kHz之间
    • 过低会导致电机抖动(可听见的啸叫声)
    • 过高会增加开关损耗
  • 占空比:高电平时间与周期的比值
    • 0%表示电机停止
    • 100%表示全速运转
  • 分辨率:占空比可调节的最小步进
    • 8位分辨率提供256级调速
    • 16位分辨率可实现更平滑控制
// PWM生成模块示例 module pwm_generator ( input clk, input [7:0] duty_cycle, output reg pwm_out ); reg [7:0] counter; always @(posedge clk) begin counter <= counter + 1; pwm_out <= (counter < duty_cycle) ? 1'b1 : 1'b0; end endmodule

1.2 H桥电路设计

要实现电机的正反转控制,H桥电路是必不可少的。典型的H桥由四个开关元件(MOSFET或晶体管)组成:

控制信号组合电流路径电机状态
Q1=1, Q4=1电源→Q1→电机→Q4→地正转
Q2=1, Q3=1电源→Q3→电机→Q2→地反转
其他组合无导通路径制动/停止

注意:必须确保同一侧的开关不会同时导通,否则会导致电源短路。在实际电路中通常会加入死区时间控制。

2. Quartus II工程搭建

2.1 开发环境配置

使用Altera Cyclone系列FPGA(如EP2C8)时,需要正确设置Quartus II工程:

  1. 创建新工程(File → New Project Wizard)
  2. 选择目标器件:Cyclone II → EP2C8Q240C8
  3. 配置未使用引脚为三态输入(Assignments → Device → Device and Pin Options)

2.2 模块化设计架构

一个完整的电机控制系统通常包含以下Verilog模块:

  1. 时钟分频模块(div_clk.v)
    • 将系统时钟分频为适合PWM的频率
  2. 按键消抖模块(debounce.v)
    • 消除机械按键的抖动现象
  3. PWM生成模块(pwm_gen.v)
    • 根据设定值产生PWM波形
  4. 方向控制模块(dir_ctrl.v)
    • 管理电机转向逻辑
  5. 顶层模块(motor_ctrl.v)
    • 集成各子模块功能
// 按键消抖模块示例 module debounce ( input clk, input button_in, output reg button_out ); reg [15:0] count; reg button_sync; always @(posedge clk) begin button_sync <= button_in; if (button_sync ^ button_out) begin count <= count + 1; if (&count) button_out <= button_sync; end else count <= 0; end endmodule

3. 关键代码实现

3.1 可调占空比PWM

通过参数化设计,我们可以创建灵活可配置的PWM模块:

module adjustable_pwm #( parameter WIDTH = 8 )( input clk, input [WIDTH-1:0] duty, output reg pwm ); reg [WIDTH-1:0] counter; always @(posedge clk) begin counter <= counter + 1; pwm <= (counter < duty) ? 1'b1 : 1'b0; end endmodule

3.2 电机控制状态机

使用有限状态机(FSM)管理电机运行状态:

module motor_fsm ( input clk, input rst, input start, input reverse, output reg direction, output reg enable ); typedef enum {IDLE, FORWARD, REVERSE} state_t; state_t current_state, next_state; // 状态寄存器 always @(posedge clk or posedge rst) begin if (rst) current_state <= IDLE; else current_state <= next_state; end // 状态转移逻辑 always @(*) begin case (current_state) IDLE: next_state = start ? (reverse ? REVERSE : FORWARD) : IDLE; FORWARD: next_state = start ? (reverse ? REVERSE : FORWARD) : IDLE; REVERSE: next_state = start ? (reverse ? REVERSE : FORWARD) : IDLE; default: next_state = IDLE; endcase end // 输出逻辑 always @(posedge clk) begin direction <= (current_state == REVERSE); enable <= (current_state != IDLE); end endmodule

4. 系统集成与调试

4.1 引脚分配策略

在Cyclone II EP2C8Q240C8上的推荐引脚配置:

信号名称引脚号功能说明
clk2350MHz系统时钟
motor_pwm45PWM输出至H桥
motor_dir46方向控制信号
btn_start28启动/停止按键
btn_reverse29方向切换按键
btn_speed30速度调节按键

4.2 功能验证方法

  1. 仿真测试

    • 使用ModelSim进行功能仿真
    • 验证PWM波形、方向控制和按键响应
  2. 在线调试

    # Quartus II Tcl脚本示例 set_instance_assignment -name VIRTUAL_PIN ON -to motor_pwm set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to motor_pwm
  3. 实际测试步骤

    • 逐步增加占空比观察电机加速
    • 测试方向切换响应时间
    • 检查极端情况下的系统稳定性

5. 性能优化技巧

5.1 时序约束设置

在Quartus II中设置正确的时序约束:

create_clock -name clk -period 20 [get_ports clk] set_input_delay -clock clk 2 [all_inputs] set_output_delay -clock clk 3 [all_outputs]

5.2 资源优化策略

针对Cyclone II器件的优化方法:

  • 使用DSP块实现高精度PWM
  • 采用流水线设计提高时钟频率
  • 共享计数器资源减少逻辑单元使用
// 资源共享示例 module optimized_pwm ( input clk, input [7:0] duty_a, duty_b, output pwm_a, pwm_b ); reg [7:0] counter; always @(posedge clk) begin counter <= counter + 1; end assign pwm_a = (counter < duty_a); assign pwm_b = (counter < duty_b); endmodule

6. 扩展应用设计

6.1 速度闭环控制

通过编码器反馈实现闭环控制:

module speed_control ( input clk, input encoder_a, input encoder_b, output [7:0] pwm_duty ); reg [15:0] speed_count; reg [15:0] target_speed = 16'd1000; // 编码器脉冲计数 always @(posedge encoder_a) begin if (encoder_b) speed_count <= speed_count - 1; else speed_count <= speed_count + 1; end // PID控制器简化实现 reg [31:0] error_sum; always @(posedge clk) begin error_sum <= error_sum + (target_speed - speed_count); pwm_duty <= 8'd128 + (error_sum[31:24] >> 2); end endmodule

6.2 多电机同步控制

通过时间分割复用控制多个电机:

module multi_motor_ctrl #( parameter MOTOR_NUM = 4 )( input clk, output reg [MOTOR_NUM-1:0] pwm_out, output reg [MOTOR_NUM-1:0] dir_out ); reg [1:0] state; reg [7:0] duty[MOTOR_NUM]; always @(posedge clk) begin state <= state + 1; for (int i=0; i<MOTOR_NUM; i=i+1) begin pwm_out[i] <= (state == i[1:0]) && (counter < duty[i]); dir_out[i] <= direction_reg[i]; end end endmodule

在完成基础功能后,可以尝试将这些模块组合成一个完整的电机控制系统。实际测试时,建议先用示波器验证PWM波形,再连接电机进行实际负载测试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询