ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

直流电机PWM调速课设全解析:从H桥驱动到AT89C51定时器中断

直流电机PWM调速课设全解析:从H桥驱动到AT89C51定时器中断 简介针对单片机课程设计常见选题之一——“单片机控制直流电动机”这份资料提供了从设计思路到仿真验证的完整参考方案。资源包仅含1个 docx 文件共17页大小约229KB内容组织为设计目的、任务要求、原理分析、硬件资源、硬件图、程序框图、程序代码、调试运行、仿真截图及设计心得等模块便于按步骤查阅与学习。方案围绕80C51/AT89C51单片机展开重点讲解PWM脉宽调制调速原理、H桥驱动电路与L298芯片应用并涉及A/D、D/A转换、按键手动加减速及4×6键盘列扫描等知识点结合PROTEUS仿真验证可帮助电子信息、自动化等专业学生快速理解直流电机调速系统的设计与调试方法。该文档已有659人学习下载适合用作课程设计参考、实验预习、程序编写对照及答辩准备。1. 从调速公式到H桥一次把直流电机PWM控制课设讲透拿到这份《单片机控制直流电动机——课程设计》时我第一反应是老课设了。但不妨换个角度看AT89C51加L298、PWM调速、按键中断、数码管显示这套组合到今天依然是51单片机入门最扎实的闭环练习。它覆盖了定时器、外部中断、I/O矩阵键盘、动态扫描显示和功率驱动五个基础模块任何一个环节脱节电机都不会按预期转动。整个设计的核心逻辑并不复杂通过改变PWM脉冲的占空比改变电枢电压的平均值从而调节电机转速。89C51产生脉宽可调的矩形波经L298功率放大后驱动直流电机数码管实时显示速度值。文档里值得细看的是调速程序里那个constant变量的用法——它直接决定占空比的变化粒度也埋了一个容易踩的边界坑。本文把硬件选型、驱动时序、定时器初值计算和仿真调试串联起来讲新手能照做老手也能看边界。2. PWM调速原理与AT89C51的资源分配2.1 直流电机转速公式与电枢控制法的选择依据直流电机的转速表达式可以写成n (Ua - Ia·Ra) / (Ce·Φ)其中Ua为电枢端电压Ia为电枢电流Ra为电枢回路总电阻Ce为电势常数Φ为每极磁通量。从这个式子能直接看出两条调速路线改变电枢电压Ua或者改变磁通Φ。磁场控制法通过调节励磁电流改变Φ功率损耗小但低速时磁路饱和、高速时换向火花加剧动态响应也差。工业上最常用的还是电枢控制法——保持励磁不变调节电枢端电压。电枢控制又分连续调压和脉宽调制两种实现。连续调压需要可控整流或直流变换器电路复杂PWM方式本质是开关驱动装置用固定频率控制电源的通断通过改变一个周期内导通时间t1与周期T的比值即占空比D t1/T来改变平均电压。平均电压Vd Vs·DVs为电源电压D在0到1之间连续可调电机速度也就连续可调。这就是把数字I/O变成模拟调速能力的核心思路。2.2 三种占空比调节方式对比与定频调宽的选型理由改变占空比D有三种途径文档里的图1-2给出了直观说明。这里把三种方式放在同一张表里对比调节方式保持量改变量效果问题定宽调频t1不变周期T频率随占空比变化频率接近机械固有频率时引发振荡调宽调频T不变t1频率随占空比变化同上定频调宽T不变t1同时改变关断时间频率固定仅占空比可变无振荡风险实现最简单前两种方式在调速时改变了脉冲频率当这个频率落在电机转轴系统的机械谐振频段时会出现明显抖动甚至失稳。定频调宽法锁死频率、只动占空比从根源上避免了这个问题所以本设计选用它。频率选多少也要算文档给的晶振是12MHz调速程序里每0.1ms产生一次中断10个中断周期合成一个PWM周期即输出频率约1kHz。这个频率远高于电机转子的机械响应带宽电机感受到的是平滑的平均电压。提示PWM频率不是越高越好。频率太高开关管开关损耗上升L298发热明显频率太低电机会出现断续转动和噪音。1kHz到20kHz是比较合理的区间本设计落在1kHz噪声略大但逻辑清晰适合教学场景。2.3 AT89C51定时器资源安排AT89C51有两个16位定时器T0、T1。本设计用T0产生PWM时基T1空闲或用于测速闸门。T0工作在方式116位定时时初值计算公式为初值 65536 - 定时时间 / 机器周期 机器周期 12 / 晶振频率 12 / 12MHz 1us若需要0.1ms中断一次初值 65536 - 100 65436 0xFF9C TH0 0xFF, TL0 0x9C文档调速程序里给的却是TH00X9C、TL00X9C同时还设置TMOD0x02即方式2的8位自动重装模式。这种模式下计数到256溢出初值0x9C即156从156涨到256需要100个计数周期机器周期1us所以中断周期就是100us与程序注释“频率为固定的1kHz左右”吻合。两种写法都对但一个是0.1ms定时配方式1一个是100us定时配方式2看代码时先要对上号。注意基础框架程序里写“定时时间为0.1mst0定时器工作在方式1TH055536/256、TL055536%256”这个初值对应的是10ms定时不是0.1ms文档自身前后不一致。跟进代码时以55536为准实际演示的是数码管每10ms刷新一次、外部中断加计数的框架程序调速程序才是完整闭环。3. L298驱动电路与硬件连线要点3.1 L298内部结构与H桥逻辑L298是双H桥高电压大电流功率集成电路内部有两个完全相同的功率放大回路每个H桥由四个功率晶体管组成。本设计只用其中一个H桥引脚对应关系如下引脚功能本设计连接IN1、IN2方向控制输入TTL逻辑电平接单片机P2.0、P2.1ENA使能端接收PWM信号接PWM输出OUT1、OUT2电机驱动输出接直流电机两端SENSA电流反馈脚不用时直接接地VCC逻辑电源4.5~7V接5VVSS电机驱动电源接电机电源按电机额定电压选H桥的控制逻辑在文档里写得很清楚使能端ENA为高电平时IN1为PWM、IN2为低电机正转IN1为低、IN2为PWM电机反转IN1与IN2同为高或同为低电机快速停止。当ENA为低电平时无论IN1、IN2是什么状态电机都停转。这里的“快速停止”实际上是对两个下桥臂同时导通把电机电枢短路利用反电动势实现制动。还有一种停止方式是“自由停止”——把四个管子全部关断电机靠惯性滑行。课程设计里通常不做区分但工程上要注意不同的停止方式对系统动态特性和安全性影响很大。快速停止适合急停场景自由停止适合断电滑行场景。提示SENSA、SENSB不用时一定要接地悬空会导致内部比较器误触发出现电机不受控的抖动。3.2 按键、数码管与单片机的引脚映射根据文档第七节程序器件连线如下加速键接P3.2INT0低电平触发外部中断0减速键接P3.3INT1低电平触发外部中断1电机驱动P2.0、P2.1分别接L298的IN1、IN2数码管位选P1.0~P1.3低电平选中对应位数码管段码P2口输出共阳段码这里要注意P2口既接L298输入又接数码管段码会存在总线冲突风险。文档中的主程序和调速程序是分开的两个工程硬件上也应该分时复用或直接分口。实际做实验板时我一般建议把段码放到P0口并加上拉电阻P2口专门给L298的方向控制避免调试时互相干扰。如果按文档原方案要确保数码管刷新和PWM输出分时执行不能在同一时刻写P2。46键盘矩阵在文档里只有“键盘列扫描”的标题没有给出具体引脚分配。常见做法是用P1口的4根线做行扫描P3口的6根线做列读入或者反过来。本设计的按键功能已经由外部中断承担46矩阵应该是用于扩展功能比如设置目标转速、切换手动/自动模式。3.3 Proteus仿真元件选型Proteus仿真时需要用到的元件清单AT89C51单片机 L298电机驱动芯片 MOTOR-DC直流电机模型带转速输出端口 POT-HG可变电阻模拟A/D输入 7SEG-MPX4-CA共阳四位数码管或分别放置四个单个数码管 BUTTON按键 CRYSTAL12MHz晶振 CAP22pF~33pF电容晶振匹配 RESPACK-8排阻数码管限流Proteus的直流电机模型比较理想化它带一个转速输出端口电压值正比于实际转速可以直接接到ADC或用电压表观察转速变化。仿真时要注意电机模型的转动惯量参数默认值偏小占空比突变时转速会瞬间跳变和真实电机的大惯性响应差异明显。想更真实把电机模型的Inertia转动惯量调大一些观察到的加减速曲线才接近实际。4. 调速程序实现与定时器初值计算4.1 程序框架拆解定时器中断产生PWM调速程序的核心代码如下每一段拆开讲清楚它做了什么#include reg51.h #include intrins.h #define uchar unsigned char #define uint unsigned int sbit P20 P2^0; // L298 IN1 sbit P21 P2^1; // L298 IN2 uchar flag 0; // 高/低电平标志 bit direction 0; // 方向标志 static uchar constant 1; // 占空比控制量 void time0(void) interrupt 1 using 1 { static uchar i; i; if (i constant) flag 1; // 高电平区间 if (i 10 i constant) flag 2; // 低电平区间 if (i 10) i 0; // 周期归零 TH0 0X9C; // 100us定时 TL0 0X9C; }这段中断服务程序是PWM波形的生成核心。i是一个0到9循环的计数器每个中断周期加1。当i不大于constant时flag置1i大于constant时flag置2i到10时归零。主循环里根据flag的值决定P2.0输出高或低。这样constant的值越大高电平持续的中断周期越多占空比越大。参数说明constant初始值为1占空比约10%如果加到9占空比约90%。TH0TL00X9C配合方式2的8位自动重装中断周期100usPWM周期1ms频率1kHz。这个频率由中断间隔和i的循环上限共同决定改任何一个都能改变PWM频率。4.2 按键中断与占空比调节的边界问题void int1_srv(void) interrupt 2 using 2 // 减速键P3.3 { if (INT1 0) { while (!INT0); // 等待按键释放注意此时读的是INT0 constant--; if (constant 10) constant 0; } } void change(void) interrupt 0 using 0 // 加速键P3.2 { if (INT0 0) { while (!INT0); // 等待按键释放 constant; if (constant 10) constant 0; } }这两个中断服务程序有几个值得注意的点。首先是while(!INT0)在减速中断里写的是INT0而不是INT1这大概率是文档笔误。实际运行中按下减速键后如果P3.2恰好处于低电平代码会一直卡在这个循环里表现为按键失灵。修改方式很简单减速中断里应该读INT1。其次是边界判断的问题。constant的合法范围应该是1到9对应10%到90%的占空比。程序在constant加到10时直接归零等于从100%占空比瞬间跌到0%电机会出现一次明显的抖动和失速。如果把判断条件改成if (constant 9) constant 9;把上限锁在9下限锁在1就能保证占空比始终落在10%到90%区间内不会出现边界跳变。注意中断服务函数里用while(!INT0)等待按键释放这种方式在按键按下期间会阻塞中断系统。如果此时有其他中断请求比如测速中断会一直排队得不到响应。更稳妥的做法是在主循环里做按键扫描加延时消抖中断只置标志位。4.3 主循环与数码管显示void main() { EA 1; // 开总中断 TMOD 0x02; // T0方式28位自动重装 ET0 1; // 开T0中断 TR0 1; // 启动T0 EX0 1; // 开INT0中断 IT0 1; // INT0下降沿触发 EX1 1; // 开INT1中断 IT1 1; // INT1下降沿触发 TH0 0X9C; // 100us定时初值 TL0 0X9C; while (1) { P21 0; // IN2固定低电平电机方向为正转 if (flag 1) { flag 0; P20 1; // IN1输出高 } if (flag 2) { flag 0; P20 0; // IN1输出低 } } }主循环做的事情很纯粹根据flag设置P2.0的输出电平。P2.1固定为0所以电机一直正转。想要反转把P21置1、P20输出PWM即可。IT01和IT11把外部中断设为下降沿触发对应按键按下瞬间的负跳变这样按一次只触发一次中断不需要额外的电平检测逻辑。基础框架程序里的显示函数用了P1做位选、P2做段码TABLE数组放的是共阳数码管段码0xC0到0x90分别对应数字0到9。显示逻辑是依次点亮千位、百位、十位、个位每位延时5ms四位数码管轮流亮一遍约20ms利用视觉暂留形成稳定的数字显示。4.4 测速思路与中断计数方案文档在调试运行一节提到“电动机测速端口接另一片单片机的INT0、INT1”说明测速环节用的是外部中断计数。通用做法是在电机轴上装码盘光电对管输出脉冲信号接到单片机的外部中断引脚每次脉冲触发一次中断在中断里对计数变量加1。测速公式为转速(rpm) (单位时间脉冲数 / 码盘孔数) × 60比如码盘一圈有20个孔1秒内计数到200个脉冲则转速转速 200 / 20 × 60 600 rpm具体实现时用T1做定时器定时1秒产生中断在中断里读取脉冲计数值清零后重新计数。T0继续产生PWM两个定时器各司其职。注意AT89C51没有硬件除法器除以20这种操作要写成软件除法或者把码盘孔数选成2的幂16、32用移位代替除法能省不少指令周期。5. Proteus仿真验证与调试排错实战5.1 仿真搭建步骤从Proteus元件库中取出AT89C51、L298、直流电机、数码管、按键、12MHz晶振、两个22pF电容、电阻排。放置元件后先给AT89C51接好复位电路和晶振电路否则仿真运行时单片机会反复复位。将L298的VCC接5V逻辑电源VSS接电机额定电压。仿真里电机用12V的话VSS就接12V。SENSA、SENSB接地。单片机P2.0接L298的IN1P2.1接IN2L298的ENA接高电平或接一个独立的PWM引脚。文档逻辑里ENA固定使能PWM从IN1输入这种方式是可以工作的。数码管的公共端接P1.0到P1.3段码脚接P2口。共阳数码管的公共端是低电平选通所以位选用0x01、0x02、0x04、0x08这些单bit低电平值。按键一端接P3.2/P3.3另一端接地。仿真里可以不加上拉电阻AT89C51内部有上拉但实际物理板上建议接10k上拉避免按键线悬空时电平漂移。直流电机的转速输出脚接一个电压探针或者ADC模块方便直接读转速值。5.2 仿真运行时的观察要点仿真跑起来后按下加速键观察三个量L298输出的PWM波形、电机两端电压平均值、数码管显示数值。PWM波形用Proteus的虚拟示波器探针接到电机正极端或L298的OUT1脚。占空比变大时示波器上高电平的宽度应该变宽同时电机转速电压表的读数上升。速度显示数据的来源要搞清楚文档的测速方案是另一片单片机这意味着仿真里要放第二片AT89C51才能完成闭环。如果只放了一片单片机且没接码盘信号数码管显示的frq1实际是INT0外部中断的触发次数按一次加速键frq1加1显示的就是按键计数不是真实转速。这两个概念在答辩时经常被混淆提前想清楚。提示如果不做双单片机测速可以把电机模型的转速输出脚接到单片机的ADC引脚用ADC值除以一个系数来估算转速。这样仅用一片单片机就能同时完成PWM输出和速度显示终端硬件成本也更低。这是对原设计的一个实用简化方向。5.3 常见故障与排查方法故障现象可能原因排查手法电机完全不转L298的ENA未接高电平VSS未接电源电机两端接错到OUT3/OUT4用电压表量L298的VSS和OUT1/OUT2之间电压电机只能加速不能减速减速中断里while(!INT0)误读INT0改成while(!INT1)数码管显示乱码段码表用的共阴/共阳与实物不符确认共阳段码表0xC0对应00xF9对应1按键按一下转速跳变多次没有消抖或者不停按着按键导致重复触发中断里等待按键释放或者加延时消抖占空比加到100%后电机突停constant到10后被置0把边界改成1~9电机发热严重PWM频率过低或开关管压降过大提高PWM频率到10kHz以上检查VSS电压是否足够上电后先测晶振引脚波形是否正常示波器能看到12MHz正弦波。再测单片机复位脚上电瞬间应该是高电平稳定后回落。这两项正常单片机才具备运行条件。然后逐个模块排查先让PWM输出固定高电平看电机是否全速转再让PWM输出固定低电平看电机是否停转最后才让定时器中断工作逐级缩小问题范围。5.4 占空比变化粒度的扩展调整文档中constant每次按键变化1对应10%的占空比步进粒度偏粗。如果想实现更精细的调速可以加大中断循环的上限。比如把i的循环上限从10改成100PWM周期变成100个中断周期频率降到100Hz但这个频率太低电机会明显抖动。更合理的做法是保持频率不变缩短中断周期定时初值改为0xF68位方式从246计数到256间隔10us i的循环上限仍为100 PWM周期 100 × 10us 1ms频率仍为1kHz 每个中断周期占空比步进 1%按键一次变化10%以内可以自由设定这样用了更高的定时器中断频率换来了更细的占空比分辨率。代价是CPU在中断里消耗的时间占比上升主循环能做的事变少。对只承担PWM输出和数码管显示的单片机来说这个开销可以接受。CPU占用率大约是每10us中断一次平均每条指令约1us中断服务约30条指令约30%的CPU时间在中断服务中留给显示和按键扫描的余量仍然够用。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进