FPGA新手也能搞定的直流电机PWM调速:用Quartus II和Verilog从按键消抖到烧录全流程

张开发
2026/4/7 6:59:52 15 分钟阅读

分享文章

FPGA新手也能搞定的直流电机PWM调速:用Quartus II和Verilog从按键消抖到烧录全流程
FPGA新手实战从零实现直流电机PWM调速系统第一次接触FPGA开发时看着实验室里转动的直流电机那种通过自己编写的Verilog代码控制物理设备的成就感至今难忘。本文将带你完整实现一个基于FPGA的直流电机PWM调速系统特别针对刚入门Verilog的开发者从按键消抖处理到最终程序烧录每个环节都会详细解释其原理和实现方法。1. 项目准备与环境搭建在开始编码前我们需要准备好开发环境和硬件设备。推荐使用Quartus Prime Lite Edition最新版Quartus II它支持大多数Altera/Intel FPGA芯片且完全免费。硬件方面需要FPGA开发板如Cyclone IV EP4CE系列USB-Blaster下载器直流电机驱动模块常用L298N或TB6612FNG直流电机额定电压与开发板匹配关键设置注意事项// 新建工程时务必选择正确的器件型号 // 例如Cyclone IV EP4CE6E22C8对应的设置 Device Family: Cyclone IV E Package: EQFP Pin count: 144 Speed grade: 8首次使用Quartus时容易忽略的配置项配置项推荐设置说明未使用引脚As input tri-stated防止短路损坏芯片编译模式Fast Compile加快开发迭代速度默认文件类型Verilog HDL避免创建不必要的BDF文件提示安装完成后建议运行一次LED闪烁测试程序验证开发环境是否正常工作。2. PWM核心模块设计PWM脉宽调制是控制直流电机转速的核心技术。其基本原理是通过调节高电平在一个周期内的占比占空比来改变平均输出电压。我们首先设计一个可调占空比的PWM发生器。PWM模块关键参数基准时钟50MHz开发板常见晶振频率PWM频率1kHz适合大多数直流电机占空比分辨率8位256级可调module pwm_generator ( input clk_50M, // 50MHz时钟输入 input [7:0] duty, // 占空比控制(0-255) output reg pwm_out // PWM输出信号 ); reg [7:0] counter; always (posedge clk_50M) begin counter counter 1; pwm_out (counter duty) ? 1b1 : 1b0; end endmodule实际应用中需要考虑的几个关键点频率选择电机特性不同最佳PWM频率也不同。通常普通直流电机1kHz-10kHz空心杯电机10kHz-20kHz大功率电机5kHz以下占空比线性度测试不同duty值对应的实际转速可以用手机APP测速仪验证死区时间H桥驱动时需要添加防止上下管直通3. 用户交互与按键处理开发板上通常使用机械按键控制电机启停、转向和调速。机械按键存在抖动问题需要通过硬件或软件方式消除。这里我们采用经典的Verilog消抖算法。按键消抖模块设计module debounce ( input clk, input button_in, output reg button_out ); reg [19:0] counter; reg button_sync; always (posedge clk) begin button_sync button_in; if (button_out ! button_sync) counter counter 1; else counter 0; if (counter) // 当计数器满约20ms消抖时间 button_out button_sync; end endmodule典型的三按键控制方案按键功能逻辑处理KEY1启停切换PWM使能信号KEY2转向控制H桥方向引脚KEY3调速循环增加占空比注意按键消抖时间一般取10-20ms具体值需要通过实际测试调整。时间太短可能无法有效消抖太长则影响操作响应速度。4. 系统集成与调试技巧完成各子模块后需要将它们集成到顶层模块并进行引脚分配。这是新手最容易出错的环节下面给出一个完整的集成示例。顶层模块连接module motor_ctrl_top ( input clk_50M, input key_start, input key_dir, input key_speed, output motor_a, output motor_b, output [3:0] led // 用于显示当前速度档位 ); wire pwm_out; wire debounced_start, debounced_dir, debounced_speed; // 实例化消抖模块 debounce db_start(.clk(clk_50M), .button_in(key_start), .button_out(debounced_start)); debounce db_dir(.clk(clk_50M), .button_in(key_dir), .button_out(debounced_dir)); debounce db_speed(.clk(clk_50M), .button_in(key_speed), .button_out(debounced_speed)); // 实例化PWM模块 pwm_generator pwm( .clk_50M(clk_50M), .duty(current_duty), .pwm_out(pwm_out) ); // 控制逻辑 reg [7:0] current_duty 8d64; // 初始占空比25% reg direction 0; always (posedge debounced_speed) begin case(current_duty) 8d64: current_duty 8d128; // 50% 8d128: current_duty 8d192; // 75% 8d192: current_duty 8d255; // 100% default: current_duty 8d64; // 25% endcase end always (posedge debounced_dir) direction ~direction; assign motor_a direction ? pwm_out : 1b0; assign motor_b direction ? 1b0 : pwm_out; assign led current_duty[7:4]; // 用LED显示当前速度档位 endmodule引脚分配参考表信号名称FPGA引脚开发板对应接口clk_50MPIN_2350MHz时钟输入key_startPIN_45按键KEY1key_dirPIN_46按键KEY2key_speedPIN_47按键KEY3motor_aPIN_101电机接口Amotor_bPIN_102电机接口Bled[0]PIN_85LED1led[1]PIN_86LED2led[2]PIN_87LED3led[3]PIN_88LED4调试时常见问题及解决方法电机不转检查电源是否接通测量PWM输出引脚是否有信号确认H桥使能引脚已激活按键无反应检查消抖时间是否合适确认按键引脚分配正确测试按键硬件是否正常转速不稳定检查电源功率是否足够尝试调整PWM频率添加电机两端滤波电容5. 进阶优化与扩展思路完成基础功能后可以考虑以下增强功能速度闭环控制// 添加编码器反馈 input encoder_a; input encoder_b; // 速度计算 reg [31:0] pulse_count; reg [15:0] current_rpm; always (posedge encoder_a) begin pulse_count pulse_count 1; end // 每1秒计算一次RPM always (posedge clk_1s) begin current_rpm (pulse_count * 60) / PULSES_PER_REV; pulse_count 0; end通信接口扩展UART控制通过串口发送速度指令PWM远程控制接收RC接收机信号I2C/SPI接口连接传感器或显示屏保护功能实现过流保护检测电机电流堵转保护监测转速异常温度保护添加温度传感器实际项目中我在为一个小型机器人设计驱动系统时发现简单的速度开环控制在不同负载下表现差异很大。后来添加了编码器反馈和PID算法后转速稳定性得到了显著提升。PID参数整定是个需要耐心的过程建议先从较小的比例系数开始尝试。

更多文章