尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

STM32驱动振镜打标:XY2-100协议与AM26LS31差分信号链详解

发布时间:2026/9/24 11:52:27

资讯中心
01
ARTICLE

STM32驱动振镜打标:XY2-100协议与AM26LS31差分信号链详解

STM32驱动振镜打标:XY2-100协议与AM26LS31差分信号链详解
直接聊结论激光打标/雕刻系统的信号链如果只留第一道分水岭十有八九会是“STM32 能输出 PWM、能拉 GPIO但接上振镜驱动器就是带不动”。我在自己从零搭振镜控制的时候就卡在这里后来把 XY2-100 协议和差分物理层理清楚问题才真正解开。这篇就把这条信号链完整拆开讲一遍从 STM32F103 产生时序到 AM26LS31 转成差分信号再到振镜驱动器能识别的完整链路适合正在自研振镜控制板、做低成本打标机实验或者只是想搞清楚振镜卡内部原理的硬件/嵌入式工程师。1. 为什么振镜信号链是打标系统的第一道分水岭先摆一下整个打标系统的骨架。一台最基础的振镜式激光打标机分成两大部分一部分负责“光”包括激光器、扩束镜、聚焦镜另一部分负责“让光去对的地方”这就是振镜扫描系统。振镜扫描系统又由振镜电机和振镜驱动器组成。驱动器接受控制板给出的位置指令把电压/数字信号转换成电机线圈电流驱动镜片偏转激光焦点随即在工件上画出图形。上位机或运动控制软件做的工作是把图形解析成一条条线段再把线段拆成密集的坐标点。拆出来的坐标点最终要通过某一种接口送给振镜驱动器。老一代模拟振镜用 ±10V 模拟电压电压越高镜片偏转越大数字振镜则普遍采用差分串行协议XY2-100 是出现频率最高的一个。很多人的第一步是把 STM32F103 和振镜驱动器用杜邦线连起来向数据脚输出高/低电平用定时器输出一个 PWM 做时钟接着发现振镜要么不动要么乱抖。原因不是代码太烂而是没有理解两个层次的问题协议层振镜驱动器要的不是普通 PWM而是符合 XY2-100 的“时钟 数据 同步”串行帧格式。物理层振镜驱动器的 XY2-100 接口绝大多数是差分形式的 RS-422/RS-485 兼容输入直接把单片机 GPIO 接上去共模噪声、地电位差、长线反射全都会压过来。STM32F103 在这里的角色是“协议产生器”AM26LS31 是“物理层驱动芯片”两者配合才能把逻辑信号变成能在几十厘米甚至几米线缆里可靠传输的差分信号。搞明白这条链路后续不管是换协议还是换主控芯片思路都是通用的。2. XY2-100 时序拆解SYNC、CLOCK、DATA、CHANNEL 到底在传什么2.1 四个信号的分工XY2-100 虽然名字里带“100”但它并不是一个像 I2C 那样死板的标准协议。不同振镜厂商实现有 16 位和 20 位的差别时钟频率上限也不完全一致。无论位宽怎么变最核心的四个信号是固定的信号方向作用CLOCK±控制板 → 驱动器位时钟驱动接收端一位一位采样数据DATA±控制板 → 驱动器串行位置数据通常是高位先出SYNC±控制板 → 驱动器帧同步标记一帧位置数据的开始/结束CHANNEL±控制板 → 驱动器通道选择用于多轴/多驱动器共用总线时分复用这四个信号不是孤立的必须组合成完整帧来理解。所谓“帧”可以理解成一次完整的位置更新一帧数据里只传输一个轴的目标位置有些实现会把 X、Y 两个轴放入一帧的多个通道里。帧与帧之间的间隔决定了坐标更新率也就是打标速度的上限。2.2 常见的 16 位帧格式以最常见、也是 STM32 实现最顺手的 16 位位置数据帧为例一次传输过程是这样的SYNC 置高通知驱动器“新的一帧要开始了”。CLOCK 连续输出 16 个脉冲。在每个 CLOCK 的上升沿或下降沿看驱动器手册之前DATA 线上摆好当前位。16 个数据位全部移出后SYNC 拉低驱动器把收到的 16 位数据锁存到当前位置寄存器。时序看起来是下面这个样子的简化示意SYNC ____▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔____ CLK ____▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁____ DATA ____X D15 D14 D13 ... D1 D0 X____注意这个“锁存”动作很关键。它决定了 XY2-100 不能像串口那样按字节流看而必须以帧为单位对齐。如果同步极性写反或者同步宽度不对驱动器收到的数据位虽然顺序对但帧边界错位最终结果就是振镜偏转到一个完全错误的位置甚至乱抖。2.3 位宽到底是 16 还是 20这是新手最容易懵的地方。XY2-100 这个名字的原始定义里位置字其实是 20 位其中若干位用作符号和标志实际位置分辨率可能达到 16~19 位。国内很多数字振镜驱动器比如常见的配套 JPT、瑞镭、创鑫等激光器方案的振镜驱动板实际使用时也常按 20 位去接收。我在项目中采用过一个稳妥策略代码里封装一帧数据的位数参数默认 16 位可以在顶层配置为 20 位。发送 16 位时数据值按带符号整数处理范围是 -32768 到 32767对应镜片机械偏转范围的两端。发送 20 位时用带符号扩展的方式把 16 位坐标扩展成 20 位int32_t value_20bit (int32_t)x; // x 为 int16_t // 符号扩展后低 20 位有效范围 -524288~524287这样遇到 20 位驱动器时改一个参数就能适配不需要重写时序生成函数。至于你的驱动器支持哪种位宽不要猜直接看数据手册里的 timing diagram。2.4 CHANNEL 信号解决的场景CHANNEL 信号有时被忽略但在多轴系统里非常有用。振镜系统一般有两轴X 轴控制水平偏转Y 轴控制垂直偏转。如果每个轴单独拉一组 CLOCK/DATA 线主控引脚占用多线缆也多。CHANNEL 线的做法是让多个驱动器共享同一组 CLOCK 和 DATA靠 CHANNEL 表示“这一帧是给谁的”。比如发送 X 轴数据时CHANNEL 拉低发送 Y 轴数据时CHANNEL 拉高。每个驱动器的接收端只在自己对应通道电平下采样。实际应用中有些驱动器即使没有真正用到 CHANNEL 线也会要求把这根线接上以避免悬空噪声误触发。所以就算你的系统只有一路振镜我也建议把 CHANNEL 引脚显式拉高或者拉低而不是悬空。3. AM26LS31 在链路中的作用逻辑电平转差分3.1 为什么不能拿 GPIO 直接长线传输STM32F103 的 GPIO 输出的是 3.3V 单端信号。单端信号的意思是接收端判断高/低电平靠的是信号线上的电压和地之间的差值。如果控制板和振镜驱动器之间距离一长或者旁边有激光电源、伺服驱动器这类强干扰源信号线上的地电位会和控制板的地电位出现偏差接收端看到的就是“一个等于信号电压的共模噪声叠在信号上”轻则波形变形重则完全误码。差分传输绕开了这个问题。AM26LS31 把一路单端 TTL/CMOS 信号转换成两路完全反相的差分输出 Y 和 Z。接收端不关心 Y 对地的绝对电压是多少只关心 Y-Z 之间的差值。激光电源干扰过来的共模噪声在两根线上同时出现接收端一相减就抵消了。这就好比两个人打电话单端是“一个人说话声音大小靠他嗓门大小判断”差分是“两个人一个说正话一个说反话听的人只比较两个人的音量差”。哪怕周围环境很吵只要两个声音同时被干扰差值依然能保留原始信息。3.2 AM26LS31 的典型接线AM26LS31 是一片四路差分线驱动器封装有 SOP16、DIP16 等引脚逻辑不复杂。每一路的基本结构是输入 A ──► 输出 Y正相 └─► 输出 Z反相片上有两个使能端G 和 /G用来统一控制所有输出。5V 供电即可工作STM32 的 GPIO 输出高电平约 3.3V已经超过 AM26LS31 作为 TTL 输入的 VIH 阈值约 2V可以直接驱动不需要再电平转换。一个 AM26LS31 正好有 4 路对应 XY2-100 一轴的 CLOCK、DATA、SYNC、CHANNEL 四个差分信号。如果要做 X/Y 两轴独立信号线就需要两片。AM26LS31 输入引脚STM32 GPIO差分输出接双绞线1APA41Y / 1ZCLOCK±2APA52Y / 2ZDATA±3APA63Y / 3ZSYNC±4APA74Y / 4ZCHANNEL±注意 AM26LS31 输出端是推挽结构的差分对不是开漏所以不需要上拉电阻。输出端如果不接负载芯片也依然会输出差分电压。连接振镜驱动器时通常双绞线到达接收端后在接收端加一个 120Ω 左右的终端电阻用来吸收线缆末端的反射能量避免高速时钟边沿产生振铃。3.3 接收端要靠什么芯片接回去振镜驱动器端通常已经集成了差分接收电路常见芯片是 AM26LS32 或兼容的 RS-422 接收器。AM26LS32 内部有四个接收器每个接收器把差分输入转成单端 TTL 输出给驱动器内部的 FPGA/DSP。接收端不是简单地把 Y、Z 两根线剥皮接进去就行还有两个细节值得注意终端电阻距离很短小于 20cm时可以不加如果线长超过 0.5m终端电阻基本是必须的。直接焊一个 120Ω 电阻在 Y-Z 之间就能明显改善波形。接收端的共模电压范围RS-422 标准允许接收端的地电位相对发送端有 ±7V 左右偏移。听起来很宽松但我建议有条件还是让控制板地和驱动器地在供电端共地不要只靠差分信号硬扛。3.4 怎么判断物理层是否搭对在没有振镜驱动器的情况下也可以用 AM26LS32 接收器加一个示波器来验证发送端。更直接的办法是拿差分探头测 AM26LS31 的 Y、Z 输出端或者用双通道普通探头一个接 Y、一个接 Z示波器用通道 A 减通道 B 的数学功能直接看差分波形。如果看到的是幅度约 2V 以上、上升沿清晰、没有明显台阶和振铃的方波物理层基本是健康的。如果幅度低、有大量毛刺、边沿严重回勾优先查终端电阻、屏蔽层接地和电源去耦。4. STM32F103 生成 XY2-100 的两种常用实现4.1 方案 A定时器中断 GPIO 逐位翻转最容易理解和调试这个方法思路最直接定一个定时器让它按 XY2-100 的时钟频率产生中断每次中断里翻转 CLOCK、设置当前位的数据。用 STM32F103 的定时器中断在 72MHz 主频下做到 2MHz 的时钟翻转频率完全可行。代码如下注意这是简化的核心逻辑#define XY_CLK_H() GPIOB-BSRR GPIO_PIN_0 #define XY_CLK_L() GPIOB-BRR GPIO_PIN_0 #define XY_SYNC_H() GPIOB-BSRR GPIO_PIN_1 #define XY_SYNC_L() GPIOB-BRR GPIO_PIN_1 #define XY_DATA_H() GPIOB-BSRR GPIO_PIN_2 #define XY_DATA_L() GPIOB-BRR GPIO_PIN_2 volatile uint16_t xy_data; // 待发送的 16 位位置数据 volatile int xy_bit; // 当前发送到第几位 void TIM3_IRQHandler(void) { if (TIM3-SR TIM_SR_UIF) { TIM3-SR ~TIM_SR_UIF; if (xy_bit 0) { // 先放数据再给时钟上升沿 if (xy_data (1 xy_bit)) XY_DATA_H(); else XY_DATA_L(); XY_CLK_H(); XY_CLK_L(); xy_bit--; } else { // 一帧结束同步拉低锁存数据 XY_SYNC_L(); // 这里可以置位标志位通知主循环发下一帧 frame_done 1; TIM3-CR1 ~TIM_CR1_CEN; // 停止定时器 } } } void XY_SendFrame(uint16_t pos) { while (frame_done 0 timer_running); xy_data pos; xy_bit 15; XY_SYNC_H(); frame_done 0; TIM3-CR1 | TIM_CR1_CEN; }这个方案的优点是非常直观逻辑全在明处非常适合第一版调通。缺点是两个中断服务函数里干活太多如果还要同时处理串口、激光开关、插补计算中断会占掉大量 CPU 时间。实测在 2MHz 时钟下发送一帧 16 位数据大约 8µs定时器中断每次执行时间如果控制在 1µs 以内点率能到比较可用的范围。但如果要把点率推到几十 kHz 以上还要跑插补算法这个方案就会捉襟见肘。4.2 方案 BDMA SPI 定时器高帧率推荐要解放 CPU可以用 DMA 把预先准备好的“定时器更新事件触发引脚翻转”的数据灌给 GPIO。思路是把一帧里每一位的状态预先组织成一个 32 位 GPIO 寄存器值数组。定时器以 XY2-100 的位时钟为更新频率触发 DMA。DMA 每次传输把这个数组中的一个值写到 GPIO 的 BSRR/BRR 寄存器完成引脚翻转。例如 STM32F103 的 GPIOB BSRR 地址 0x40010C10BRR 地址 0x40010C14。数组里每个元素可以是uint32_t frame_bits[16]; // 示例第 i 位数据为高CLOCK 低时写 BSRRCLOCK 高时写 BRR具体如何配置 DMA 通道和定时器内联每个项目差异较大这里不贴完整代码重点是要理解它的核心逻辑DMA 以固定速率把内存中的位模式“搬运”到引脚和 XY2-100 要求的时钟时序一一对应。这个方案的最大优势是 CPU 只负责准备数据实际信号生成完全由定时器和 DMA 硬件完成位置更新率可以做得更高CPU 还有余量去跑直线插补、功率控制、串口交互。我在实际项目中是用 STM32F103 内部定时器触发 DMA传输完成后触发一次半传输/完全传输中断在中断里填充下一帧数据做到了 40kHz 以上的坐标更新率CPU 占用依然很低。4.3 为什么有人用 SPI 做却总是对不齐网上也有人直接用 SPI 的 MOSI 输出数据、SCLK 输出时钟来做。理论上可行但会踩一个坑XY2-100 的时钟和数据边沿相对关系和 SPI 的 CPOL/CPHA 四种模式并不是天然对齐的。SPI 主机在某个时钟沿送出数据从机在另一个沿采样这个配合只适合 SPI 从机XY2-100 接收端要求的是“数据先稳定然后时钟某个边沿采样”。两者看起来都叫“时钟 数据”但时序约束不一样直接拿 SPI 模组去拼经常出现数据与时钟边沿对不齐驱动器采样到了毛刺。所以更可控的路径是把 SPI 当作纯粹的“数据移位输出”CLOCK 信号则用定时器 PWM 产生并软件保证两个外设的相位关系。DMA 负责把数据从内存连续送到 SPI 数据寄存器定时器负责给出一位一位的时钟。这样既绕开了软件中断开销又不像纯 GPIO 那样每帧都要 CPU 介入。4.4 数据准备和插补的注意点时序生成只是信号链的前半段真正让电机跑得顺畅的还有坐标插补。STM32F103 算力有限不建议在中等复杂图形上做太高级的样条插补。实用做法是上位机或 PC 端把图形预处理成稠密点序列STM32 只做直线插补的切分和下发。举个例子一段从 (0, 0) 到 (1000, 0) 的线段打标速度要求 2000mm/s点距 0.05mm那么每秒要输出 40000 个点。STM32 按定时器节拍每 25µs 取一个点通过插补公式计算当前坐标填入发送缓冲区。注意 XY2-100 的一帧数据发送本身是异步的缓冲区一定要用双缓冲或环形队列否则上一帧还没发完下一帧已经开始覆盖数据就会出现振镜一顿一顿的现象。5. 完整信号链搭建与示波器验证5.1 一套可落地的接线表我用 STM32F103C8T6 最小系统板加一片 AM26LS31 模块搭过一版接线如下供直接参考信号STM32F103 引脚AM26LS31 输入引脚驱动器接线端CLOCKPA41ACLOCK± 差分对DATAPA52ADATA± 差分对SYNCPA63ASYNC± 差分对CHANNELPA74A固定高/低电平CHANNEL± 差分对STM32 与 AM26LS31 之间尽量短距离连接杜邦线长度控制在 10cm 内。AM26LS31 的 5V 供电和 STM32 的 5V或外部稳压 5V共地。差分输出到振镜驱动器之间用双绞线线径 24AWG 左右屏蔽层如果接就在控制板端单端接地。5.2 上电前先做的三项检查第一确认所有差分引脚没有接反。Y/Z 或 A/B 标号接反接收端看到的就是反相波形驱动器会认为数据位全部倒置。第二确认 CHANNEL 引脚不是悬空。没有实际通道切换需求时把它在代码里固定为高或低避免驱动器误采样。第三确认振镜驱动器接收端的终端电阻。如果驱动器没有内置终端电阻就在差分输入端并一个 120Ω 电阻。没有它2MHz 时钟沿的反射会直接导致数据抖动。5.3 用示波器看哪几个关键波形不用一上来就接振镜先把 STM32 和 AM26LS31 这一级调试好。第一个测点是 AM26LS31 的输入端也就是 STM32 的 GPIO 引脚确认 SYNC 能周期性地拉高、CLOCK 有连续脉冲、DATA 上有随数据变化的电平。第二个测点是 AM26LS31 的输出端用差分方式观察 CLOCK±确认差分幅度正常。第三个测点是接收端接上长线后观察 DATA± 在 CLOCK 边沿的时刻是否稳定。如果示波器只有一个普通探头也可以把探头接地夹子夹在控制板的地上分别测 Y 和 Z 两根线再在脑子或纸上做减法。这种方法能看到毛刺但不如真正的差分探头准确。5.4 一个简单的验证程序流程初始化 GPIO 后先不放插补直接让程序每 10ms 发送一组固定的递增坐标比如从 0 开始每次加 100。上电后用示波器观察 DATA 波形是否只在一帧间隔内变化、SYNC 宽度是否稳定、CLOCK 频率是否符合预期。这一阶段只要逻辑上对振镜就应该按比例偏转。如果振镜完全不动优先怀疑 SYNC 极性。XY2-100 不同驱动器对 SYNC 的有效电平定义不一样有的高有效有的低有效这也是我自己第一次调板子时卡了最久的问题。6. 实际使用中容易忽略的坑从信号质量到项目管理6.1 终端电阻超过 300Ω 等于没接很多人知道要加终端电阻但随手找了一个 10kΩ 电位器或 1kΩ 电阻就并上去。对 2MHz 时钟来说终端电阻要和双绞线特征阻抗匹配才有意义。RS-422 双绞线常见特征阻抗约 100~120Ω所以终端电阻取 120Ω 最合适最大不要超过 330Ω。实测用 1kΩ 和 120Ω 对比时钟上升沿的过冲和振铃差距非常明显。6.2 地线处理要遵循“一段一段来”差分传输能抵消共模干扰但不代表可以不共地。RS-422 接收器的输入共模范围看起来有 ±7V但那是标准极限实际驱动器为了抗静电输入保护电路可能限制得更窄。稳妥做法是控制板电源、AM26LS31 电源、振镜驱动器电源全部在同一个配电接入点共地。如果振镜驱动器和激光电源离得远中间用专门的地线连接不要只靠差分线内部的地线承担大电流回流。6.3 位置值范围和符号别搞反XY2-100 发送的是有符号位置数据。16 位模式下0x7FFF 和 0x8000 往往对应机械角度的两极0 是中位。如果直接把加速度、速度转换出来的无符号数填进去等于告诉振镜“偏到极限”轻则发出异响重则撞到机械限位。最好在初始化时先发 0 值确认镜片回到中位再递增测试。6.4 激光控制和位置输出同步是另一条容易漏的线打标不只是“振镜动”还要在合适的时候打开激光。激光器通常需要两路信号一路 TTL 开关控制激光出光一路 PWM 模拟信号控制功率。这两路信号与 XY2-100 的位置数据必须同步如果激光在振镜还在快速移动时点亮图形就会产生圆角或拖尾。实际工程中我会在帧发送完成中断里同时更新激光开关状态。比如插补器算出当前位置后同时算出这一点的激光功率在下一帧同步时随位置一起输出。STM32F103 的定时器 PWM 用于功率控制正好占空比更新通过 DMA 或直接寄存器写入保证不占用太多 CPU。6.5 不要把协议文档看成完全一致的真理XY2-100 只是一个广为流传的名字不是国际标准。同一片驱动板上固件版本不同都可能导致 SYNC 极性、位宽、CHANNEL 时序发生变化。我接触过的驱动器里有的 CLOCK 上升沿采样有的下降沿采样 SYNC 有的拉高表示启动有的拉低表示锁存。所以做工程时第一优先级永远是手里的驱动器数据手册而不是网上随手搜到的某个框架图。如果手册写得不清楚直接问厂商要例程和 timing diagram比盲调快得多。6.6 调试顺序决定了效率我的调板顺序一直是先调试物理层再调试协议时序最后才接振镜。物理层没有调好之前协议层再正确也是浪费时间。每一步用示波器确认一个事实AM26LS31 输入端有正确 TTL 波形。AM26LS31 输出端有正确差分波形。接收端差分波形无异常毛刺、抖动。用逻辑分析仪抓 CLOCK/DATA/SYNC确认帧格式和驱动手册一致。再接振镜负载小幅坐标偏移测试响应。这套流程走下来绝大多数问题都出在第二步到第四步之间很少真正需要动电机。回头再看我自己最初踩过的坑最浪费时间的反而不是芯片选型或代码复杂度而是没有把协议和物理层拆开去判断。只要把 STM32F103 产生时序、AM26LS31 做差分驱动、接收端按帧锁存这三段各自验证清楚整个信号链就通了。后续如果再遇到振镜不听话优先怀疑的也就那几处SYNC 极性、终端电阻、数据符号范围、CHANNEL 悬空。把这些都处理掉剩下真正要做难的才是图形算法和工艺参数本身。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。