串口线上那点事儿:RS-485的接线哲学
上个月那个项目,差点被一条地线搞疯。三台PLC,一个威纶通触摸屏,Modbus RTU通信,本来图纸上清清爽爽。结果现场一上电,数据乱跳——有时候是0,有时候是65535,还有时候干脆超时。查了两天,最后发现是RS-485的屏蔽层被现场电工接到了机柜外壳,而外壳竟然对地有48V交流感应电!拆掉屏蔽,世界清净。所以啊,RS-485总线必须单点接地,而且最好是信号地接在一起,别跟电源地混为一谈。现场的血泪教训,教科书不会写这么细。

说实话,Modbus这套协议就像楼道里的电线——看着简单,谁都能比划两下,但真要跑起大系统,里面的门道多着呢。波特率、数据位、停止位、校验方式,这小四个参数只要有一个对不上,设备就跟你装死。好多新手问我,为什么用USB转485模块调试没问题,换上西门子的CP341卡就通信不上?很多时候是终端电阻在捣鬼。有些转换器内部带了120欧电阻,而PLC板的485接口往往也有偏置电阻,两者一湊,信号电平直接垮掉。所以调Modbus,手边常备一个示波器或者至少逻辑分析仪看波形才是正道。
Modbus TCP的迷思:以太网就一定能快?
几年前给一个水厂做上位机,业主指定要用Modbus TCP。心想这好,以太网多简单,网线一插IP一配不就完了。结果轮询200个仪表数据,更新周期居然要3秒!客户跳起来骂娘。一查,问题出在Modbus TCP的请求-响应模式,哪怕在100M网络上,你发一条读保持寄存器的指令,设备处理完了才回,一来一回至少几个毫秒,串行轮询下来自然慢成狗。跟Modbus RTU比,它只是省去了物理层的延迟,协议栈的瓶颈一点没少。后来换成多线程并发轮询,同时开多个TCP连接去读不同设备,速度才起来。所以别迷信“网上跑的就快”,协议本身的设计决定了它的天花板。

不过话说回来,Modbus TCP有个好处——它可以直接穿透路由,哪怕设备在另一个城市也能远程调试。有次出差在宾馆,VPN连回工厂,把一台振动传感器的寄存器改了个参数,爽。这种时候就感觉,这老掉牙的协议幸好出了个TCP版。
寄存器那些坑:线圈、保持寄存器与输入寄存器的爱恨情仇

问:Modbus有几种数据区?分别怎么用?
答:通用分类是四种:线圈(Coil),可读可写,开关量输出,比如控制继电器;离散量输入(Discrete Input),只读,开关量输入,比如限位开关状态;保持寄存器(Holding Register),可读可写,模拟量输出或参数,比如设定变频器频率;输入寄存器(Input Register),只读,模拟量输入,比如电流值。但到了不同厂家手里,全乱了套!有人把参数放在输入寄存器,有人放在保持寄存器,更坑的是有些仪表手册里写的是“4xxxx”,你按保持寄存器去读,回来的全是零——因为它实际是3xxxx的输入寄存器,只读,写不进去。所以啊,拿到设备第一件事不是写程序,而是用Modbus调试工具发个03、04功能码测试一下寄存器实际属性。
问:为什么读回来的浮点数全是乱的?
答:两个字:字节序。Modbus协议传输的是16位整数,浮点数占32位,也就是两个寄存器。不同设备存储顺序不一样:有的大端在前,有的小端在前,有的还奇葩到字交换(CDAB)。如果你读到的数据明显像是天文数字或者负数超级大,八成是字节序没搞对。解决办法:先读已知值(比如仪表测常温25.6℃),看寄存器原始值,反推断序。这活计没灵丹妙药,只有一个个试。
还有一次读取的最大数量限制——有些老设备最多让你一次读125个寄存器,超了就回错误码02(非法数据地址)。你以为自己聪明,分两次读,结果碰上位机只支持单线程,照样超时。逼急了直接买贵一倍的带独立通讯处理器的PLC,唉,钱能解决的问题都不是问题。
写在最后:为什么Modbus还不死?

搞了二十年工控,眼看他起朱楼,眼看他宴宾客,PROFIBUS、DeviceNet、CC-Link……一个个都被以太网浪潮拍在沙滩上,唯独Modbus纹丝不动。你说它落后吧,连ST最新单片机都内置了硬件Modbus仿真;你说它简单吧,简单到任何工程师花半天就能撸一个从站栈;更关键的是,它没有版权费,所有资料全开放。在工业界,开放和免费有时候比技术先进性更管用。新的OPC UA很香,但Modbus就像那辆破皮卡,哪里都能去,什么人都修得好。只要能跑数据,我还会用它。
其实每次教新来的小伙子Modbus,都想起二十年前自己抱着首钢的Modicon PLC手册啃的日子。协议没变,变的是我们。