简介这份文档聚焦三菱Q系列PLC串行通讯模块QJ71C24N与QJ71C24N-R2的RS232通讯方法面向工业自动化现场调试人员、PLC编程初学者及需要完成设备间数据交换的工程师重点解决两类模块在无顺序协议下的参数配置与收发程序设计问题。压缩包内仅1个docx文件约197KB以图文结合方式呈现模块通道差异、通讯线缆示意、Works2开关设置界面以及发送与接收程序示例便于对照实际工程查阅。该文档已有3907人学习在三菱串行通讯调试场景中具备较高参考价值。读者可了解QJ71C24N双通道RS-232与RS-422/485与QJ71C24N-R2双RS-232通道的选型差异掌握波特率、校验方式、数据位、停止位等参数的一致性原则并从接收缓冲区定义、发送帧打包、CRC校验、超时处理等环节获得可复用的编程与排错思路。1. 产线上两块串行通讯模块接错一个口就要查半天上个月帮人看一条包装线主控柜里 Q系列PLC 机架上插着两块串行通讯模块一块 QJ71C24N、一块 QJ71C24N-R2对面挂着三台只有 9 针口的称重仪和一把老条码枪。现场的人说“通讯时好时坏”我到现场先做的事不是看程序而是核对这两个模块的通道到底接到了哪里——QJ71C24N 的两个通道里只有 CH1 是 RS-232CH2 是 RS-422/485而 QJ71C24N-R2 是两个通道全 RS-232。型号差一个后缀可用的口就少一个程序里写的通道号也跟着全错。这套东西干的事其实很朴素让 Q 系列 PLC 用串口跟第三方设备换数据走无顺序协议时基本就是“我发一串字节、你回一串字节”没有主站从站那一套握手。适合谁做产线改造、设备联网、老设备数据采集的电气和自动化开发尤其是手上已经有 Q 系列机架、又不想为了几个串口再塞一块通讯网关的人。2. 硬件与协议选型通道拓扑、9 针线序和三种协议的分界动手写程序之前选型和接线必须先落定这两件事一旦定错后面在软件里怎么调都是白费功夫。这一章把模块能力、物理链路、协议三件事按现场顺序捋一遍都是能直接照抄进图纸和配置表的内容。2.1 通道拓扑QJ71C24N 与 QJ71C24N-R2 的差别落在哪两个模块外观几乎一样都占用一个智能功能模块槽位都能开两个通道但通道的电气规格不同。QJ71C24N 是“一混一单”CH1 走 RS-232CH2 走 RS-422/485QJ71C24N-R2 是“双 232”CH1、CH2 都是 RS-232。这个差别决定了两件事。第一件是接什么设备。RS-232 是点对点、距离短几米到十几米适合一台仪表、一台扫码器、一台工控机这种一对一场景。RS-422/485 是差分能拉几百米、能挂多台从站适合一条线串好几台设备。所以如果现场是“三台仪表分别接三个串口”选 R2 最省事两个通道各自独立组帧、独立收发如果是“一台设备近距离对接 一条 485 总线挂若干从站”那就是 QJ71C24N 的活。第二件是程序里的通道号。无顺序协议下每个通道有自己独立的开关设置、独立的缓冲区、独立的发送请求和接收完成信号。CH1 配好了不代表 CH2 能用两个通道的开关设置必须分别进界面设一遍。我见过最典型的翻车是现场把线接在 QJ71C24N 的 CH2 上程序里通篇按 CH1 的缓冲区地址收发模块本身没有任何报错就是收不到数。一个务实的习惯是先在图纸上给每个物理口编号写成“模块位号-通道号-对接设备-协议”四列程序里的变量命名直接沿用这个编号。后面调试时不用回翻图纸看变量名就知道在说哪个口。2.2 交叉线缆与信号地9 针接头最容易忽略的两根线QJ71C24N 系列用的都是模块自带的 9 针 D-sub 母座RS-232 三线制TXD、RXD、GND就能通。要点只有一个交叉。PLC 侧的发TXD要接到对方侧的收RXDPLC 侧的收RXD接对方侧的发TXDGND 对 GND。现场遇到最多的是两种线一种是设备手册写“直连线”其实对方已经内部交叉过了你再交叉一次就变成收发对接另一种是只接了两根信号线、GND 没接短距离、同电源时勉强能通一旦两台设备取自不同配电回路共模电压差就会让通讯随机丢字节表现为“白天正常、晚上电机一启动就乱码”。这种问题换程序、调波特率都没用。我的做法是所有 RS-232 线一律三线接全屏蔽层在 PLC 侧单端接地线长超过 10 米就改 485。另外 9 针口上的 RTS/CTS 在无顺序协议的三线模式下不参与流控不要为了让“看起来更完整”把它们短接成自环某些设备会把 RTS 当成硬件流控使能反而卡住发送。提示线做好之后先在断电状态下用万用表量通断别指望上电后用程序去验证线序那会把“线接错”和“参数设错”两个故障混在一起。2.3 三种协议怎么选MC、无顺序、双向协议的分界这三块串行通讯模块支持的协议里MC 协议是给自家生态用的PLC 当从站上位机按固定报文格式读写软元件报文结构由协议规范定死你不需要自己拼帧但也意味着对方必须说这套“方言”。双向协议更轻模块把收到的字符直接映射到软元件区发也是从软元件区直接往外吐中间不做帧解析适合对方设备报文格式已经固定死、你只想搬字节的场景。无顺序协议是这三者里最通用的你自己决定发什么字节、什么时候发、收到多少字节算一帧模块只负责按开关设置里的帧格式是否加 STX/ETX、是否加和校验码、结束符用 CR 还是 CRLF帮你拼装和拆解。跟第三方仪表、扫码枪、称重设备打交道绝大多数时候走这条。选型上的判断顺序我一般是这样对方设备手册里明确写“支持 MC 协议”或者对方是自家触摸屏/上位机组态优先 MC对方报文格式固定、只需要单向搬运用双向协议最省代码对方要求“发一条查询指令、回一条应答”那必然是无顺序协议因为你必须控制发送时机和判帧逻辑。无顺序协议里还有个容易被忽略的点它是“无顺序”的意思是协议本身不保证多帧之间的先后和完整性模块不会帮你做序列号排序也不会自动重发。可靠性得靠应用层自己补——加和校验、加结束符、加超时重发这三样在后面的程序章节里会具体落。3. 参数配置落地Works2 里从添加模块到通道 1 的每一格配置这一章按实际操作顺序写先把模块加进工程再把型号对准最后逐项设开关。三菱体系的智能功能模块配置有个特点——所有参数都存在工程里下载时必须连模块参数一起下载只下程序不下参数模块仍然按出厂默认跑这是新手最容易卡住的地方。3.1 添加模块型号选错后面全白搭在 Works2 里对着机架上的智能功能模块位置右键选“添加新模块”模块类型挑“串行通信”型号从列表里选实际插的那一块。这里必须和物理模块严格一致插的是 QJ71C24N-R2就不能选 QJ71C24N。原因很实际——两种模块的通道能力不同选错之后打开开关设置界面你会发现通道 2 那一页的选项跟物理模块对不上或者在 R2 上按 485 的参数去配最后跑起来通道 2 完全没反应。添加时还要填起始 I/O 号。这个号不是随便填的它由模块插在机架第几槽决定前面每占一个槽含 CPU、电源占用的逻辑位就往后推。填错的表现很有迷惑性程序能下载、模块 READY 灯也亮但所有U0\G缓冲区读写全部打到别的模块或者空地址上读回来的永远是 0。添加完成后在工程树的智能功能模块下面会多出这个模块的节点展开后能看到“开关设置”“中断设置”等项。通道是分开的两页CH1 一页、CH2 一页两边都要设。工程树结构添加完成后 PLC 参数 机架/模块配置 智能功能模块 QJ71C24N - 位号 0起始 I/O 按实际槽位 - 开关设置 - CH1 / CH2 分开两页 - 中断设置 QJ71C24N-R2 - 位号 1 - 开关设置参数说明上起始 I/O 号决定程序里U0\Gxxx前面的那个U0位号只影响工程里的显示顺序不影响寻址。所以核对时看的是 I/O 号不是位号。3.2 开关设置逐项速率、数据位、校验、停止位打开通道 1 的开关设置是一张逐项下拉的表。这些参数必须和对方设备完全一致——不是“兼容就行”波特率差一档、校验方式差一位收到的就是成片乱码或者干脆一个字节都没有。设置项示例值说明通信速率19200 bps与对方设备一致长线或多设备总线建议降到 9600数据位8 位传 ASCII 指令用 8 位对方只支持 7 位时校验位会占一位奇偶校验偶校验无校验、奇校验、偶校验三选一必须和对方一致停止位1 位少数老仪表固定 2 位通信方式全双工RS-232 点对点用全双工485 半双工时选半双工和校验码有决定模块是否自动计算并附加/校验累加和帧格式格式 1决定 STX/ETX、结束符的组合方式配的时候有个隐性约束数据位和校验位是捆在一起的。对方写“7 位数据、偶校验”你就不能设 8 位数据加偶校验因为 7E1 和 8E1 在一帧里的位数不同接收端会持续判帧错误。同理停止位 1 和 2 也是逐位对齐的差一位就整帧错位。速率不是越高越好。现场 19200 足够跑几十毫秒一条的查询应答如果线缆质量一般或者跟变频器同槽走线38400 以上丢字节的概率明显上升。我的默认值是 9600 起步跑通之后再往上加加到出现偶发校验错就退回上一档——这比一开始就设很高、然后花两天怀疑程序要省事得多。3.3 无顺序协议的专属设置帧格式、结束符与缓冲区分配无顺序协议下还有几项专门服务于“自定义报文”的设置它们决定模块帮你做多少事。帧格式决定模块收发时是否自动加 STX帧头、ETX帧尾、是否附加和校验码。如果对方设备的协议是“STX 数据 ETX 校验”那就可以让模块自动组帧程序里只写数据段如果对方协议是“STX 命令字 数据 和校验 CR”模块的自动格式包不住就得选不自动附加全部在 PLC 里用指令拼好再写进发送缓冲区。接收结束条件有两种常见做法按字节数判收到固定长度就算一帧和按结束符判收到 CR/LF 就算一帧。变长报文必须用结束符方式否则你永远不知道一帧什么时候结束定长报文用字节数方式更稳因为对方如果漏发结束符按结束符判会一直等下去。缓冲区是这一节最需要记住的东西。无顺序协议下收发数据不是走指令参数而是走模块内部的缓冲区用U0\G直接读写。常见分配是以模块手册的缓冲区分配表为准这里的地址按首槽、CH1 起始给出地址内容U0\G256CH1 发送数据字节数注意是字节不是字数U0\G257~U0\G511CH1 发送数据区U0\G512CH1 接收数据字节数U0\G513~U0\G767CH1 接收数据区U0\G768/U0\G769~CH2 发送字节数 / 发送数据区U0\G1024/U0\G1025~CH2 接收字节数 / 接收数据区最后一个动作是把参数和程序一起下载。Works2 里“下载”对话框要勾上模块参数只勾程序的话模块跑的还是出厂默认值表现就是“程序没错、参数看着也对、就是通讯不上”。这一条我在现场至少遇到过三次。4. 收发程序拆解发送帧拼装、接收缓冲轮询与判帧程序部分按“发送侧在 QJ71C24N、接收侧在 QJ71C24N-R2”这个方向写这是原项目里给的组合实际项目里反过来也一样因为两侧用的都是同一套缓冲区机制。核心思路就三句话发送方把字节数写进去、把数据搬进去、置发送请求接收方盯着接收字节数、有数就搬走、搬完复位。4.1 发送侧把 ASCII 指令打包成字节写进缓冲区假设对方设备要求发一条 8 字节的查询指令比如STX 命令 参数 ETX CR其中 STX、ETX、CR 由程序拼好模块不开自动帧格式那发送逻辑就是先组帧再搬运。(* QJ71C24N CH1 无顺序协议发送D200 起存放已拼好的 8 字节 ASCII 帧 *) (* ① 写发送字节数单位是字节不是字 *) MOV K8 U0\G256; (* ② 8 字节 4 个字按字块搬进发送缓冲区 *) BMOV D200 U0\G257 K4; (* ③ 置通道 1 发送请求模块按开关设置把缓冲区内容打到串口上 *) SET Y1;逐段说明。第一行写的是字节数这是最常见的错有人按字数写8 字节的帧写成 4模块就只发前 4 个字节对方永远判不出完整帧回的报文自然也不对。第二行用BMOV按字搬一个字两个字节所以搬 4 个字如果用MOV一条条搬注意高低字节顺序Q 系列是低字节在前MOV H4241发出的顺序是41 42即AB拼 ASCII 帧时按这个顺序排。第三行置位发送请求Y1的具体点数由模块在机架上的起始 I/O 决定示例按首槽给出实际项目里以模块的 I/O 信号表为准。发送完成之后要复位发送请求否则下一次发送不会触发。稳妥的写法是等“发送完成”输入信号再RST Y1同时把发送成功计数加一。如果对方设备处理慢两次发送之间要留间隔——模块发完最后一个字节到对方开始回包之间通常有几十毫秒的空档连续快速重发会把对方的接收缓冲冲掉。(* 发送完成回执清请求、计数、置下一次可发标志 *) LD X1 (* 通道 1 发送完成点数按起始 I/O 核对 *) RST Y1; INC D500; (* 发送成功计数便于和接收计数对比查丢包 *) SET M10; (* 允许进入下一次查询 *)这里有个小细节值得说D500这个发送计数后面会派上大用场。接收侧也有一个接收计数两个数一对立刻就能判断是“发不出去”还是“发出去但没回来”比盯着串口灯猜要快得多。4.2 接收侧轮询接收字节数、搬数、复位接收侧不做中断用轮询最省心每个扫描周期看一眼接收字节数寄存器非零就说明模块收到东西了。(* QJ71C24N-R2 CH1 无顺序协议接收轮询接收字节数 *) LD SM400; CMP U0\G512 K0 M100; (* M1001 表示接收区有数据 *) LD M100; MOV U0\G512 D300; (* D300 本次收到的字节数 *) BMOV U0\G513 D301 K10; (* 最多取 20 字节 10 个字按实际帧长调整 *) (* 取完之后必须告知模块可以收下一帧否则接收区不再更新 *) MOV K0 U0\G512;这段的关键在于两个“单位”和两个“复位”。U0\G512里是字节数D300存下来之后做长度判断比如对方协议固定 12 字节那就先比D30012不等就丢掉。BMOV的 K10 是字数要按最大帧长往上取整宁可多搬几个字也别少搬——少搬的后果是判帧时拿到截断的报文校验必然不过。最后一行MOV K0 U0\G512是很多人漏掉的模块的接收区在数据被取走之后不会自己清零字节数不清零下一帧的到达判断就永远成立程序会把同一帧反复处理几百遍表现是“数据刷屏、全是重复”。更规范的做法是用模块的“接收数据读出请求”信号配合清零逻辑等价。4.3 判帧与超时把“能通”变成“可靠”收发都通了只算及格。产线上的通讯要的是“错了能发现、卡了能恢复”这两件事得在应用层补。判帧放在取数之后先看长度对不对再看帧头帧尾对不对最后算和校验。和校验如果让模块自动加了开关设置里“和校验码有”那就直接比对模块给的校验字节如果模块不开自动校验就在 PLC 里自己累加。三段判断任何一段不过直接丢弃这一帧并计数不去解析数据避免把乱码当有效值写进控制逻辑。(* 简易判帧长度 帧头帧尾 累加和 *) LD SM400; AND D300 K12; (* 长度必须是 12 字节 *) AND D301 H0230; (* 首字低字节 30H 0即 STX 之后的起始字符 *) AND D306 H0D0A; (* 末尾 CR/LF *) OUT M20; (* M20 帧结构合法 *) LD M20; MOV D302 D400; (* 只把合法帧的数据段搬进工艺变量区 *) INC D501; (* 接收有效帧计数 *)超时是另一半。发送之后启动一个定时器比如 500 ms等接收计数变化超时就重发连续三次超时就置通讯故障位、报警、把相关工艺变量标成“无效”不要让上层逻辑拿着上一次的旧值继续算。这条在配方、称重这类场景里特别重要一个陈旧的重量值可能导致整批料废掉。(* 发送后 500ms 无回应则重发三次判故障 *) LD M10; OUT T10 K500; LD T10; AND D501 D501_OLD; (* 接收计数没变化 没收到新帧 *) INC D510; (* 超时次数 *) LD D510 K3; SET M30; (* 通讯故障位上位机报警用 *) RST M10;参数说明T10的 500 是 100 ms 基准下的值也就是 50 s不对——Q 系列默认定时器是 100 ms 基准K500就是 50 秒这里要写K50.5 秒或者把基准改成 10 ms。这类基础参数的坑我吃过不止一次调试时盯着“怎么五秒还不重发”结果是自己把基准搞混了。保险做法是在程序注释里把基准写清楚。5. 避坑排查通讯不上和数据错乱各查一半串口调试最耗时间的不是写代码是分不清故障出在哪一层。我的排查原则是先把“物理层和参数层”和“程序层”切开前者表现为一个字节都收不到、或者整片乱码后者表现为能收到但内容不对、帧错位、重复处理。下面五条都是现场反复出现的。5.1 链路层收不到、乱码、时通时断现象一模块 READY 灯亮程序照跑接收字节数永远是 0。原因通常是参数没随程序一起下载模块还在跑出厂默认默认速率和校验跟对方对不上或者起始 I/O 号填错U0\G512读的根本不是这块模块。解决重新下载时勾上模块参数用 Works2 的模块监视确认起始 I/O再读一次U0\G512如果读出来是随机值说明地址错了。现象二收到的全是乱码但长度对得上。基本是速率或校验、数据位不一致。解决把两侧参数列成表逐项比重点看“7 位数据 偶校验”有没有被写成“8 位数据 偶校验”、停止位是 1 还是 2。改完记得重新下载参数改完不下载等于没改。现象三白天正常晚上或电机启动就断。共模干扰。RS-232 只接了 TXD/RXDGND 没接或者屏蔽层两端都接了地形成地环路。解决补上 GND屏蔽层 PLC 侧单端接地信号线远离动力线槽距离超过 10 米直接换 485。5.2 应用层半包、重复、帧错位现象四同一帧数据被反复处理几百遍上位机曲线出现平台。接收字节数没复位。模块收到一帧后U0\G512保持非零轮询逻辑每个扫描周期都认为“有新数据”。解决取完数据立刻把字节数寄存器清零或者用“接收数据读出请求”信号做边沿触发。这条我建议写进模板里别靠每个项目现场记得。现象五偶发校验失败重发一次就好。多半是帧边界没判干净。上一帧的尾巴残留在接收区或者对方一次发了两帧、你按一帧的长度取走剩下半帧留在缓冲区里下一轮被当成新帧的开头。解决接收区按最大帧长一次性清干净再取判帧时严格校验帧头帧头不对就整段丢弃并重新同步不要“凑合着从中间解析”。另外提三个容易忽略的配置项中断设置里如果开了接收中断轮询逻辑会和中断抢同一块缓冲区数据会出现“一半在中断里处理、一半在轮询里处理”的怪象非必要不开通道 2 在 QJ71C24N 上是 485半双工时收发切换需要时间程序里发完要留至少几个字符时间的间隔还有模块的看门狗和 CPU 的扫描周期如果扫描周期被别的逻辑拖到几百毫秒轮询接收就会漏帧这种情况要么缩短扫描、要么改成中断接收。6. 二次开发把这条链路做成可复用的通讯模板真正让这套东西变得好用的不是把某一次通讯调通而是把它封成模板。我的做法是抽三个功能块FB_SerialSend、FB_SerialRecv、FB_SerialLink。前两个只管单通道的收发和缓冲区地址后一个管状态机——空闲、发送中、等待应答、超时重发、故障锁定。FB_SerialSend的输入只留四个通道号决定用U0\G256还是U0\G768、数据区首地址、字节数、触发位输出是完成位和错误码。通道号到缓冲区地址的映射用一个常量数组做CH1映射到 256/257CH2映射到 768/769换模块型号时只改这张表不动逻辑。这一步做完“接错通道”这类问题在编译期就能暴露一半。FB_SerialRecv里把“取数—复位—判帧”三步焊死在一个循环里不再给调用者“忘记复位”的机会。判帧规则做成参数最小长度、最大长度、帧头字节、是否校验和。现场遇到新设备只改参数不改代码。复用点做法收益通道映射常量数组 通道号入参换型号只改表程序不动缓冲区复位封在接收块内部杜绝重复处理判帧规则长度/帧头/校验参数化新设备只改参数超时重发状态机统一处理各设备行为一致诊断计数发送数、接收数、校验错数现场十分钟定位验证方法上我习惯在模板里留一组诊断寄存器把发送计数、接收计数、校验错计数、超时计数都放进去映射到触摸屏的一页。现场一出问题看这四个数的关系就能定性发送在涨、接收不涨查线和对端接收在涨、校验错也在涨查参数和干扰两边都在涨但工艺值不动查判帧和数据搬移的地址。这比拿笔记本连 PLC 在线监视快得多。还可以再加一层“回路自测”把模块的一个通道设成自发自收外部把 TXD 和 RXD 短接程序定时发一条固定帧看能不能原样收回来。这段代码在出厂前跑一遍能把参数配置、缓冲区地址、复位逻辑全部验证掉剩下的问题就只可能出在对端设备上。后来我把这套模板固化成了一个检查清单上电先跑自测回路再核对接线表和通道映射表最后才打开对端设备。从那以后我每次上新项目都强制走一遍这个顺序再没出现过“调了两天发现是参数没下载”这种事。希望帮到你。本文还有配套的精品资源点击获取