ARTICLE DETAIL

资讯详情

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

基于8086与8255A的步进电机开环控制系统设计与调试复盘

基于8086与8255A的步进电机开环控制系统设计与调试复盘 说实话这门课设刚发下来的时候我盯着“步进电机开环控制系统”这几个字愣了半天。单片机课设还好说微机原理课设要拿8086去控制电机总觉得哪里有点复古。但真正做完一轮之后我的看法完全变了步进电机开环控制恰恰是最能体现“微机系统”这门课价值的一个题目——它不是让你背8255A有几个端口而是逼你把总线时序、I/O接口、驱动电路、控制程序这几层东西全部串起来。这篇文章就把我这轮课设从拿到题目到最终答辩的完整过程复盘一遍包括硬件接线、控制程序设计、实测排错的完整链路以及一些我在做之前完全没想到的坑。如果你也在做类似的题目哪怕实验箱型号不一样里面的思路和经验应该也能直接用上。1. 拿到题目别急着敲代码先想清楚开环控制到底在干什么1.1 从“开环”这两个字说起“开环”听起来很高深其实就是没有反馈。系统执行完指令之后它并不知道电机实际转到了哪个位置也不去检测有没有丢步纯粹靠“发一个脉冲走一步”这种硬关系来保证位置精度。步进电机之所以适合做开环是因为它本身的机械结构决定了——转子是永磁体定子绕组按顺序通电时会产生一个旋转磁场转子会老老实实地跟着这个磁场一步一个脚印地走只要每一步都走对累计的角度就是准确的。这就好比你闭着眼睛走台阶。每一级台阶高度是固定的你只要数着自己走了多少级就知道自己大概到了几楼。但如果哪一步踩空了相当于电机失步你是察觉不到的后面所有的位置计算都会跟着错。开环控制就是这样一套“信任步进电机每一步都算数”的逻辑。1.2 系统要实现哪些功能题目里写的是“开环控制系统”字面要求并不复杂但完整的课设一般要覆盖这几块步进电机能够正常运转转速可调能够实现正转和反转切换能够控制转动的步数也就是实现定位功能显示当前状态方向、转速、已走脉冲数等配合按键或者通过主机发送命令来操作。如果你只做到“电机能转”答辩的时候肯定会被问倒。做课设的意义不只是让电机转起来而是把整个控制链路讲明白CPU怎么算出控制字、怎么通过数据总线送到8255A、8255A的端口输出怎么变成电机绕组的通断信号、相序的变化顺序为什么是那样的。想清楚这条链路代码怎么写自然就清楚了。1.3 系统结构怎么搭我的系统结构大致是这样的核心控制8086微处理器实验箱上的CPU模块并行接口8255A可编程并行接口芯片工作于方式0A口作为输出口驱动电路ULN2003达林顿管驱动板实验箱集成或外接模块执行机构四相五线步进电机我用的28BYJ-48减速比1:64输入设备实验箱上的按键用来切换正反转、启动停止、加减速显示设备数码管用来显示转速档位和累计步数。这里有一个容易忽略的点如果实验箱上用的电机是自带减速齿轮的那种比如28BYJ-48减速比1/64那么电机轴真正转一圈需要4096个脉冲步距角5.625°/64而不是网上常说的48个脉冲。这个细节等你算“转多少圈”的时候就会明白有多重要。1.4 为什么推荐用四相八拍而不是单四拍步进电机的通电方式有三种单四拍A→B→C→D、双四拍AB→BC→CD→DA、八拍A→AB→B→BC→C→CD→D→DA。三种方式都能转但区别很大单四拍每拍只有一个绕组通电产生的力矩小而且因为磁场切换是跳跃式的电机振动大低速时容易因为惯性在换相瞬间卡住。双四拍每拍有两个绕组同时通电力矩比单四拍大运行相对平稳但步距角和单四拍相同。八拍单四拍和双四拍交替进行每半步切换一次步距角减半分辨率翻倍力矩过渡更平滑振动明显小启动也更顺畅。对于课设来说八拍的代码无非就是多一张相序表运行效果却明显更好。答辩时老师看到你能解释清楚三种通电方式的区别印象分会好很多。2. 硬件链路从8086总线到电机线圈中间发生了什么2.1 实验箱硬件平台与接口地址确定微机系统课程设计通常用实验箱完成。不同学校的实验箱型号差异挺大有的用TPC-8086有的用DVCC系列还有用启元、伟福这些牌子的。但不管哪个牌子实验箱上基本都集成了8086 CPU模块、8255A芯片、LED/数码管显示模块、按键模块还有步进电机接口。拿到实验箱第一件事绝对不是写代码而是翻原理图查清楚两件事一是8255A的端口地址是多少二是步进电机的控制信号接到了8255A的哪个端口。这两个查错了后面所有代码都是白写。我用的实验箱上8255A的A口地址是0FF28HB口是0FF2AHC口是0FF2AH不对这里要提醒你不同实验箱的地址分配差异非常大。有的实验箱通过译码电路把8255A映射到F880H~F883H有的映射到F800H~F803H。比较常见的一种映射是把A口、B口、C口、控制字寄存器分别放在连续的四个地址上基地址由拨码开关或者跳线决定。所以正确做法是看实验箱原理图上8255A的片选信号CS接在了哪根地址线上再结合地址译码逻辑推算。这一步别偷懒我就见过有同学照着网上代码写地址结果把控制字写到一个根本不存在的端口上电机纹丝不动查了半天才发现问题。2.2 8255A工作在方式0A口输出8255A有三种工作方式这里我们用方式0也就是基本的输入输出方式不需要握手信号直接往端口写数据就行。方式0下A口、B口、C口都可以独立设为输入或输出一个控制字搞定。控制字格式如下D7 1方式设置有效标志D6D5 00A组方式0D4 0A口输出1为输入D3 0C口高四位输出D2 0B组方式0D1 0B口输出D0 0C口低四位输出。因此控制字就是10000000B也就是80H。初始化代码片段8086汇编MOV DX, 0FF2BH ; 控制字寄存器地址以实验箱实际地址为准 MOV AL, 80H ; 方式0A口输出 OUT DX, AL写了这个之后往A口写数据就相当于从A口的8根引脚输出高低电平信号。这一步逻辑很简单但值得多想一层CPU执行OUT指令时地址总线上会出现0FF2BH这个地址译码电路选中8255A控制信号IOR有效数据总线上的80H被锁存到控制寄存器里。这个“OUT指令到底在硬件上做了什么”的过程就是微机系统课程的核心内容答辩时老师很爱问。2.3 ULN2003驱动电路与电机相序8255A的A口输出能力很弱灌电流拉电流也就几毫安级别直接驱动步进电机绕组根本带不动。实验箱上一般会接一片ULN2003它内部是七路达林顿晶体管阵列每路能承受500mA左右的电流用来驱动小型步进电机绰绰有余。ULN2003的输入接8255A的A口低四位输出接电机绕组。ULN2003内部是集电极开路的NPN达林顿管输入为高电平时输出导通到地也就是输出低电平。因此电机绕组的公共端要接电源正极28BYJ-48是5V各相绕组通过ULN2003接地。某个绕组导通就意味着它被拉低电流从正极流过绕组再到地。这个细节直接影响相序表的数值。如果8255A输出高电平表示“导通信号有效”那么相序表中应写1如果后面还加了反相逻辑那就要反着写。我的实验箱上A口输出经反相器再进ULN2003所以实际程序里用的是低电平有效相序。这里必须对着原理图看清楚别盲目抄网上的表。不管电平逻辑怎么变电机内部绕组的通电顺序必须是循环的。四相电机的八拍顺序为A → AB → B → BC → C → CD → D → DA对应到A口低四位D0接A相、D1接B相、D2接C相、D3接D相如果高电平经过反相后有效则控制字序列可能写成TABLE: DB 08H, 0CH, 04H, 06H, 02H, 03H, 01H, 09H如果是高电平直接驱动没有反相则是TABLE: DB 01H, 03H, 02H, 06H, 04H, 0CH, 08H, 09H两种表看起来完全相反但实际效果等同。关键是表的循环顺序要对相邻两个状态之间只有一相发生改变半步这样转子受到的力矩变化最平滑不容易抖动。2.4 为什么开环就够用了步进电机的“锁步”特性课设答辩高频问题之一就是“为什么步进电机开环控制就能保证位置精度它不会丢步吗”这个问题要从步进电机的结构和工作原理回答。步进电机的转子是永磁体定子绕组通电后产生磁场转子会转到与磁场方向对齐的位置。只要负载力矩不超过电机的最大静力矩和动态力矩转子每次都能精确响应一个脉冲的转角这就是所谓的“锁步”特性。换句话说步进电机天生就是“数字执行器”——输入脉冲个数与输出转角满足严格的线性关系没有累计误差。开环控制的风险在于失步启动频率太高、负载过大、加减速太猛都可能导致转子跟不上脉冲节奏丢掉一步甚至原地振荡。所以在开环系统里软件要做的最重要的事情就是控制脉冲频率确保每一步都走得稳。正因为步进电机有这种特殊性我们在做系统设计时才能用“脉冲计数”代替“位置反馈”把复杂问题简化成纯软件问题。这在其他电机的控制上是不可想象的普通直流电机开环控制项多只能控制转速无法精确定位。3. 核心代码用8255A把脉冲序列“挤”出去3.1 相序表与定时方案的整体设计思路软件层面的核心就是把相序表按时间顺序不断送给A口。送得快电机转得快送得慢电机转得慢送得方向反过来电机就反转送固定次数电机就转到指定角度。整体程序我分成了三个模块初始化模块设置8255A方式设置数据段初始化参数控制循环模块读取按键根据按键状态决定发送相序表的方向和延时延时模块/定时模块决定相邻两个相序之间的时间间隔也就是电机的步进频率。最关键的代码是相序发送循环。以正转为例最简单的实现是MOV SI, OFFSET TABLE MOV CX, 8 ; 八拍每发送8个状态完成一个电角度周期 LOOP1: MOV AL, [SI] MOV DX, 0FF28H ; A口地址 OUT DX, AL CALL DELAY INC SI CMP SI, OFFSET TABLE 8 JB LOOP1 MOV SI, OFFSET TABLE ; 循环回表头这个循环每执行一次电机走半步八拍模式的半步对28BYJ-48来说约0.0879°8次走完一个完整电周期。通过修改DELAY的时间就能调速。反转就是倒着查表。我用的技巧是设一个方向标志DIR正转时SI加1反转时SI减1走到表边界就回绕TEST DIR, 1 JZ FORWARD DEC SI CMP SI, OFFSET TABLE - 1 JNZ OK MOV SI, OFFSET TABLE 7 ; 回绕到表尾 JMP OK FORWARD: INC SI CMP SI, OFFSET TABLE 8 JNZ OK MOV SI, OFFSET TABLE OK:这个回绕逻辑一定要写对不然在表边界处会漏拍电机在那个位置会明显顿一下。3.2 软件延时与定时器中断两种方案的取舍调速的实现方式有两种软件延时和定时器中断。软件延时是最直观的做法。每个相序发送后调用一个DELAY子程序里面的循环次数决定了等待时间。以1ms为基本单位循环嵌套实现延时。优点是代码简单、不涉及中断概念适合快速调通功能。缺点是CPU在延时期间一直在空转干不了别的事情而且不同主频下同样的循环代码延时时间不一样实验箱的CPU频率一般约5MHz和PC完全不同所以网上的延时参数基本都要自己调。我实际用了两个嵌套循环内层循环次数固定外层循环次数由转速档位决定DELAY PROC MOV BL, SPEED ; SPEED越小转得越快 DELAY_OUTER: MOV CX, 0010H DELAY_INNER: LOOP DELAY_INNER DEC BL JNZ DELAY_OUTER RET DELAY ENDP调速时只需要改变SPEED这个变量的值。这种方案的可读性很好答辩时讲解也比较容易。定时器中断方案更优雅也更能体现“微机系统”这门课的水平。实验箱上通常有8253/8254定时器可以让它工作在方式3或方式2定时输出一个方波或负脉冲再利用它触发中断。每来一次中断就把相序表向前推进一步。这样CPU就不用傻等了可以在主循环里干按键扫描和数码管刷新。我当时为了赶时间先用软件延时通了后来才改成8253定时中断版本。如果你时间充裕强烈建议直接做定时器版本——不仅运行效果更稳定而且在写实验报告的时候关于“如何与低速外设配合”这个章节会充实很多。硬件连接的典型设置是8253的通道0接一个分频值GATE接高电平CLK接实验箱时钟源OUT接到8259A中断控制器的某个IRQ端。程序初始化时往8253写入控制字和初值然后开中断在中断服务程序里发送相序。3.3 按键处理与状态显示按键和显示这部分是实验室设备的“标配”。实验箱上一般有独立按键和数码管通过8255A的B口、C口连接。我的方案是B口接按键设置为输入C口接数码管段码设置为输出A口继续接电机驱动。主循环的伪代码如下初始化8255A 设置初始方向为正转初始速度档位为3 死循环: 扫描按键 如果按下“正转”键: 方向标志清零运行标志置1 如果按下“反转”键: 方向标志置1运行标志置1 如果按下“加速”键: 速度档位减1延时缩短 如果按下“减速”键: 速度档位加1延时增长 如果按下“停止”键: 运行标志清零停止发脉冲 如果运行标志1: 按当前方向发送一相步进脉冲 刷新数码管显示当前状态这里要强调一个经验按键扫描和脉冲发送不能放在同一个简单顺序里否则会出现一种情况——按下按键时电机停一拍或者电机运行期间按键根本扫不到。最简单的解决办法是让按键扫描和脉冲发送交替执行主循环每转一圈最多只发一个脉冲再扫描一次按键。对于步进电机这种低速设备脉冲频率本来就不高这种交替处理完全够用而且逻辑非常清晰。数码管显示方面由于我用的实验箱是共阳数码管段码表稍微特殊一点。要注意的是显示刷新速度太慢会闪烁太快则浪费CPU时间我用简单的软件延时控制在几百微秒的刷新周期就能稳定显示。显示内容我放在两个变量里DIR方向1表示正转2表示反转和SPEED速度档位方便调试时观察。3.4 定位控制发够步数就停课设里如果只是“连续运转”功能上偏单薄。我加入了一个“设置步数”的功能通过一个按键进入步数设置模式用加减键调整步数值再按启动键电机就转指定步数后停下。定位功能用汇编实现并不复杂关键是计数逻辑MOV CX, STEPS ; 目标步数 STEP_LOOP: CALL OUTPUT_ONE_STEP ; 发一个八拍状态半步 DEC CX JNZ STEP_LOOP CALL MOTOR_STOP ; 停止发脉冲但保持最后相序这个“保持最后相序”很重要。如果停止后把端口清零所有绕组都断电电机会失去保持力矩轴会被外力推动位置就丢了。正确的做法是停在最后一个相序状态让电机绕组继续保持通电状态这就是“锁相”保持。在代码上OUTPUT_ONE_STEP每次发送相序后把当前相序值保存在内存的一个变量里MOTOR_STOP时不再更新相序但也不把A口清零这样电机就能停在原地。定位精度方面因为我用的是八拍模式一个脉冲对应半步。28BYJ-48的原始步距角是5.625°/半步不对严格说它的步距角是5.625°/64也就是0.0879°。这个数字是减速箱带来的结果电机本体是每步11.25°经1/64减速后输出轴每步约0.1758°。八拍模式下每两个相序状态之间其实对应的是半步所以输出轴每一步约0.0879°。你可以在报告里计算“转一整圈需要多少个脉冲”——64×644096个八拍脉冲。这些计算在报告里写清楚会很加分。4. 实测阶段的坑不转、抖动、失步的排查链路4.1 电机完全不动从端口电压开始查写完之后首次上电测试电机纹丝不动。这是课设最经典的失败场景也是排查链路最有价值的一段。我当时的排查顺序是第一步先用万用表测8255A的A口引脚电压在程序里手动写一个死循环每隔一段时间往A口送0FFH然后再送00H看引脚是否有高低电平变化。如果没有问题出在程序初始化或地址错。如果有电平变化说明CPU到8255A这一路是通的。第二步测ULN2003输入端的信号。如果8255A输出正常但ULN2003输入没有信号可能是连接线没插好或者接触不良。实验箱的排线经常有松动按下、拔出、重新插紧是最常见也最容易被忽略的解决手段。第三步测ULN2003输出端。输出端的预期是对应导通的绕组输出低电平其余是高阻或高电平。如果输入端有信号而输出没有很可能是ULN2003的公共端COM没有接电源或者芯片本身烧了。ULN2003内部自带续流二极管COM端接电源正极时才能正常续流不接COM端驱动感性负载很容易损坏芯片。在我这次的排查中最终发现的问题很尴尬——8255A的设置正确、相序表正确、程序逻辑正确但电机的5V电源没有接。实验箱的步进电机接口上有一个单独的电源跳线帽默认是断开的我忘了插上去。电机绕组没有供电程序发出花来也不会转。这个经历看着好笑但很有代表性每次遇到“不转”的问题第一件事就是检查电机电源、地线、公共端。百分之六七十的“不转”都出在供电上。4.2 电机抖动但不连续转动通电后电机有了反应但不是顺畅地旋转而是原地剧烈振动轴来回摆动好像在“挣扎”。这个问题我在实验室见过好几个同学遇到过原因通常是相序表顺序错了。四相电机的相序必须严格按A→AB→B→BC→C→CD→D→DA循环。如果表中某相邻两项并不是相邻状态比如直接从A跳到C转子会受到一个不连续的力矩就会往回跳。尤其是当相序表写成了A→AC→C→CA这种交叉相序电机转子会被前后两个方向的磁场反复拉扯表现出来就是抖动不转。排查方法是借助LED显示。把8255A的输出数据同时接到8个LED上实验箱通常自带这个功能程序单步运行、手动控制每次发送一个相序状态肉眼观察LED的亮灭顺序是否符合预期。LED从A相到B相到C相到D相应该像流水灯一样依次点亮而不是乱跳。还有一种情况会导致抖动但原因完全不同相序表是好的但相邻两个相序之间的延时太短电机还没完成当前半步的过渡就收到了下一个脉冲。尤其是低速档时转子本身有惯性频率一旦超过电机的启动频率范围就会出现“跟不上了”的症状。28BYJ-48是减速电机它的空载启动频率通常比较低几十到几百赫兹范围如果你一上来就按高速档启动就会在启动阶段就失步抖动。解决方法是先低速启动稳定后再逐渐加速。4.3 高速跑起来就失步我的程序在低速档运行很平稳但把速度调到最高档后出现了两种现象一种是电机干脆停转还有一种是我在定位模式下高速跑电机实际转过的角度明显小于设定角度也就是丢步了。这个问题的本质是开环控制的经典局限启动频率太高。步进电机的启动频率和运行频率是两回事。运行频率可以比较高但启动时必须从低频率起步然后逐渐升频这就是“加减速控制”。如果加电之后第一个脉冲就按800Hz以上的节奏发转子来不及建立起足够的加速度就会失步。最简单的修复方式是“软启动”程序启动时无论选择哪个速度档位都从最低速度档开始每隔一段固定时间自动提升一档直到达到目标速度。比如从最早延时值开始发64个脉冲然后延时减半再发64个再减半逐步过渡到目标速度。这样做的原理是让转子在低频率下有足够时间建立起角速度积累动量后再提高频率就更容易跟上。精确的加减速控制需要查矩频特性曲线课设阶段不需要做到那么细软启动已经足够满足绝大部分演示场景。我在报告里写了这样一句话“本系统采用阶梯式升频启动方式在启动阶段逐步缩短相序更新间隔使电机从静止状态平滑过渡到目标转速避免因启动频率超过最大启动频率而导致的失步现象。”这句话后来被老师圈了出来说思路正确。4.4 复位瞬间电机乱跳还有一个现象比较隐蔽按实验箱的复位键之后电机有时候会“咔咔”乱跳两下然后才进入正常状态。这是因为复位瞬间CPU内部寄存器和8255A的端口都处于未定义状态A口可能随机输出一些电平导致电机绕组通断组合随机变化。电机在复位瞬间根本不受程序控制所以会产生异常动作。解决方法是硬件和软件双重手段硬件上让8255A的复位端与CPU的复位信号同步这样复位一结束8255A就回到初始状态软件上在程序最开始不急着发相序而是先把A口的数据设为全零或全部线圈同时上电的稳定状态延时几百毫秒后再进入主循环。如果实验箱没有专门的控制信号来自定义至少软件层面要加这个“安全初始化”步骤。我在主程序的数据段里专门留了一个变量MOTOR_PHASE默认为0主程序一开始就执行初始化端口并写入安全状态然后延时300ms再做8255A的设置和键盘扫描。这一步看起来不起眼但能避免演示过程中按复位键后电机乱跳的尴尬场面。5. 报告和答辩中值得展开的几个点5.1 开环控制系统的精度边界答辩时老师会问“开环控制有什么缺点什么情况下不适用”。这个问题如果只回答“没反馈、会失步”就显得太浅了。我希望贡献一个更适合课设的视角开环控制真正的问题不是单步精度而是“发生丢步后系统不会自我纠正”。具体来说步进电机的单步精度其实很高只要不丢步累计角度和理论值之间的误差是很小的。但一旦因为负载突变、瞬时堵转或启动频率过高而发生丢步后续所有位置计算就全部偏移了而且这个误差会一直积累下去。相比之下闭环带编码器反馈系统在每次换相时可以检查实际位置发现偏差立即补偿甚至能识别出堵转和失步状态。对于课设这种轻负载、低速、稳定性要求不高的场景开环完全够用但在工业机床进给、3D打印机高精度运动等场景通常要么用高可靠性的步进驱动加闭环反馈要么直接用伺服系统。另外老师还可能追问“如果负载改变了开环系统的性能会怎么变”这时候要能答出步进电机的矩频特性曲线是固定的负载扭矩变大会导致可用最高运行频率下降最大启动频率也会下降。所以开环系统的速度上限本质上受负载影响留的裕量不够就容易失步。用“矩频特性”这个词答辩档次一下就上去了。5.2 把“转速—延时”的实测数据整理成报告素材我建议在调试阶段花一点时间做个简单的数据表用不同延时值跑20圈记录实际耗时的秒数然后换算成每秒的步数。这些数据在报告里呈现出来会很有说服力。我当时的延时值范围用的是从0CH到64H对应的转速数据大致是每分钟十几转到一百多转。注意这个转速是输出轴的转速减速后的脉冲频率要乘以64或4096才是电机本体的脉冲频率数据整理的时候不要搞混。具体计算方式如果八拍模式下每4096个脉冲转一圈对应28BYJ-48延时为T毫秒时每秒的脉冲数为1000/T输出轴每秒转圈数为(1000/T)/4096每分钟就是(1000/T)/4096×60。比如T10ms时约1.46转/分钟这也是为什么减速步进电机转速看起来这么慢但它能带动的扭矩要高很多。这个表整理好放到实验报告里能体现出你真正做了实测。5.3 可扩展的方向与后续优化空间答辩的最后老师通常会问“你这个系统还能怎么改进”。有些方向显得太泛泛而谈我建议结合自己实际做过的思考来说一是给电机加编码器组成半闭环或全闭环检测实际位置发现失步立即报警或补偿二是增加细分驱动用专用的步进驱动芯片比如DRV8825或A4988通过电流斩波实现16细分甚至32细分让电机运行更平滑、噪声更小三是换成两相混合式步进电机加配套驱动器响应更快、扭矩更大也更接近工业实际应用四是用EtherCAT等工业总线来下发脉冲指令把多台电机接入同一个运动控制网络——但这个方向对课设来说跨度偏大可以作为了解不一定要展开。还有一个可落地的改进思路就是用高级语言生成控制序列表再下载到实验箱或者在PC端写个小界面通过串口给8086实验箱下发“转90度”“反转10圈”这类指令。这样把“上位机下位机”的架构引入课设内容会丰富不少也更好展示。根据我个人做完整个课设的体会这套开环控制系统看似简单但它的调试过程覆盖了微机接口课程的大多数核心知识点地址译码、I/O读写时序、并行接口编程、定时器/中断协作、外设驱动与抗干扰处理。你在实验箱上踩过的每一个坑回头来看都是对这门课最生动的一次理解。最后提醒一句接线之前多看一眼原理图查故障时先查电源写代码时先把相序表掰扯清楚这三件事做好了这个课设基本就稳了。
返回列表