恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Proteus仿真51单片机PWM电机正反转控制与H桥换向详解
首页
资讯中心
/
Proteus仿真51单片机PWM电机正反转控制与H桥换向详解
Proteus仿真51单片机PWM电机正反转控制与H桥换向详解
发布时间:2026/9/14 5:28:10
简介Protues仿真实例-51单片机-PWM电机正反转是一份面向单片机初学者与电子设计课程的虚拟仿真学习包用于演示如何通过PWM信号控制直流电机的正转与反转。资源共16个文件压缩后仅59KB包含Protues仿真电路.dsn、C语言与汇编源码.c/.a51、可烧录的.hex固件、Keil工程配置.uv2等类型覆盖从代码编写、编译到仿真验证的完整链路。已有982人学习下载。通过该实例学习者可深入理解51单片机定时器产生PWM的工作原理掌握占空比与电机转速的关系并学习H桥等电机驱动电路的连接与换向控制方法。仿真环境无需硬件支持反复调整参数观察电机状态变化既能巩固单片机I/O口与定时器知识也可作为课程设计或项目预研的参考实用性较强。1. 为什么先搭“PWM电机正反转”而不是直接画板一个很常见的翻车现场是51单片机点灯、按键练熟了一到PWM电机驱动就卡住——示波器里PWM波形是对的电机却只转一个方向或者一换向驱动芯片就烫手。问题往往不在占空比计算而在H桥的换向时序和死区处理。标题里的“Protues”是习惯性误拼实际指的就是 Proteus 仿真 51 单片机项目用 Keil C51 写代码生成 hex在 Proteus 里放 AT89C51、L293D 和直流电机用定时器中断模拟 PWM实现调速与正反转。适合课设入门、硬件调试前的逻辑验证也适合从 51 转 STM32/增强型 51 的工程师先想清楚方向切换到底在切换什么。2. PWM调速、H桥换向与51定时器原理和选型2.1 占空比怎么算平均电压PWM控制电机转速的核心公式直流电机调速的本质是调电枢平均电压。PWM 波在一个周期内高电平时间为 Ton周期为 T占空比 D Ton / T × 100%则电机两端平均电压 U_avg U_h × DU_h 是 H 桥供电电压。电机是电感负载稳态转速近似正比于 U_avg所以在 50% 占空比下12V 供电的电机等效于 6V 供电。这个公式成立有条件PWM 频率要远高于电机电气时间常数 τ L/R。常见小型直流电机 L 约 1~10mHR 约几欧到十几欧τ 大约 0.1~1ms。PWM 频率只有几十 Hz 时电流纹波很大转速会明显波动1kHz 左右可闻噪声明显实用中 1kHz~20kHz 都很常见。Proteus 仿真里不必追求太高频率因为仿真速度与中断频率成反比先用 100Hz 验证逻辑再按参数表调到实际需要的频率。2.2 H桥换向拓扑与直通冲突正反转不能靠反接电源线实现工程上用的是 H 桥四个开关管电机接中间两支路。正转时左上右下导通反转时右上左下导通。这个标题里的实例通常用 L293D 这类集成 H 桥比用四个三极管自己搭更接近实际产品。L293D 的控制逻辑不复杂IN1、IN2 决定方向EN1 接 PWM 调速。正转时 IN11、IN20EN1 输出 PWM反转时 IN10、IN21EN1 输出 PWMEN10 时输出高阻电机滑行。这个逻辑对应一张常用的真值表模式IN1IN2EN1电机效果正转10PWM正转可控速反转01PWM反转可控速停止000高阻、自由滑行刹车110短接制动真正需要警惕的是直通换向时若先改 IN1/IN2再停 PWM那么在切换瞬间如果 PWM 恰好为高桥臂可能上下同时导通形成 VCC 到 GND 的短路。集成芯片内部虽有逻辑保护但换向时序仍然要按“先撤 PWM、再换方向、等续流消散、再恢复 PWM”的顺序写。2.3 51单片机定时器产生PWM的三种做法传统 51 内核没有硬件 PWM 外设产生 PWM 常见三种做法。第一种是纯软件延时翻转 IO改占空比要改延时难以动态调速只适合演示。第二种是定时器中断配合计数变量这是本实例采用的方式定时器固定中断周期每次中断让计数器加一计数器与占空比变量比较后输出高低电平。第三种是换成带硬件 PWM 的增强型 51 或 STM32输出交给外设CPU 只在调占空比时写寄存器。三种做法对比如下实现方式分辨率CPU 开销动态调速适用场景软件延时翻转低中不方便教学演示定时器中断IO 翻转高高改变量即可51 课设、Proteus 验证硬件 PWM 外设高几乎为零写寄存器量产、闭环控制第二种方法的中断骨架非常固定void timer0_isr(void) interrupt 1 { if (pwm_cnt PWM_PERIOD) pwm_cnt 0; PWM_OUT (pwm_cnt pwm_duty) ? 1 : 0; }pwm_cnt 从 0 加到 PWM_PERIOD-1pwm_duty 是 0~PWM_PERIOD 之间的整数。比较用的是而不是这样 pwm_duty 等于 PWM_PERIOD 时输出 100% 高电平等于 0 时输出恒低边界行为正确。PWM 频率等于定时器中断频率除以 PWM_PERIOD分辨率等于 1/PWM_PERIOD这两个参数直接决定调速平滑度和中断开销。3. Proteus仿真实例搭建元件、Keil工程与最小代码3.1 Proteus元件对照与接线顺序在 Proteus 里新建工程后先按左侧工具栏的 P 进入元件库检索并放置以下元件AT89C51、L293D、MOTOR-DC、BUTTON、RES。AT89C51 和 AT89C52 在仿真中可互换L293D 在 Proteus 的 Motor Drivers 分类下MOTOR-DC 在模拟器件分类下。连线时按“信号流”布局别乱拉线。单片机 P1.0 接 L293D 的 IN1P1.1 接 IN2P1.2 接 EN1L293D 的 OUT1、OUT2 接直流电机两端VSS 接逻辑电源 5VVS 接电机电源 12V 或 9V所有地必须共地。按键接 P3.0、P3.1、P3.2另一端接地P3 口内部有弱上拉不外加电阻也能工作但为了抗干扰可以各加一个 10kΩ 上拉到 VCC。AT89C51 的 EA 引脚应接 VCC这样 CPU 按内部程序存储器取指否则仿真可能跑到外部总线状态。双击单片机把 Clock Frequency 改为 12MHz这个值必须与 Keil 工程里的晶振设置一致否则定时器初值全偏。电路较大时可以用总线画法减少连线用 Bus Mode 画总线再用 Wire Label Tool 给导线命名网络标号Proteus 里同名网络自动连通。3.2 Keil C51 工程定时器中断产生 PWM 的最小代码Keil 5 装好后要确认安装了 C51 支持包否则新建工程里找不到 AT89C51 设备。工程设置里勾选 Output 页面的 Create HEX File编译后才能在 Proteus 里加载。下面是一份可直接跑通正反转和调速的完整工程代码#include reg51.h sbit MOTOR_IN1 P1^0; // L293D 方向引脚 sbit MOTOR_IN2 P1^1; sbit MOTOR_PWM P1^2; // L293D 使能脚 EN1接 PWM sbit KEY_UP P3^0; // 加速 sbit KEY_DOWN P3^1; // 减速 sbit KEY_DIR P3^2; // 换向 #define PWM_PERIOD 100 // 计数器长度占空比分辨率 1% unsigned char pwm_cnt 0; unsigned char pwm_duty 50; // 初始占空比 50% bit motor_dir 0; // 0 正转1 反转 bit motor_run 0; // 是否输出 PWM void timer0_isr(void) interrupt 1 { TH0 0xFF; TL0 0x9C; // 12MHz 下定时 100us if (pwm_cnt PWM_PERIOD) { pwm_cnt 0; } if (motor_run (pwm_cnt pwm_duty)) { MOTOR_PWM 1; } else { MOTOR_PWM 0; } } void delay_ms(unsigned int ms) { unsigned int i, j; for (i 0; i ms; i) for (j 0; j 120; j); } void set_direction(bit dir) { motor_run 0; // 先撤掉 PWM 使能 motor_dir dir; if (dir 0) { MOTOR_IN1 1; MOTOR_IN2 0; } else { MOTOR_IN1 0; MOTOR_IN2 1; } delay_ms(5); // 等一个 PWM 周期以上 motor_run 1; } void main(void) { TMOD 0x01; // 定时器0模式116位 TH0 0xFF; TL0 0x9C; ET0 1; EA 1; TR0 1; set_direction(0); // 默认正转 while (1) { if (KEY_UP 0) { delay_ms(20); while (KEY_UP 0); delay_ms(20); if (pwm_duty 95) pwm_duty 5; } if (KEY_DOWN 0) { delay_ms(20); while (KEY_DOWN 0); delay_ms(20); if (pwm_duty 5) pwm_duty - 5; } if (KEY_DIR 0) { delay_ms(20); while (KEY_DIR 0); delay_ms(20); set_direction(!motor_dir); } } }定时器初值 0xFF9C 对应 12MHz 晶振下的 100us 中断周期。PWM_PERIOD 为 100所以一个 PWM 周期是 100×100us10msPWM 频率为 100Hz。pwm_duty 初始 50即 50% 占空比。按键加速步进 5%避免一次按键从 0 直接跳到 100%实际调试时更好观察转速变化。换向函数 set_direction 的四步顺序是刻意设计的先禁止中断输出 PWM改方向延时 5ms再恢复 PWM用于规避直通。Proteus 里双击 AT89C51在 Program File 选择上面编译生成的 hex 文件点左下角运行按钮。如果电机不转先看 P1.2 是否有波形再看 L293D 的 VS 是否供电。没波形就先查晶振频率与初值计算有波形不转就查 VS 和电机接线。3.3 仿真前必查的5个参数参数表比代码更容易漏。上电前逐项确认检查点正确设置错误后果单片机晶振12MHz与代码一致定时器初值不准PWM 频率偏差定时器初值TH00xFFTL00x9C中断周期不对转速不受控L293D 电源VSS5VVS9V~12V电机不转或逻辑混乱方向与 PWM 引脚P1.0/P1.1 接方向P1.2 接 EN正反转无效果或占空比调速失效EA 引脚接 VCC 或高电平程序可能从外部总线取指失败4. PWM参数调节、正反转死区与排错4.1 PWM占空比计算公式与定时器初值的换算调参数的第一件事是看懂定时器初值。12MHz 晶振下机器周期是 12/12MHz1us定时器每计一个数耗 1us。要中断周期 T_int100us计数个数是 100初值 65536-100654360xFF9C。PWM 周期是 T_int × PWM_PERIOD代入数字得到 100us×10010ms即 100Hz。占空比是 pwm_duty / PWM_PERIOD也就是 pwm_duty 每加 1占空比变 1%。如果真实项目需要 1kHz PWM可以减小中断周期或减小 PWM_PERIOD。中断周期 50us、PWM_PERIOD20 时PWM 仍是 1kHz但占空比分辨率只有 5%转速调节会有一档一档的感觉。常用参数组合目标 PWM 频率中断周期PWM_PERIOD定时器初值分辨率100Hz100us1000xFF9C1%1kHz50us200xFFCE5%10kHz10us100xFFF610%10kHz 那行在传统 51 上不建议用中断模拟因为 10us 一次中断中断服务函数本身就要消耗不少于这个时间CPU 会被占满。这也是为什么增强型 51 和 STM32 普遍使用硬件 PWM 的理由。Proteus 仿真里频率高了不仅占 CPU仿真速度也会肉眼可见变慢所以上面代码先用 100Hz 跑逻辑确认无误后再按实际需要调表。4.2 正反转切换必须加死区仿真里烧不掉的H桥前面 set_direction 里的顺序是正反转实现的关键。实际工程里很多人直接在 while 循环里写 DIR1 或 DIR0PWM 还在输出这种改法在 Proteus 里通常看不出问题因为 L293D 的仿真模型不会模拟过热和电气击穿。真实板子上换向瞬间 PWM 高电平和反向导通同时存在桥臂电流会在极短时间内飙升反复几次驱动芯片就废了。死区处理不必复杂核心是先让 PWM 输出进入高阻或恒低状态。常见做法是 motor_run 置 0在中断里对所有 PWM 输出引脚统一拉低然后切换 DIDX 方向引脚延时至少一个 PWM 周期最后恢复 motor_run。上面代码 delay_ms(5) 在 100Hz PWM 下是半个周期实际上已经足够长如果 PWM 频率提高到 1kHz延时可以缩短到 1~2ms但只少不多。换向的另一种做法是软切换先降占空比到 0停若干毫秒再切方向再恢复占空比。这对电机电流冲击更小但按键操作和程序逻辑都更复杂。对于课设和一般调速需求先拉低再换向已经完全够用。4.3 Proteus仿真51单片机的6个常见误区按键抖动不处理。Proteus 里的按键仿真也有抖动不加延时消抖会出现一次按加速却连续加好几次的情况。代码里的 delay_ms(20) 是标准做法。示波器接错点。MOTOR_PWM 引脚接虚拟示波器看到的是方波电机两端看到的是被电机电感滤过的近似直流两者波形形态不同别拿电机端波形判断 PWM 好坏。反转时电机不转但正转正常。先查 IN1/IN2 是否同时为 0EN1 是否确实有 PWM。L293D 的 EN 脚只有在输入逻辑有效时才把 PWM 传到底部桥臂。P0 口做输出却不加上拉。51 的 P0 是开漏结构这个实例如果用了 P0 接电机驱动方向必须外接 10kΩ 上拉否则输出高电平不够。换向死在 while (KEY_DIR 0) 里。Proteus 仿真时会一直等按键松开看起来像程序跑飞实际是正常等待。观察时把虚拟终端或示波器加上或者设一个不依赖按键操作的调试状态。电机转速只跟随占空比线性变化但低占空比不转。直流电机存在启动电压5% 占空比下 12V 平均电压只有 0.6V电机不转是正常的不是程序问题。仿真电机模型更接近理想线性模型实际电机这种现象更明显。5. 用Proteus图表验证PWM波形再迁到硬件PWM5.1 用虚拟示波器和图表量化占空比仿真跑起来后在 Proteus 左侧选择虚拟示波器把探头加到 MOTOR_PWM 引脚。调整时间轴到 20ms/div 左右可以看到稳定方波。方波高电平时间与周期的比值就是实际占空比配合代码里设置的 pwm_duty 能直观判断定时器初值和比较逻辑是否正确。想量化调速线性度可以再拖一个 DC Voltmeter 并联在直流电机两端。把 pwm_duty 分别设为 25、50、75、100记录电压表读数理论值应接近 U_VS × 占空比。例如 VS12V 时25% 约 3V50% 约 6V75% 约 9V。读数偏差过大时检查 VS 电压或 L293D 的饱和压降。5.2 同一套逻辑从51迁到STM32/增强51的快速路径Proteus 不只支持 51 内核同样可以完整仿真 STM32。换芯片时方向控制、按键消抖、死区顺序这部分代码原样保留要换的只是 PWM 生成方式传统 51 用中断里比较变量产生 PWMSTM32 用定时器 TIM 输出比较通道产生 PWM。占空比变量直接映射到捕获/比较寄存器 CCRPWM_PERIOD 对应定时器自动重装值 ARR。迁移时最容易漏掉的是一个周期初的极性设置也就是 PWM1 还是 PWM2 模式占空比对应的输出电平正好相反。5.3 加编码器闭环前的最后两个检查点如果后续要把这个实例扩展成转速闭环系统先确认两个点。第一H 桥只允许一个方向使能位负责调速不能同时用正转和反转两个 PWM 信号控制否则会出现直通风险。第二换向死区在闭环控制中不能改成零转速环输出从正到负跨越零点时必须先经过停 PWM 状态。比较好的结构是转速 PID 输出速度值正负号映射到 motor_dir绝对值限幅后映射到 pwm_duty换向仍复用 set_direction 的时序。这样一个仿真工程稍微改改就能变成小型风机、云台或小车驱动的基础模块。本文还有配套的精品资源点击获取