做设备调试这几年,我经常碰到一个有点尴尬的局面:现场设备只给了一个RS485口、一份几十页写着“自定义协议”的文档,要么是仪表、扫码枪、LED屏,要么是某个老款变频器,厂家只肯说“我们走串口,支持读写寄存器”,问能不能连PLC,对方就甩过来一句“你们PLC支持什么协议”。标准PPI和Modbus RTU都不对口,命令帧格式完全是自己家定的,这时候就得把串口从“标准协议模式”切换成自由口模式,让S7-200 SMART把每一个字节都交给你的程序来处理。这篇文章我就用实际做过的项目思路,把S7-200 SMART自由通讯从硬件接线、寄存器配置、XMT/RCV指令,到一个典型轮询例程的完整逻辑,一层层拆开讲清楚。不管你手里是CPU自带串口还是加了SB CM01信号板,只要想和自定义协议设备通信,这篇文章都值得从头到尾看一遍。
自由口这名字听起来很自由,但它不是“无协议”的乱发模式,相反,它是把协议从“PLC固件替你处理”改成“你自己用程序处理”。帧头、帧尾、校验、超时、错误重发,全都要在梯形图或者STL里自己搭建。说白了,它不是让你省力,而是让你从零开始掌握这根串口的全部控制权。
1. 自由口在什么场景下非用不可
1.1 标准协议搞不定的那类设备
我在项目里遇到最多的情况是三类:第一类是串口仪表,比如温控表、流量计、称重仪表,厂家协议各不相同,有的用ASCII格式带回车结尾,有的用二进制帧带CRC校验;第二类是扫码枪、读卡器这类快速出数据的设备,它们通常不会主动跟你协商协议,一上电就开始按自己的节奏往串口上吐数据;第三类是上位机或者第三方控制器,对方是主站,不定时往PLC里下命令,PLC需要实时响应。
这三类设备的共同点是:通讯的主动权不完全在PLC手里,或者协议根本无法用现成的PPI、Modbus库去适配。遇到这种情况,如果你还要硬套Modbus RTU库,那就得接受一个现实:对方的寄存器映射、命令组帧方式、校验规则根本不兼容,你找厂家改协议,往往比你自己写自由口程序更耗时。
1.2 自由口和PPI、Modbus的关系:先分清三种玩法
很多新手一听到自由口就以为S7-200 SMART的串口默认就是自由口,其实不是。S7-200 SMART的串口在出厂状态和大多数调试场景下都运行在PPI协议模式,这是西门子自己的一套通讯协议。此外,通过指令库也可以实现Modbus RTU主站/从站功能。
三个东西放在一起,很多人容易糊涂:
| 模式 | 本质 | 适合场景 | 你需要做的工作 |
|---|---|---|---|
| PPI | 西门子私有协议 | 西门子设备互连、触摸屏通讯 | 几乎零配置 |
| Modbus RTU | 公开的标准串口协议 | 支持Modbus协议的仪表、变频器 | 调库函数、配置从站地址 |
| 自由口 | 裸串口收发,无协议 | 自定义协议设备、私有Cmd帧 | 帧格式、校验、超时全部自己写 |
自由口不是三种之一,而是另外两种的底层基础。我后来用Modbus RTU库时特别注意了一个细节:库指令底层其实离不开XMT/RCV这套发送接收机制,指令库只是把协议组帧、解析、校验封装成了模块。所以你先把自由口玩明白了,再用Modbus库或者自己改协议,心里都会清晰很多。
1.3 你一定会用到的场景清单
根据我做过的项目,下面这些场景基本都能归到自由口:
- PLC做主站,轮询多个RS485仪表,各仪表协议相同但都是私有帧;
- PLC接扫码枪,扫码枪主动上传一维码/二维码数据,PLC只负责接收和解析;
- PLC与触摸屏或第三方HMI之间用自定义协议传输非标数据块;
- PLC做从站,接收上位机或另一台PLC下发的命令帧,解析后返回结果。
记住一个判断方法:如果对方协议里出现了Modbus的功能码、寄存器地址、CRC16算法,直接改用Modbus库更省事;如果对方协议里有你们俩讨论出来的“帧头+长度+命令+校验”这种私有结构,或者干脆就是一串不定长ASCII文本,那自由口就是唯一出路。
2. 动手前的三个硬件事实:端口、极性、调试通道
2.1 串口资源:Port0和SB CM01
S7-200 SMART的CPU本体上通常会有一个RS485串口,也就是Port0,这是最常见的自由口通道。如果项目里一个串口不够用,比如Port0要跑Modbus RTU,Port1还要接自由口设备,那就可以加一块SB CM01信号板,扩展出第二个RS485接口,也就是Port1。
这两组口在使用自由口时是独立的,各自有自己的的控制寄存器、接收缓冲区和中断事件。Port0的控制字是SMB30,Port1是SMB130,接收相关的寄存器也都有两套,写程序时一定要看清自己用的是哪个端口,否则明明配的是Port1,却往SMB30里写配置,对方设备自然没反应。
2.2 RS485接线里最容易翻车的三个点
自由口协议是软件的事,但通讯成不成,很大一部分取决于硬件接线。我做现场时最常翻车的就三个点:
第一个是A/B极性。RS485是差分信号,A和B接反了会导致完全收不到数据,或者时好时坏。不同厂家的设备对端子标法还不一样,有的标A+、B-,有的标A-、B+,甚至还见过标成DATA+、DATA-的。最稳妥的办法是看设备手册里的接线图,而不是想当然地按颜色接。用万用表测一下对地电压也能判断:正常静态时A线对地电压比B线高一点点,如果测得相反,说明极性接反了。
第二个是终端电阻。RS485在长距离或者高速通讯时,线两端最好各并联一个120欧左右的终端电阻,用来吸收信号反射。很多调试现场距离只有十几米,不接终端电阻也能跑,但一旦距离超过几十米,或者波特率到了19200以上,不接电阻就可能会出现偶发乱码、偶发通讯失败。可以在设备侧先不接,跑不通再补上,但心里要清楚这是常见干扰源。
第三个是共地问题。RS485虽然只用两根信号线A和B,但它不是完全隔离的,两端设备的参考地如果不一致,共模电压太高就会烧接口或者导致通讯错乱。我在现场处理时,如果设备说明书明确要求共地,就把两端的工作地连起来;如果不能确定,优先选择带隔离的转换器来避免隐患。
2.3 为什么S7-200 SMART比老S7-200更适合玩自由口
初期用过老款S7-200的人应该知道,那个时代的CPU把编程口和自由口放在同一个串口上,一旦你把串口切成自由口模式,在线监视、程序下载就全断了,只能小心翼翼切回PPI模式,或者在启动时快速拔插编程线。而S7-200 SMART放弃了串口编程,改为通过以太网口进行程序下载和在线监视,这样串口就可以长期稳定地工作在自由口模式下,完全不影响你边调程序、边看监控。
这个变化在实际项目中价值非常大。我以前调试一个自由口读取温度的案例时,程序改一遍就要切换一次通讯模式,来回折腾相当痛苦。用S7-200 SMART之后,网线一插,串口摘下来给设备用,监控表、状态图表照样实时刷新,调试效率完全不一样。
3. 自由口靠什么运转:XMT/RCV指令、缓冲区与中断事件
3.1 XMT发送:缓冲区第一个字节是“长度”
S7-200 SMART自由口通讯中,发送数据用XMT指令,格式非常简单:
XMT TABLE, PORTTABLE是发送缓冲区首地址,PORT是串口号。PORT就是0或1。重点在于缓冲区格式:这个缓冲区所在的数据区里,从首地址开始的那一个字节,必须填入本次要发送的字节数,后续的字节才是真正要发到串口上的数据。
我举个例子。你想发送“AA 55 01 01 01 03”这6个字节,缓冲区就可以这么规划:
| 地址 | 内容 | 说明 |
|---|---|---|
| VB100 | 16#06 | 发送长度,6字节 |
| VB101 | 16#AA | 帧头1 |
| VB102 | 16#55 | 帧头2 |
| VB103 | 16#01 | 从站地址 |
| VB104 | 16#01 | 功能码 |
| VB105 | 16#01 | 数据长度 |
| VB106 | 16#03 | 校验和 |
程序里填充好这7个字节后,执行一次XMT VB100, 0,PLC就会把VB101到VB106共6个字节依次发出去。XMT一次只能发一帧,而且同一时刻只能有一个发送任务在执行,所以在发送完成之前不要再次调用XMT给同一个端口,否则程序会报错或者数据发得不完整。
3.2 RCV接收:先理解它是个“挂在后台的任务”
和XMT对应的接收指令是RCV:
RCV TABLE, PORT很多第一次用RCV的人会有个误区,以为PLC执行到RCV指令的那一个扫描周期,就会立刻把串口收到的数据拿回缓冲区。实际情况不是这样。RCV是一条“挂起式”指令:它执行后,PLC就在后台监听这根串口,一旦有数据进入接收缓冲区,就会自动向缓冲区里填数,直到接收完成条件满足,然后触发一个接收完成中断事件。
RCV缓冲区格式和XMT类似但意义不同:缓冲区首地址放的是“本次实际接收到的字节数”,这个字节不是由用户预先填写的,而是由PLC的接收逻辑在接收完成后自动写入的。比如你把接收缓冲区设在VB200,那接收完成后你在监控表里看到的VB200就是一个数字,它代表这一帧一共收了多少字节。从VB201往后,才是实际收到的数据内容。
这里要特别提醒:RCV也是一个一帧任务。也就是说,RCV执行后收到的第一帧数据一旦完成,接收逻辑就停止等待了。如果你想让PLC连续接收下一帧,必须在接收完成中断程序里再执行一次RCV,把接收任务重新挂起来。
3.3 接收控制字SMB87家族怎么配
自由口接收要正常工作,光执行RCV指令还不够,必须先配置好一组与接收相关的特殊寄存器。Port0对应最核心的是SMB87以及SMB88到SMB94,Port1对应的是另一组地址。这一组寄存器做的事情,概括起来就是回答四个问题:要不要允许接收?一帧什么时候算开始?一帧什么时候算结束?最多收多少个字节?
| 寄存器 | 常用功能 | 说明 |
|---|---|---|
| SMB87 | 接收控制字 | 控制接收使能、空闲检测、超时检测等 |
| SMB88 | 起始字符 | 收到该字符才算一帧开始 |
| SMB89 | 结束字符 | 收到该字符认为一帧结束 |
| SMB90 | 空闲检测时间 | 线路空闲N毫秒后开始接收 |
| SMB92 | 消息超时时间 | 接收开始后N毫秒未完成则结束 |
| SMB93 | 字符间超时时间 | 相邻字符间隔超过N毫秒则认为帧结束 |
| SMB94 | 最大字符数 | 接收缓冲区最多能放多少字节 |
实际项目里,我很少同时用起始字符和结束字符,因为自定义协议的帧头帧尾往往要在中断服务程序里解析确认,用寄存器来硬性判断反而容易出问题。我比较习惯的配置组合是:开启接收使能、开启空闲检测、开启消息超时、开启字符间超时。这样一帧数据的起始条件是“线路空闲了一段时间后有字节进来”,结束条件是“字符间隔超时”或“总超时”,比较适合大多数主从轮询的通讯方式。
给一组常用的配置值,以Port0、9600-8-N-1为例:
LD SM0.0 MOVB 16#F0, SMB87 // 接收使能 + 消息超时 + 字符间超时 + 空闲检测 MOVB 16#05, SMB90 // 空闲检测 5ms MOVB 16#64, SMB92 // 消息超时 100ms MOVB 16#05, SMB93 // 字符间超时 5ms MOVB 16#FF, SMB94 // 最大接收255字节注意,SMB90、SMB92、SMB93这些时间值不是随便拍的。空闲检测时间要比设备正常发送前一帧的间隔短,否则容易把连续发送的两帧当成一帧;消息超时要比设备最慢的响应时间大,否则设备还没回复完,PLC就宣布“这帧结束了”;字符间超时则要根据波特率来估算,9600波特率下一个字节大约1ms多一点,设5ms左右基本不会拆帧。
3.4 中断事件:8、9、25、26怎么对应
自由口最常见的中断事件有四个:Port0接收完成事件号8,发送完成事件号9;Port1对应事件号25和26。程序里用ATCH指令把中断程序和事件号关联起来。
ATCH INT_Receive, 8 // Port0接收完成 ATCH INT_Transmit, 9 // Port0发送完成 ENI // 开全局中断接收完成中断是我最依赖的事件。一旦有数据到达,就会跳出主程序的循环逻辑,进入接收中断程序,在中断里把数据拷贝走、置位标志位,然后重新执行RCV,继续接收下一帧。发送完成中断则用来标记“上一帧已经发完了”,方便主程序判断是否可以继续发送下一帧,或者用于在发送完成后延时等待对方应答。
4. 一个完整的轮询例程:自定义协议的发送、接收与校验
4.1 先定义一个能说清楚的协议
做自由口项目,第一件事永远是先把协议帧定义清楚。我这里设计一个最简二进制协议,用于和某模拟温控仪表通讯。主站PLC向从站发读取温度命令,从站回传两个字节的温度值。
主机请求帧格式:
| 字段 | 长度 | 示例 |
|---|---|---|
| 帧头1 | 1字节 | AA |
| 帧头2 | 1字节 | 55 |
| 从站地址 | 1字节 | 01 |
| 功能码 | 1字节 | 01(读) |
| 数据长度 | 1字节 | 01 |
| 校验和 | 1字节 | 03 |
校验和算法很朴素:从站地址、功能码、数据长度三个字节累加,取低8位。这里就是01+01+01=03。
从站应答帧格式以“55 AA”开头,携带功能码81、数据长度02、两字节的温度数据,再跟一个校验和。这套格式足够暴露所有自由口例程的核心逻辑:组帧、发送、接收、校验、解析。
4.2 初始化子程序:端口配置、接收参数、中断挂接
程序结构上,我一般会单独建一个初始化子程序,在第一次扫描时调用,把端口配置、接收参数和中断都放在一起,方便维护。初始化完成之后,主程序才进入轮询逻辑。
LD SM0.0 MOVB 16#09, SMB30 // Port0自由口模式,9600bps、8数据位、无校验、1停止位 MOVB 16#F0, SMB87 // 接收使能 + 消息超时 + 字符间超时 + 空闲检测 MOVB 16#05, SMB90 // 空闲检测 5ms MOVB 16#64, SMB92 // 消息超时 100ms MOVB 16#05, SMB93 // 字符间超时 5ms MOVB 16#FF, SMB94 // 最大接收255字节 R VB100, 31 // 清空发送缓冲区和接收缓冲区前32字节,避免旧数据干扰 ATCH INT_Receive, 8 ATCH INT_Transmit, 9 ENI RCV VB200, 0SMB30这里用16#09是自由口模式的很常见配置值,具体每位定义还要以系统手册的SMB30表为准。赋值后如果你在监控表里读回SMB30,看到的应该就是你写进去的值,通讯异常时第一个排查点就是这里。
4.3 主程序轮询:定时发命令、等应答、处理超时
主程序做的事情很直白:每隔一段时间向仪表发一次读命令,发完等接收,接收完成之后就更新数据,顺便判断有没有超时。为了避免主程序发送和中断接收互相打架,我习惯用标志位来协调:
- V500.0:发送请求标志
- V500.1:发送完成标志
- V500.2:接收完成标志
- V500.3:通讯超时标志
主程序每500ms置位一次V500.0。发送子程序发现V500.0为1且端口空闲时,就执行XMT VB100, 0,同时把V500.0复位。XMT发出后,在发送完成中断里置位V500.1,表示“这一帧已经吐出去了,现在进入等待应答状态”。主程序如果等了一个超时周期都没有收到接收完成标志,就把V500.3置位,同时清一下接收缓冲区,准备下一轮发送。
这里一定要避免“发完立刻就在主程序里死等RCV”的写法。S7-200 SMART是循环扫描的,主程序里的等待如果需要几个扫描周期,靠SM0.5翻转或者定时器来做超时判断就够了。实际操作里,我用一个秒脉冲信号加计数器的方案,每500ms触发一次轮询,简单可靠。
4.4 接收中断服务:校验数据并重新挂起RCV
接收中断是自由口程序的大脑。数据送到之后,在中断里做三件事:保存长度、做校验、重新执行RCV。
INT_Receive: LD SM0.0 MOVB VB200, VB220 // 把实际接收字节数保存到VB220 // 计算校验:取地址+功能码+数据长度(可按实际协议调整) // 将计算值与帧末字节比较,一致则拷贝VB201开始的完整数据 // 到VB300开始的连续区域,并置位V500.2 RCV VB200, 0 // 重新挂起接收,等待下一帧 CRETI你肯定会问:既然重新执行RCV放在中断最后一行,那主程序怎么知道这帧数据是新的?答案是靠标志位V500.2。接收中断置位它,主程序看见V500.2为1后,立刻读取VB220和VB300里的数据,处理完再把它清零。因为RCV已经重新挂起来了,所以即使主程序慢半拍,也不会漏掉下一帧。
还有一个细节:中断服务程序里不要做太多复杂运算。拷贝数据、校验和的计算尽量精简,如果还要查表、浮点换算,最好放到主程序里做,否则中断执行时间太长会影响扫描周期和通讯稳定性。
4.5 发送完成中断的用途
XMT发送结束后,会产生发送完成中断。我一般在这个中断里置位发送完成标志。还有一个用途是控制“问→答”之间的最短间隔:有些设备要求在命令发出后等待几十毫秒再接收,或要求在发送完成后至少间隔多久才能继续发送下一帧,这个延时可以在发送完成中断里通过启动一个定时器来实现。
发送完成中断还有一个容易踩的坑:在中断里再次执行XMT,必须确认上一帧已经发送完毕且通讯状态正常,否则新发送任务会覆盖掉正在进行的发送。我见过有人刚用自由口时,在发送完成中断里直接发下一帧,结果设备端收到的第一帧就缺了尾巴。
5. 现场调试的完整排查链路与参数调优
5.1 从空载调试入手:本地环回验证收发
自由口程序第一次上电,不要直接接现场设备。先把PLC和一根RS485转USB线连好,用串口调试助手做“假设备”,这是最有效的验证手段。具体办法是:把调试助手的串口参数设置成和PLC自由口参数一致,然后让PLC定时发送读命令,调试助手收到后手工填一个应答帧发回去,看PLC的接收中断能不能触发、数据能不能正确解析。
如果周围没有转接线,可以做一个简单的环回测试:把RS485的A和B线短接在一起,让PLC发送一帧,自身接收。这种情况下,XMT发出的数据会原样被RCV收回来。如果连自发自收都失败,那问题基本出在RCV配置、中断挂接或者缓冲区地址上,而不是现场设备的问题。
我在新手阶段最喜欢用这个办法排查自由口,因为它可以把“PLC侧问题”和“设备侧问题”在几分钟内隔离开。程序改来改去都没有反应时,就先回到环回测试确认通讯链路本身是通的,再去对接设备协议。
5.2 用监控表和串口助手把问题定位到字节
现场调试自由口,两个工具缺一不可:一个是PLC侧的监控表/状态图表,一个是PC端的串口调试助手。
PLC侧需要重点监控的地址:
| 地址/参数 | 看什么 |
|---|---|
| SMB30/SMB130 | 确认端口已处于自由口模式,配置值没被程序覆盖 |
| SMB86 | 接收状态字,看接收任务是否正常 |
| SB87/SMB87系列 | 确认接收控制参数符合预期 |
| VB100 | 确认发送缓冲区长度是否正确 |
| VB200 | 确认实际接收字节数有没有变化 |
| V500.0~V500.3 | 确认标志位时序是否正常 |
串口调试助手则用来盯着物理层面上的数据流。如果PLC发了命令但设备没回,调试助手挂在设备侧能看到底是谁没发;如果设备回了帧但PLC没反映,则继续往RCV配置上排查。套用一句话就是:“帧在线上跑没跑,串口助手一抓就知道。”
5.3 典型故障对照表:乱码、收不到、拆帧、粘包
把常见故障和根因列成一张表,现场对着查很方便:
| 现象 | 常见原因 | 处理方向 |
|---|---|---|
| 完全收不到数据 | A/B极性接反 | 交换A/B接线或修改程序里的收发极性标志 |
| 偶尔收到但很快超时 | 共地不良、屏蔽层悬空 | 补接共地线、检查屏蔽层两端接地策略 |
| 收到的是乱码 | 波特率、数据位、校验位不一致 | 核对PLC自由口参数和设备实际参数完全一致 |
| 一帧被拆成多帧 | 字符间超时时间设置太短 | 增大SMB93,比如从5ms调到10ms |
| 多帧被粘成一帧 | 空闲检测时间太长或设备帧间隔太短 | 调小SMB90,或改用结束字符方式断帧 |
| 数据对但校验老失败 | 协议帧里包含长度或校验字段含义理解错误 | 对比设备协议文档逐字节核对 |
| 换了一台设备就不通 | 从站地址或波特率配置不一致 | 确认设备侧拨码开关或参数菜单 |
这里面最值得说明的是拆帧和粘包。拆帧的本质是RCV在等一帧结束的时候,判定条件太敏感了,设备两字节之间的间隔稍微一长,PLC就觉得这帧已经结束了;粘包则相反,设备两帧之间间隔本来就短,PLC的空闲检测时间又太大,两帧之间的间隔被当成了一帧中间的停顿,结果两帧数据被放在了同一个缓冲区里。
5.4 参数调优:超时时间不是拍脑袋定的
SMB90空闲检测时间、SMB92消息超时、SMB93字符间超时,这三个参数是自由口调试中最需要调的。不同波特率、不同设备响应时间下,最合理值差别很大。
我的调参流程一般是:
- 先用串口调试助手抓设备主动发送或应答的波形,看设备两帧之间的实际间隔。如果设备发完一帧后立刻发下一帧,中间间隔只有3ms,那把空闲检测设成5ms就会把两帧当成一帧,必须设成2ms以下。
- 再抓设备收到命令后到它开始应答的响应时间。如果设备处理需要80ms,那SMB92就必须大于80ms,否则还没等设备开始答复,PLC就创建了一个“空帧结束”事件。
- 最后看设备内单字节间隔。自由口多数设备按字节连续发送,字节间隔一般在数毫秒内,SMB93设成5到20ms之间大多够用。如果你的设备在发送帧中间被打断后有停顿,就不要用字符间超时断帧,改成固定字符数SMB94断帧更稳。
调参要有耐心,一次只改一个参数,改完观察一两分钟,不要同时调两三个,否则出了问题根本不知道是哪个参数影响的。
6. 从自由口起步的项目进阶:Modbus库、从站模式与双端口架构
6.1 Modbus RTU库与自由口的真实关系
S7-200 SMART的Modbus RTU库用起来确实方便,但那不意味着你可以完全忽略自由口。库指令底层封装的其实就是串口收发、中断处理、协议解析,本质上和自由口共享同一套串口物理资源。所以库和自由口不能同时使用同一个串口:如果你在程序里先用Modbus初始化指令占用了Port0,就不能再往SMB30里写自由口配置了。
如果你的设备协议本身是Modbus RTU,或者接近Modbus,我会优先建议直接用库而不是自己写自由口。自己写自由口虽然能学到东西,但Modbus库毕竟经过大量测试,CRC校验、超时处理、异常码解析都封装好了,项目开发周期短很多。自由口的价值在于补Modbus库覆盖不到的空白。
6.2 自由口做从站:接收命令帧再回应的时序控制
前面讲的例程是PLC做主站主动发起轮询,但实际项目里PLC也经常要做从站。比如上位机作为主站,不定时向PLC发命令帧,PLC收到后根据命令内容回传数据。
从站模式下的自由口编程思路和主站不完全一样。RCV仍然在后台挂着,但主程序里除了等待接收完成之外,没有固定的发送节奏。接收中断里收到命令帧后,要把数据拷贝出来,然后可以置位一个处理标志;主程序解析完成之后,再将应答帧填入发送缓冲区,执行XMT。这里有个半双工的天然限制:RS485同一时刻只能有一个方向在传数据,所以XMT执行期间实际上不能再同时接收,应答帧发出之前和发出之后,一定要保证RCV已经重新挂起或者等待发送完成,否则就会丢帧。
6.3 双端口协同的架构建议
我最近做的几个项目里,比较典型的自由口架构是双口协同:Port0用Modbus RTU库和现场多台仪表通讯,Port1用自由口和上位机或者某私有协议设备交互。这样PLC既是Modbus主站,又是自定义协议从站,一条RS485干两条活。
双口协同有一个很实际的注意点:Port0和Port1的接收参数、中断事件是独立的,但在PLC内部,两个口的中断服务程序如果同时触发,会有一个优先级问题。我一般把Port0的数据交互做成“收发分离”:Port0只负责和现场设备轮询,Port1只负责和上位机应答,两边在主程序里通过中间变量交换数据,而不是在中断服务程序里互相直接读写对方的缓冲区。这样即使某一侧通讯出问题,也不会把另一侧的逻辑拖垮。
另外,如果Port0在跑Modbus库,程序执行了Modbus初始化指令之后,它会自动重写SMB30的配置。这时候如果你还想在同一个程序里动SMB30,就会出现配置互相覆盖的怪问题。我建议把两个口的配置职责分清楚,写注释标明“此处是Port0,勿动SMB30”,避免后人维护时踩坑。
最后再分享一个小经验:自由口程序调试最核心的检查顺序永远是“物理层→配置层→协议层”,不要一上来就怀疑缓冲区偏移或校验算法。把A/B极性、共地、终端电阻这三个硬件问题排除干净,再打开监控表看SMB87、SMB90、SMB92这些参数是不是你想要的,最后才用串口助手抓帧对比协议。按这个顺序走,大部分自由口问题都能在半小时内定位。我踩过的所有坑,几乎都绕不开这“三板斧”。