十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C51驱动L298实现直流电机PWM调速与Proteus仿真详解

C51驱动L298实现直流电机PWM调速与Proteus仿真详解 简介一份面向51单片机初学者的直流电机PWM控制完整工程基于AT89C51/AT89C52与L298驱动芯片实现电机加速、减速、正转、反转及停止控制并配有Proteus仿真适合课程设计、电子竞赛或入门实践。包内共21个文件涵盖C语言源程序、Keil工程文件、Hex烧录文件、Proteus仿真工程及电路截图等压缩包仅116KB结构简洁C源文件方便逻辑修改仿真工程便于电路验证图片则可快速预览整体接线。已有415人学习下载。资料完整覆盖了从独立键盘命令输入、单片机定时产生PWM波形到L298驱动输出、1602液晶实时显示转速的完整信号链路读者可据此理解PWM调速原理、L298控制方式及Proteus联调方法并可直接烧录运行或修改参数扩展功能快速完成同类直流电机控制项目。1. C51 驱动 L298 的标题里真正值得复现的是哪几件事标题很长但拆开看只有三个角色C51 单片机负责判断方向和速度L298 负责把控制逻辑放大成功率输出直流电机是最终负载。加速减速不是改电压而是调 PWM 占空比正转反转不是换电源极性而是切换 H 桥的对角导通停止则有刹车停和惯性停两种做法。标题中出现的“软件源程序”和“Proteus 仿真”意味着这套逻辑全在 8051 内部用软件定时器解决没有一个硬件 PWM 外设。放在学习路径里这个组合刚刚好覆盖了单片机驱动功率器件最常见的接口问题IO 电流不足、逻辑电平匹配、电源共地、定时中断产生稳定波形。下面按先电路、再代码、后仿真的顺序把整个流程铺开你可以直接拿同一份代码改引脚和周期。2. 驱动链路上的电平问题L298 引脚、C51 IO 和电源地线怎么配合先别急着写代码。C51 的 P1 和 P3 引脚输出高电平约 4.2V电流只有几十毫安直接接直流电机会因为负载电流过大导致输出电压跌落甚至损坏单片机。L298 在这里做的事不是简单放大电流它的每一路输出是一个 H 桥内部四个功率管两两组合把电机两端接到电源正或负。逻辑输入端需要很小的电流信号电平兼容 5V TTL因此 C51 可以直连不需要再经过 ULN2003 这类中间驱动。2.1 L298 双 H 桥和直流电机的四个状态直流电机两端接上正电压就正转反一反就反转L298 的 IN1、IN2、ENA 组合起来正好表达了这几种状态。ENA 是使能端为高电平时功率输出才生效为低电平时无论方向引脚怎么设置电机两端都不会被驱动。IN1 和 IN2 控制 H 桥的四个功率管一组对角开通时电机正向通电另一组对角开通时反向通电。ENAIN1IN2电机行为应用场景110正转前进方向之一101反转倒退方向之二111刹车制动线圈两端经功率管短路100自由滑行断开驱动惯性转动0XX强制停止功率输出关闭加速减速时不改 IN1、IN2而是让 ENA 上出现 PWM 方波。占空比越高平均输出电压越高电机转速越快。这个表在 Proteus 仿真里可以直接验证把 ENA 接高电平切换 IN1、IN2观察电机转向再把 ENA 接到单片机 IO用程序调制占空比电机会随着脉宽改变转速。需要提醒的是IN1 和 IN2 同为 1 叫有源刹车电机内部线圈被短路机械上会明显顿一下同为 0 则是自由停车电机靠惯性转。项目里常默认用同样的停止逻辑但实际机械控制中两者差别很大。2.2 C51 引脚分配和 P0 口的坑仿真和实物调试之间最容易在第一版引脚定义上出问题。常见接法是P1.0 和 P1.1 接 IN1、IN2P1.2 接 ENAP3.0 到 P3.3 接四个按键。Keil C51 里用 sbit 做位定义代码非常直观sbit IN1 P1^0; // 电机方向引脚 A sbit IN2 P1^1; // 电机方向引脚 B sbit ENA P1^2; // 使能脚软件 PWM 输出 sbit KEY_UP P3^0; // 加速 sbit KEY_DOWN P3^1; // 减速 sbit KEY_REVERSE P3^2; // 正反转切换 sbit KEY_STOP P3^3; // 停止这段位定义的意义是让代码和原理图对应起来。P1^0 是 Keil C51 的位寻址写法8051 的 P1.0 是一个可直接独立操作的位不需要为宏定义写复杂的寄存器赋值。注意如果手头板子把控制脚放在 P0就要在外部加 10kΩ 上拉排阻否则漏极开路输出无法稳定拉高。Proteus 仿真里很多人不加上拉一直调不通往往就是 P0 口在高电平状态下电位悬空L298 逻辑端读到随机电平。2.3 Proteus 里 L298 的电源和共地设置L298 在 Proteus 原理图里一般有 VCC 和 VS 两个电源入口VCC 给内部逻辑电路供电接 5VVS 给电机功率供电仿真里常用 12V。两个电源的负极和单片机的 GND 必须连到同一个网络电机电流从 VS 流出经过 H 桥、电机、功率管回到 GND如果逻辑地和功率地分开只能看到仿真波形却带不动电机。还要注意 L298 芯片内部虽然有续流二极管模型但实物设计中电机两端仍应并联反向快速恢复二极管防止关断瞬间感性电动势损坏芯片或单片机。这个设计在仿真中体现不出来落到电路板时必须补上。3. 用软件 PWM 实现加速和减速定时器中断与状态机怎么写8051 系列里很多型号没有硬件 PWM 外设所以“加速减速”在代码层面就是做一个可以随时改变占空比的方波输出。常见做法是用一个定时器产生固定频率中断中断里维护一个计数器每计到一定次数就完成一个 PWM 周期再拿计数器的值与目标占空比比较决定 ENA 引脚输出高还是低。3.1 定时器初值怎么算以 12MHz 晶振为例8051 的机器周期是 12 个时钟周期所以定时器每计数一次需要 1μs。想让 PWM 频率在 1kHz 左右可以设置每次中断 10μs100 次中断构成 1ms 周期。定时器 0 工作在模式 116 位初值计算方式为 65536 - 10 65526十六进制就是 0xFFF6。定时器溢出后进入中断函数重新装载初值。#define PWM_PERIOD 100 // 一个 PWM 周期包含 100 个时间片 volatile unsigned char pwm_threshold 0; // 0~100对应占空比 volatile unsigned char pwm_cnt 0; // 时间片计数器 volatile unsigned char key_tick 0; volatile unsigned char key_flag 0; void timer0_isr(void) interrupt 1 { TH0 0xFF; TL0 0xF6; // 初值对应 10us 中断一次 if (pwm_cnt PWM_PERIOD) pwm_cnt 0; ENA (pwm_cnt pwm_threshold) ? 1 : 0; if (key_tick 100) { // 10us * 100 1ms 扫描标志 key_tick 0; key_flag 1; } }代码里 pwm_cnt 从 0 加到 99pwm_threshold 决定高电平宽度。比如 pwm_threshold 30则一周期内前 30 个时间片输出高电平后 70 个输出低电平占空比就是 30%。TH0 和 TL0 的初值决定了定时中断频率改小初值会让中断更频繁、PWM 频率上升但单片机会把更多时间花在中断服务上留给按键扫描和逻辑处理的时间变少。3.2 正转、反转、停止这三组逻辑组合方向控制不需要在中断里做主循环里根据按键状态改 IN1、IN2 即可。可以维护一个方向变量把三态映射写清楚避免每次按下都写一堆 if 判断#define MOTOR_STOP 0 #define MOTOR_FORWARD 1 #define MOTOR_REVERSE 2 void set_direction(unsigned char dir) { switch (dir) { case MOTOR_FORWARD: IN1 1; IN2 0; break; case MOTOR_REVERSE: IN1 0; IN2 1; break; default: // 停止 IN1 0; IN2 0; break; } }这里选择 IN1、IN2 都为 0 的停止方式相当于把电机两个端子都从功率电源上断开让电机靠惯性停下来。如果想要快速停车可以把默认分支改成 IN1 1、IN2 1让两组下管构成短路制动电机立刻抱住。程序上只需要改两个赋值差别可以对照表 2.1 去理解。参数数值含义定时器中断周期10μs时间片最小粒度PWM 周期100 × 10μs 1ms频率 1kHzpwm_threshold0100占空比百分比3.3 把按键转成目标速度和运行方向按键不能直接连到中断里做加减速因为按下时间不确定必须扫描后转换为目标值。下面这一段在 1ms 的 key_flag 有效之后执行每次按键改变一个档位停止键直接清空目标速度void main(void) { unsigned char target_speed 0; unsigned char direction MOTOR_FORWARD; TMOD 0x01; TH0 0xFF; TL0 0xF6; ET0 1; EA 1; TR0 1; set_direction(direction); while (1) { if (!key_flag) continue; key_flag 0; if (KEY_UP 0 target_speed 100) { target_speed 10; // 每次加 10%连续按 10 次到最大 } if (KEY_DOWN 0 target_speed 0) { target_speed - 10; } if (KEY_REVERSE 0) { direction (direction MOTOR_FORWARD) ? MOTOR_REVERSE : MOTOR_FORWARD; set_direction(direction); } if (KEY_STOP 0) { target_speed 0; } pwm_threshold target_speed; } }这个循环的关键在于 key_flag 由中断置位主循环只在标志到来时读取一次按键电平。每次加 10 这个步进是人为选的想细腻一点可以改成加 2但把按键消抖时间计算进去后实际手感会变得很“跳”。加速键按下后每毫秒加一格松开后立即停止所以不会出现按住一次就自动跑到最大速度的问题。若需要长按连续加速应该改成按下后延时 500ms 再每隔 20ms 加一格这部分的延时逻辑还是复用 key_flag。4. Proteus 仿真从搭建到跑起来元件连线、HEX 加载和速度观察Proteus 仿真在这个项目里的作用是提前看清 L298 逻辑输入能不能正确驱动电机。你不需要一开始就在硬件上烧片子先把 AT89C51、L298 和直流电机模型放上去验证程序逻辑足够再转到实物。4.1 在原理图里放哪些元件引脚连到哪新建 Proteus 项目后从元件库中选出的常用器件如下表连接关系尽量和代码里的 sbit 定义保持一致否则程序烧进去方向不对。元件库关键词说明AT89C51AT89C5112MHz 晶振P1/P3 作为控制脚L298L298双 H 桥驱动DC MotorMOTOR-DC用默认 12V 模型按钮BUTTON接 P3 口按下为低电平电阻RESP3 口上拉到 VCC取 10kΩ电解电容CAP-ELEC电机电源两端滤波连接时的顺序影响调试体验。P3 口作为输入必须先接上拉电阻到 5V再让按键一端接地。P1 口直接连到 L298 的 IN1、IN2、ENA不需要上拉。电机接在 L298 输出 OUT1 和 OUT2 之间电源端 VS 接 12VVSS 接 5V所有负极端连到一个 GND 网络。P0 口如果空着就不用管Proteus 不会把悬空引脚当成故障。4.2 用 Keil 生成 HEX 文件后怎么载入 L298 项目仿真依赖 HEX 文件C51 项目编译后才能写进单片机模型。Keil 中需要在 Options for Target 的 Output 标签页勾选 Create HEX File然后用常规方式构建项目。不使用 Keil 时也可以用 SDCC 这类开源编译器命令大致如下sdcc -mmcs51 --iram-size 256 -c motor.c sdcc -mmcs51 motor.rel packihx motor.ihx motor.hex这里第一步把 motor.c 编译成 8051 的重定位目标文件第二步链接第三步把 Intel HEX 文本写出来。生成后在 Proteus 里点击 AT89C51在 Edit Properties 的 Program File 中选择 motor.hex把 Clock Frequency 设成 12MHz点击运行仿真。不要忘记给单片机加电源符号Proteus 默认隐藏电源引脚但 AT89C51 的 VCC 和 GND 必须接入电源网络否则程序根本不会跑。4.3 用虚拟示波器看加速减速是否在发生运行仿真后电机能转不代表 PWM 正确因为加速减速从外观上可能只是一瞬间的变化。Proteus 左侧工具条的 Virtual Instruments 里有 Oscilloscope把探头 A 接到 ENA 引脚探头 B 接到电机一端然后对比加速前后波形。加速后 ENA 的方波高电平时间明显变宽也就是占空比变大减速时高电平时间变窄。电机两端是经过 H 桥调制的方波不是干净的直流用示波器观察时要把 Channel 的耦合方式改成 DC否则看不到低频方波的真实高度。如果 ENA 波形一直是 0V通常是没有给小电动机驱动的 VS 电源或者 pwm_threshold 始终为 0先暂停仿真检查按键加速分支是否进入了。5. 参数选型和仿真调试PWM 频率、按键消抖和常见故障到了这一步整个系统已经能在 Proteus 里动起来但离稳定运行还有一段距离。L298 这类双极型驱动芯片对 PWM 频率敏感按键扫描也需要消抖仿真和实物的差异更常见。5.1 PWM 频率选 1kHz 还是 10kHz上一章把 PWM 频率设计成 1kHz这是学习项目常用的折中。频率太低比如 50Hz电机转动会一顿一顿声音也能明显听到“咔咔咔”频率太高比如 20kHzL298 的功率管开关损耗变大芯片升温快Proteus 仿真时间步长变小运行速度也会拖慢。L298 的数据手册里并没有强制规定最高开关频率但从实际项目看2kHz 以内比较稳10kHz 以上就需要注意 H 桥上下管直通保护和续流二极管恢复时间。如果你打算把 L298 换成 TB6612FNG 这类 MOSFET 驱动可以把频率提到 10kHz因为 MOSFET 开关损耗低而且这个电子转换并不影响方向控制逻辑只需要改 ENA 的 IO 连接。5.2 按键消抖和单次触发3.3 节的按键判断没有消抖Proteus 里按钮模型是理想开关看不出来问题实物上按下和释放会产生几毫秒抖动一次按下可能被读成多次加档。可以在按键扫描里加一个简单的移位寄存器滤波器连续 8 次读到低电平才认为按下unsigned char read_key_filtered(unsigned char raw) { static unsigned char filter 0xFF; filter (filter 1) | raw; return (filter 0x00) ? 1 : 0; }filter 初始为 0xFF低电平有效按键按下时 raw 0移位寄存器会逐步变成 0x00表示按键被稳定读取到。这段代码的代价是按键响应会慢 8ms 左右在 C51 的 1kHz 扫描周期里可以接受。实际项目中还需要在按下和释放沿加入计数避免一次按下被重复处理但 Proteus 仿真中先用移位滤波已经够用。5.3 常见仿真现象和解决清单仿真失败大多发生在电源、地线、HEX 加载这三类问题上整理成表可以节省很多排查时间仿真现象可能原因排查方向电机完全不转ENA 没接到程序控制的引脚用示波器看 ENA 是否有 PWM电机只有一个方向IN1、IN2 接反但程序只看一个键对调 L298 输入端接线加速键没反应P3 口上拉电阻缺失按键电平读不到用电压表量 P3 引脚电压一上电电机就猛转target_speed 初始值不为 0main 开头显式清零电机转速固定不能减PWM 输出接在 IN1 而不是 ENA确认程序控制的是使能脚仿真速度极慢PWM 频率设置过高降到 1kHz 再观察大多数情况下把代码里的参数和原理图连线逐一对照就能定位。Proteus 仿真模型不会烧芯片所以可以大胆尝试把不同输出引脚接到 L298 输入端直到找出正反转方向一致的那组配置再固化到 PCB 连线里。注意仿真中 L298 的电源模型比较容易忽略 VSS也就是逻辑电源如果 VSS 悬空即使 VS 有 12VIN1 和 IN2 也不起作用。6. 给 L298 加一个软启动斜坡把占空比变化做平滑前面直接把 target_speed 赋给 pwm_threshold按键按下去时占空比瞬间从 30% 跳到 40%连接轴和齿轮的电机很容易产生冲击。实际控制里更常见的做法是让实际 PWM 阈值以一定速度向目标值靠近也就是加一个斜坡函数。这样加速曲线是斜线而不是台阶机械结构的应力会小很多。unsigned char motor_ramp(unsigned char current, unsigned char target, unsigned char step) { if (current target) { if (target - current step) return target; else return current step; } if (current target) { if (current - target step) return target; else return current - step; } return current; }函数里 step 是每毫秒允许改变的占空比幅度。如果当前值是 20目标值是 60step 取 2主循环需要 20 次扫描才能把速度推上去也就是大约 20ms 完成加速。step 设成 1 时坡更缓适合带负载启动step 设成 10 后响应快但和直接赋值差别不大。将这函数放到 3.3 节主循环的 key_flag 处理之后按键事件里修改 target_speedwhile 循环里执行pwm_threshold motor_ramp(pwm_threshold, target_speed, 2);就能在不改变任何硬件连接的情况下消除起步冲击。斜坡函数还有一个好处是自然限制了停止时的电流变化。按下停止键时target_speed 置 0pwm_threshold 从高占空比逐步降低电机在减速过程中不会突然被切断电源或短路因此抖动明显减小。要更快停车可以单独做一个刹车分支当 target_speed 0 且当前速度小于某个阈值时直接把 IN1、IN2 设为 1、1用线圈短路制动收尾。这个组合是 L298 控制里比较完整的策略后面如果换用 TB6612FNG 或者其他电机驱动板只需把频率提高到 10kHz 左右斜坡逻辑原样保留这也是从直流电机调速迁移到无刷直流电机驱动原理时值得保留的写法。本文还有配套的精品资源点击获取
返回列表