
在做欧姆龙 NJ501 项目时很多朋友会遇到一个“看起来不难实际一调试就卡住”的需求让 PLC 通过串口接收扫码枪、仪表、传感器或者第三方控制器主动发来的数据。网上关于欧姆龙串口通信的例子大部分集中在 CP1H、CP1L 这类小型机而 NJ501 配合 Sysmac Studio 的实现思路资料相对零散。这篇教程就把“欧姆龙NJ501实现无协议串口通信接收”的完整流程整理成图文版和视频讲解互补方便你边看边操作。文章会覆盖硬件接线、Sysmac Studio 串口参数配置、无协议通信指令触发方式、接收后的数据解析思路、联机调试方法和常见坑点排查。如果你以前用过 CX-Programmer 操作 CJ/CP 系列再看 NJ501 会觉得很多地方不太一样比如不再直接操作 CIO 区和 DM 区地址而是通过变量编程。这一点会贯穿全文重点讲解。1. 无协议串口通信到底是什么1.1 无协议通信的概念“无协议”并不等于“没有协议”而是指 PLC 的串口不启用欧姆龙专用的 HostLink、Modbus-RTU 等现成协议把串口当作一个透明的收发通道由用户程序自己组织要发送的数据也由用户程序自己解析接收到的字节流。比如扫码枪通过 RS232 发来一段 ASCII 字符1234567890\r\nPLC 收到这串字节后并不关心它的业务含义只负责把字节按顺序放进接收缓冲区。至于哪些字节是条码内容、哪些字节是结束符、需不需要做校验全部由你在程序里处理。这类通信非常适合以下几种设备RS232/RS485 接口的扫码枪或读码器电子秤、地磅仪表温湿度传感器、压力变送器激光测距传感器第三方单片机控制板老式打印机、标签机HostLink 优势在于稳定性高、有现成指令但它是欧姆龙私有协议第三方设备未必支持。Modbus-RTU 适合标准工业仪表不过很多简单串口设备只支持自定义文本帧。所以无协议模式成为串口接入中最灵活的手段。1.2 NJ501 与 CJ/CP 系列的编程差异用 NJ501 做串口通信和老一代 PLC 的差异不仅仅是软件从 CX-One 换成了 Sysmac Studio更核心的是编程习惯从“软元件地址”变成了“变量”。在 CP1H 上我们经常会写类似下面的程序MOV #1234 D100但在 NJ/NX 系列上Sysmac Studio 默认推荐用全局变量、数组、结构体程序里不再直接频繁操作绝对地址。例如你要保存接收的 100 个字节最好在全局变量表中定义gbRecvBuffer : ARRAY[0..99] OF BYTE; gbRecvLen : WORD; gbRecvDone : BOOL;这样做的好处是可读性强、程序移植方便坏处是很多习惯了地址式编程的工程师刚上手时会觉得“找不到数据放在哪里”。理解这一点对后面的串口接收调试非常重要。另一个容易踩坑的地方是NJ501 CPU 本体的通信接口一般以 EtherNet/IP 为主RS232/RS485 串口通常需要加装串行通信单元或选择带串口的扩展配置。因此配置无协议通信时首先要确认 CPU 机架上是否有可用的串口单元。1.3 为什么接收比发送更容易出问题串口发送是主动行为程序只要按顺序把数据写到发送缓冲区设置好触发信号设备就能收到。接收则完全不同PLC 不知道设备什么时候会发数据、一次发多长、是不是发到一半就停顿甚至不知道发过来的数据是不是完整的一帧。如果接收缓冲区设置太小会发生数据截断如果结束码设置不对会把两帧数据当成一帧处理如果触发指令的方式不对又可能出现重复接收。所以做接收功能时重点要思考三个问题什么时候开始接收什么时候认为一帧数据接收完成接收完成后怎么把数据安全地交给业务逻辑后面的章节会围绕这三个问题展开。2. 硬件准备与连接方式2.1 硬件环境清单按照常见工程配置你需要准备以下内容硬件/软件说明欧姆龙 NJ501 CPU例如 NJ501-□□00不同尾缀影响运动轴数量和内存通信设置思路一致串行通信单元例如 CJ1W-SCU41-V1 等 CJ 系列串行通信单元挂在 CPU 机架上Sysmac Studio欧姆龙 NJ/NX 系列编程软件版本以实际安装为准电脑与 PLC 连接线一般通过 CPU 内置 EtherNet/IP 口或 USB 口下载程序串口调试工具USB 转 RS232 线、串口助手或扫码枪实际设备需要说明的是不同 NJ501 机型和不同串行通信单元的配置界面可能有细微差别但“把某个串口设置为无协议模式、然后通过通信指令收发”的思路是一致的。如果你的机器已经自带串口可以直接跳过加装单元部分。Sysmac Studio 不要从不明来源随意下载安装包最好通过欧姆龙官网、授权代理或经销商获取。安装过程中还需要处理许可激活盗版或绿色版软件很容易在后续在线通信、固件升级时出现莫名其妙的错误。2.2 通信单元与端口规划如果你使用的 CPU 机架原本没有串口常用的做法是选择 CJ 系列串行通信单元。它有单串口和多串口型号例如带两个串口的单元可以分别接扫码枪和触摸屏或者一个口接 RS232 设备、另一个口接 RS485 总线设备。在 Sysmac Studio 中每个串行通信单元都有单元号每个串口有端口号。程序里执行通信指令时需要同时指定“访问哪个单元”和“访问哪个端口”。如果现场有多台串口设备建议先做一张端口分配表设备单元号端口号通信接口用途扫码枪01RS232读取条码电子秤02RS422/485读取重量上位机11RS232调试监视这样做的好处是写程序的时候不会把设备的“物理接线”和“逻辑编号”搞混。特别是在设备维护阶段换一个人接手项目时只要看到表格就能快速定位问题。2.3 RS232 接线注意事项RS232 属于最常用的串口形式接线上最容易犯的错误是交叉关系搞反。标准的 DB9 公头/母头中2 脚是 RXD3 脚是 TXD5 脚是 GND。PLC 串口和设备串口连接时通常是“你发我收”的交叉接法也就是 PLC 的 TXD 接设备的 RXDPLC 的 RXD 接设备的 TXDGND 互连。别把两根发送线直接接在一起否则无论如何都收不到数据。接线之前先看设备说明书上的引脚定义不能只依赖“默认 DB9 定义”。有些设备厂商把引脚重新定义了或者使用了 RJ45 形式的串口接口。错误接线最容易导致的故障现象是程序配置看起来都对但就是收不到任何数据。如果使用的是 RS422/RS485还需要注意 A/B 或 /− 极性不能接反。通信距离较长时屏蔽层要单端接地避免形成地环路。3. Sysmac Studio 中配置无协议串口通信3.1 新建工程并识别硬件打开 Sysmac Studio点击新建工程选择对应的 NJ501 CPU 型号。如果电脑已经和 PLC 用网线连好可以在线的状态下选择“从设备读取”让软件自动识别当前的硬件配置如果暂时没有连接也可以手动添加 CPU 和串行通信单元。手动添加时要注意单元安装的槽位。CJ 系列通信单元在 CPU 机架上会占用槽位槽位号必须和实际一致否则程序下载后通信单元可能无法访问。正确做法是先在软件里组态完成后再对照实物检查一遍单元号设定。在 Sysmac Studio 左侧的“配置和设置”中双击“I/O 配置”找到串行通信单元打开它的“单元设置”画面。这里通常可以设置串口 1 和串口 2 的工作模式波特率、数据位、停止位、校验位发送/接收缓冲区大小接收完成判定条件3.2 串口模式与通信参数串口模式的选择是整个配置的核心。在单元的串口设置中会有类似下面的选项HostLink Modbus-RTU Slave Modbus-RTU Master 无协议No-protocol要实现“欧姆龙NJ501无协议串口通信接收”就要把对应端口设置为“无协议模式”。接着设置通信参数常见格式如下参数示例值说明波特率9600 或 115200必须和设备端一致数据位8一般 ASCII 数据都是 8 位停止位1常见设置校验位None / Even / Odd第三方设备可能要求偶校验流控None / RTS/CTS大多数设备用 None这里容易犯的错误是只修改了 PLC 端的波特率没有检查设备端的实际参数。很多扫码枪出厂默认是 9600而仪表可能是 19200参数不一致时最常见的现象就是收到乱码或者完全没反应。建议在写程序之前先用电脑的串口助手连接设备把设备主动上报的数据帧格式抓下来。这样能确认波特率、帧头帧尾、结束符后面写解析程序时才有依据。3.3 接收完成条件的理解无协议通信接收最关键的设置是“什么时候认为一帧结束了”。不同通信单元或固件版本的设置项不同但思想基本有两种第一种是固定长度接收。设备每帧数据长度固定例如每次发 20 个字节PLC 收到 20 个字节后就认为本帧接收完成。这种方式简单但设备如果发送中途断线PLC 会一直等待直到超时。第二种是结束码接收。给串口设置一个结束字节比如常见的回车0x0D、换行0x0A、或者自定义帧尾0x03PLC 收到这个字节后立即判断一帧接收完成。这种方式更适合变长数据帧。第三种是超时接收。设置一个空闲时间串口收到数据后如果超过一定时间没有后续字节就认为本帧结束。超时接收适合设备发送间隔不规则的应用。实战中扫码枪最常见的格式是以回车或回车换行结尾所以可以把接收条件设置为“检测到结束码 0D 0A 则认为接收完成”。如果结束码只设置一个 0D要注意设备是不是发了 0D 0A 两个字节设置不当会把换行符留到下一帧开头。4. 无协议通信接收的软件设计思路4.1 定义接收变量与缓冲区在 NJ 的变量化编程中串口接收的数据建议用数组变量存放。全局变量表里可以建立类似下面的定义// 全局变量建议定义 gbReaderPort : WORD : 1; // 串口端口号根据实际单元调整 gbRecvBuffer : ARRAY[0..255] OF BYTE; // 接收缓冲区256字节 gbRecvCount : WORD; // 本次接收到的字节数 gbRecvDone : BOOL; // 接收完成标志 gbRecvEnable : BOOL; // 接收使能 gbFrameStart : WORD; // 解析用的帧起始位置 gbFrameLen : WORD; // 解析出的有效数据长度为什么要设置gbRecvEnable因为无协议接收如果一直处于允许状态缓冲区里的数据可能在业务逻辑还没处理时就被下一帧覆盖。通常做法是设备上电或系统初始化时打开接收使能。接收完成标志置位后先关闭接收使能。业务逻辑拷贝走缓冲区数据。处理完成后重新打开接收使能。这样可以最大程度避免数据被覆盖。4.2 指令触发方式与执行逻辑Sysmac Studio 中无协议串口通信会使用专门的通信指令。指令的准确名称和参数取决于你使用的串行通信单元型号。编写程序前先按键盘上的“帮助”在指令帮助中搜索“串行通信”或“RXDU”查看当前软件版本下的指令原型。指令在程序中通常不会每周期无条件执行而是用“接收请求”或“扫描周期启动”去触发。可以参考下面的伪代码逻辑// 伪代码示意接收使能与指令触发思路 // 具体指令名称以Sysmac Studio指令帮助为准 IF bPowerOn THEN bRecvEnable : TRUE; END_IF; IF bRecvEnable THEN // 调用无协议接收指令将数据接收到 gbRecvBuffer // 当接收完成标志置位后将 bRecvDone 置位 END_IF; IF bRecvDone THEN bRecvEnable : FALSE; // 进入数据处理段解析条码、更新画面、触发下一步动作 END_IF;这里特别强调“触发方式要使用边沿或完成标志”。如果接收使能信号一直为 TRUE某些指令在每次扫描周期都会重新发起接收请求导致缓冲区不断被刷新。最典型的现象是明明数据已经进来了但你的解析程序总是拿到一半的数据。当遇到这种情况不要急着改解析程序先在在线监视中观察接收缓冲区变量看看数据是什么时候写入的、写入了多少字节往往能很快定位。4.3 接收数据的基本解析思路接收缓冲区拿到的是字节数组但实际项目里我们更关心业务数据。假设扫码枪发送的帧格式是STX 条码内容 ETX 对应的十六进制是02 ASCII码 03那么程序要做的事情就是在接收缓冲区中找到 0x02 作为帧头再找到 0x03 作为帧尾把中间的内容拷贝出来。下面用 ST 语言写一个简单的帧提取思路方便理解// 功能从接收缓冲区中提取 STX(02) 到 ETX(03) 之间的内容 // 注意这是一个算法示例变量类型和边界需要按实际工程调整 bFindStart : FALSE; bFindEnd : FALSE; nStart : 0; nEnd : 0; FOR i : 0 TO (gbRecvCount - 1) BY 1 DO // 找帧头 0x02 IF (NOT bFindStart) AND (gbRecvBuffer[i] 16#02) THEN nStart : i; bFindStart : TRUE; END_IF; // 找到帧头后再找帧尾 0x03 IF bFindStart AND (NOT bFindEnd) AND (gbRecvBuffer[i] 16#03) THEN nEnd : i; bFindEnd : TRUE; END_IF; END_FOR; // 如果帧头帧尾都找到且中间有内容则拷贝有效数据 IF bFindStart AND bFindEnd AND (nEnd nStart 1) THEN nDataLen : nEnd - nStart - 1; FOR j : 0 TO (nDataLen - 1) BY 1 DO gbFrameData[j] : gbRecvBuffer[nStart 1 j]; END_FOR; bFrameValid : TRUE; END_IF;这段代码的价值在于把“接收”和“解析”分开了。接收只是把原始字节搬进缓冲区解析只负责按协议取出有效内容。如果以后设备协议变了只需要修改解析段的帧头帧尾判断而不用动通信设置。5. 校验算法与数据安全处理5.1 为什么需要校验很多自制的第三方设备或老式仪表串口通信时数据可能受到干扰偶尔会出现丢字节、错字节的情况。如果协议里没有校验PLC 可能把错误数据当成真实数据轻则显示错误重则触发错误动作。常见校验方式有累加和校验异或校验CRC16 校验LRC 校验如果设备的通信协议本身包含校验位PLC 接收完成后必须校验如果协议没有校验建议在 PLC 端至少增加超时判断避免用到不完整数据。5.2 异或校验代码示例很多扫码枪或传感器会采用一字节异或校验。下面是一段 ST 计算异或校验值的参考实现// 功能计算一帧数据的异或校验值 // 输入DataArray 数据数组DataLen 参与校验的长度 // 输出XorValue 校验值 XorValue : 0; FOR i : 0 TO (DataLen - 1) BY 1 DO XorValue : XorValue XOR DataArray[i]; END_FOR;把参与校验的字节全部异或后与设备发过来的校验字节比较如果相同则数据有效否则丢弃本帧数据。这种方式非常适合高速、短帧的串口场景。实现校验时要注意参与校验的范围。有的设备从帧头开始算有的从帧头后一个字节开始算有的只算数据区。范围搞错的话即使算法一样也永远校验不过。5.3 将接收到的原始帧用于调试在项目调试阶段强烈建议把“接收到的原始帧”实时监控下来。可以把接收缓冲区变量加入 Sysmac Studio 的数据跟踪或通过触摸屏/上位机显示原始十六进制数据。这样做的目的很直接如果解析结果不对先看原始报文对不对。原始报文正确而解析出错问题在 PLC 程序原始报文本身就乱问题大概率在通信参数或线缆。曾经遇到过一个案例程序解析总是不稳定最后用串口抓包发现设备每帧之间收到一个额外的 0x00 字节。原因是设备串口初始化时发送缓冲区没有清空多了一个空字节。这种问题不看原始报文很难定位。6. 联机调试与结果验证6.1 用 Python 模拟串口设备发送数据在没有实物扫码枪的情况下可以用电脑的串口助手或 Python 脚本模拟设备主动向 PLC 发送数据。这样做的好处是可以在受控环境下测试接收逻辑。安装 pyserial 后用一段简单脚本发送测试帧import serial import time ser serial.Serial( portCOM5, # 根据实际串口号修改 baudrate9600, # 必须和PLC端一致 bytesize8, parityN, # N: None, E: Even, O: Odd stopbits1, timeout1 ) frame b\x02ABC123456\x03 # STX 内容 ETX ser.write(frame) print(send:, frame) time.sleep(0.1) ser.close()运行前要确认电脑的 USB 转 RS232 线已经正确连接 PLC 的串口且串口号没有占冲突。然后回到 Sysmac Studio 在线监视观察gbRecvBuffer和gbRecvCount变量是否变化。如果两者都有值说明无协议通信接收已经打通。6.2 在 Sysmac Studio 中在线监视变量把工程下载到 PLC 后点击“在线”按钮然后打开全局变量表右键选择“监视”。Sysmac Studio 可以实时看到变量的当前值。监视接收缓冲区数组时可以把显示格式切换为十六进制。这样做方便直接对照设备发来的原始报文。一个重要的点是修改全局变量或程序后Sysmac Studio 有时会提示“需要传输到控制器”。如果没有把最新工程下载到 PLC程序运行的可能还是旧版本容易造成“我明明改了程序为什么没生效”的错觉。建议每次修改程序后都执行一次“传输到控制器”下载完成后检查一下 PLC 是否进入运行状态。若 PLC 处于编程模式串口通信程序不会执行。6.3 实际设备联调时的检查顺序接到真实设备后调试顺序建议是确认设备能独立工作例如扫码枪在串口助手下能正常输出数据。检查 PLC 与设备的通信参数完全一致。用 Sysmac Studio 监视接收缓冲区确认 PLC 能收到原始数据。再观察接收完成标志是否正常置位。最后启用自己的解析程序。如果第二步通过网络搜索或咨询设备厂商后仍不确定就先用串口助手抓包记录。先确认设备确实在发数据再怀疑 PLC 配置不要一开始就反复修改 PLC 参数。很多时候问题根源并不在 PLC而在设备端根本没有发送数据。比如某些扫码枪需要外部触发信号才会开始扫码未接触发线时它始终处于休眠状态自然收不到任何数据。7. 常见问题与排查思路下面这张表汇总了欧姆龙NJ501无协议串口通信接收中最高频的问题。问题现象常见原因解决思路串口设置下载后不生效通信单元没有重新上电对 PLC 或通信单元执行断电重启完全收不到数据串口模式没有改成“无协议”检查单元设置并重新下载程序完全收不到数据TX/RX 线接反、GND 未接用串口助手验证设备发送端检查接线完全收不到数据程序和设备不是同一个串口核对单元号、端口号确认实际接线位置接收乱码波特率、数据位、停止位、校验不一致用抓包数据确认设备真实参数一帧被拆成多次接收结束码设置错误或设备发送间隔太长确认设备帧尾必要时改“超时接收”两帧数据合在一起接收完成条件太长设备连续发数据把结束码设置为帧尾字节或减小固定长度接收缓冲区始终被覆盖数据拷贝不及时业务逻辑处理慢接收完成后先暂停接收处理完再使能指令重复触发使用电平时序而不是边沿触发用上升沿或接收完成标志控制在线修改程序后通信异常下载过程导致单元重新初始化尽量在停机状态下载并观察单元状态灯单独说一下“重启”这个动作。修改串行通信单元的无协议模式、结束码、缓冲区大小等参数后有些型号必须断电重新上电才能生效。很多工程师只下载程序不复位结果在线监视怎么调都不对。另外如果现场同时接了两台串口设备要特别小心单元号和端口号是否配置错了。程序里写的端口 1 可能实际接的是端口 2 的设备这种错误从程序层面完全看不出来只能回到图纸和接线表去核对。8. 工程最佳实践与建议8.1 先定协议再做程序无论设备是扫码枪还是仪表都要先确认通信协议。建议维护一份简单的串口协议文档至少包含波特率、数据位、停止位、校验方式数据帧长度还是结束码帧头、帧尾、长度字段数据字段含义校验方式设备主动上报还是 PLC 轮询没有这份文档今天调通了过两个月再维护时又会一头雾水。写进项目交接文档比只写在程序注释里靠谱得多。8.2 使用边沿触发和完成标志控制流程NJ 的通信指令即使不带强制边沿参数也应该在程序逻辑上用边沿或完成标志控制避免每个扫描周期重复发起通信请求。典型的错误写法是把“接收使能”直接接到常开触点指令每个周期都执行结果后续数据处理永远跟不上。更稳妥的做法是建立一个“接收状态机”空闲 - 等待接收 - 接收完成 - 数据处理 - 空闲这样程序结构清晰也能避免缓冲区覆盖。8.3 接收缓冲区要足够大很多工程师习惯把缓冲区设置得刚好等于一帧长度但实际使用中如果设备发送了异常帧缓冲区可能溢出。建议缓冲区至少留出 1.5 到 2 倍的空间并充分考虑最坏情况。另外要注意设备发来的可能是 ASCII 字符也可能是十六进制字节。同一个字符“A”在串口助手上显示为 A在 PLC 接收缓冲区里可能是 0x41。如果你按 ASCII 直接比较会出现数据对不上的问题。建议在程序里统一使用字节或十六进制进行判定。8.4 通信参数的修改要提前评估影响修改串口通信参数时应评估是否会对整个系统造成影响。例如 PLC 正在执行运动控制如果你此时下载程序导致通信单元重置运动轴可能会报错或暂停。安全做法是在设备停机、伺服未使能的状态下进行参数修改和下载。如果无法停机至少要提前备份原工程并确保能快速回滚配置。工程文件建议用项目名称加日期命名例如NJ501_Reader_20250325_v1.0.smc2这样即使配置改乱也能快速恢复到上一个可用版本。8.5 多设备接入时尽量采用总线方式如果现场串口设备很多多个独立串口单元会占用大量机架空间和成本。这种情况下可以评估 RS485 总线方式让多台设备挂在同一条 RS485 总线上PLC 通过站号区分设备。不过这种方式会增加协议复杂度适用于设备本身支持总线通信的场景。对于简单的单台扫码枪或仪表直接用 RS232 无协议通信接收是成本最低、最容易维护的方案。9. 总结理顺 NJ501 串口接收的完整链路欧姆龙NJ501无协议串口通信接收本质上是一条由硬件连接、通信参数、接收指令、数据解析组成的链路。任何一个环节不对最终都会表现为“收不到数据”或“数据不对”。建议你先从最小验证开始用串口助手手动发送一帧固定数据让 PLC 接收并在线监视缓冲区。这一步打通后再接入真实设备逐步完善数据解析和业务逻辑。不要一开始就写很复杂的完整程序否则问题会被淹没在一堆业务代码里。下一步可以继续学习 Sysmac Studio 中的数据跟踪功能、欧姆龙 NJ/NX 的 EtherNet/IP 通信以及如何把串口接收到的数据通过 OPC UA 或套接字发送给上位机。掌握 NJ501 的串口接收后你会发现其他品牌 PLC 的无协议通信也大多是类似思路区别只在指令名和配置界面不同。