Modbus 主站工具的候选名单里,ModScan 是那个从 1990 年活到现在的老名字。它确实还能用,但有两个硬伤:ModScan32 最后一次更新是 2014 年,ModScan64 停在 2017 年,官网下载页本身也是 2017 年的;演示版还限时。

因此这篇介绍 OpenModScan。理由很直接:

  • 最新版 1.16.0 发布于 2026 年 8 月 3 日,从 2025 年 12 月到现在发了 8 个版本,是真正在维护的项目;

  • MIT 许可,完全免费,没有演示版时限这回事;

  • Windows 和 Linux 都能装,ModScan 只有 Windows;

  • Windows 安装包有代码签名(SignPath Foundation 赞助),不会有"未知发布者"警告。

对比项

ModScan64

OpenModScan

授权

商业,有演示版时限

MIT,免费无限制

最后更新

2017-11-14

2026-08-03(1.16.0)

平台

仅 Windows

Windows 7+ / 主流 Linux 发行版

地址基准

固定 1 基(最小填 1)

Base0 / Base1 可切换

浮点字序

两种(正常 / 字序对调)

32 位、64 位各带 Swapped,共 17 种显示格式

扫描设备

内置设备扫描(RTU / TCP / RTU over TCP)

代码签名

它不是"功能更花哨",而是把 ModScan 那几个用户抱怨了十几年的地方(写死 1 基地址、浮点只给两种选项、捕获文件不是标准 CSV)逐个改掉了。


一、安装

从 Release 页下载:https://github.com/sanny32/OpenModScan/releases/latest

Windows(装在 Win7 以上都行;从源码编译才要求 Win10+):

32 位系统: qt5-omodscan_1.16.0_x86.exe
64 位系统: qt5-omodscan_1.16.0_x64.exe   或   qt6-omodscan_1.16.0_x64.exe

qt5 和 qt6 的区别只是打包用的 Qt 版本,功能一致。Win10/11 随便选一个,遇到界面渲染问题就换另一个试试。

Linux —— 按发行版挑:

# Debian / Ubuntu / Mint / Zorin / Astra
sudo apt install ./qt6-omodscan_1.16.0-1_amd64.deb

# RedHat / Fedora / Rocky / RedOS
sudo dnf install ./qt6-omodscan_1.16.0-1.x86_64.rpm

# SUSE / openSUSE(先导入公钥)
sudo rpm --import qt6-omodscan.rpm.pubkey
sudo zypper install ./qt6-omodscan_1.16.0-1.x86_64.rpm

# Flatpak
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install --user io.github.sanny32.omodscan.flatpak

Flatpak 用户注意:如果你要用串口,必须先把用户加进 dialout 组,否则打不开 /dev/ttyUSB0 这类设备——这跟其他串口工具(minicom、picocom)的坑完全一样。

bash sudo usermod -a -G dialout $USER

加完要重新登录或重启才生效。

从源码编译(想改代码或要最新 dev 分支):装好 Qt 5.15+ 或 Qt 6,然后 Windows 用 .\build.ps1、Linux 用 ./build.sh,可用 -qt5 / -qt6 指定 Qt 大版本。


二、开始之前:四个数据区和九种功能码

工具换新了,但协议没变。这节是后面所有操作的地基。

Modbus 的数据对象就四类,选错类型是"连上了却读不出数"的头号原因:

数据区

读功能码

写功能码

读写属性

典型用途

线圈 Coils

0x01

0x05 单写 / 0x0F 多写

可读写

继电器输出、指示灯等开关量输出

离散输入 Discrete Inputs

0x02

只读

拨码开关、接近开关等开关量输入

保持寄存器 Holding Registers

0x03

0x06 单写 / 0x10 多写

可读写

参数设定值、PID 参数、控制字(最常用

输入寄存器 Input Registers

0x04

只读

温度、电压、电流等模拟量采集

OpenModScan 支持的功能码,比上面这八个还多一个:

功能码

名称

备注

0x01 / 0x02

读线圈 / 读离散输入

读位(开关量)

0x03 / 0x04

读保持寄存器 / 读输入寄存器

读字(16 位)

0x05 / 0x0F

写单个线圈 / 写多个线圈

位写入

0x06 / 0x10

写单个寄存器 / 写多个寄存器

字写入

0x16

掩码写寄存器 Mask Write Register

只改寄存器里的指定位,其他位保持——这是 ModScan 没有的

从站执行失败时,返回的功能码是原功能码 + 0x80。 比如你发 0x03 读保持寄存器但地址不存在,从站回 0x83,后跟一个异常码:

异常码

含义

常见原因

0x01

非法功能

从站不支持这个功能码

0x02

非法数据地址

访问超出设备点表范围(最常见)

0x03

非法数据值

写入的值超出设备允许范围

0x04

从站设备故障

设备内部错误

一个真实的异常响应长这样:

01 83 02 C0 F1

站号 01、功能码 83(03 加了 0x80)、异常码 02(非法数据地址)、CRC。看到这个就不用怀疑接线了,是地址或类型选错了。


三、建立连接

连接就两种形态,OpenModScan 把它们分成 TcpSerial 两类(源码里叫 ConnectionType),传输模式则有三选:ASCII / RTU / IP

走 TCP(以太网设备或网关)

  • 填设备 IP 和端口,Modbus/TCP 默认端口 502

  • 本机要和设备同网段,或能路由过去

  • 传输模式选 IP

走串口(现场最常见)

  • 选串口号(Windows 是 COM3 这样,Linux 是 /dev/ttyUSB0

  • 波特率 / 数据位 / 校验位 / 停止位必须和从站完全一致,工业设备最常见的是 9600 8-N-1

  • 传输模式选 RTU(ASCII 模式很罕见)

RTU over TCP 也支持——就是"串口报文原样塞进 TCP",常用于串口服务器/网关。现场遇到那种一个网关后面挂一串 485 设备的场景,选这个。

连接参数和你正在看的这套显示配置是分开保存的,换设备时注意别只改了 IP 忘了改波特率。


四、Display Definition:一个对话框管住全部

OpenModScan 把"读哪些数据"集中在一个 Display Definition(显示定义) 对话框里。打开一个数据窗口后,你要在这里确认四件事:

设置项

含义

注意

从站 ID

目标设备站号(1~247)

填错就完全无响应

功能码 / 数据区

01 / 02 / 03 / 04 四选一

要和设备的点表对上

起始地址

从哪个地址开始读

受"地址基准"影响,见第六节

读取长度

读多少个点

超过了从站实际点数会直接报异常

地址空间

5 位 / 6 位

1.16.0 新增,见下

"地址空间"这个新设置值得单独说(1.16.0,2026 年 8 月刚加):它决定地址和长度字段的取值范围——选 6 位时范围是 1…65536,选 5 位时是 1…9999,而不是像以前那样永远按 16 位全范围放开。好处是输入更规范;副作用是如果你选了 5 位,就填不进大于 9999 的地址,会以为软件坏了。源码里这个枚举的默认值是 6 位

同一个对话框里还有一个 Show Hex View Buttons 开关,打开后地址、从站 ID、长度这几个输入框旁边会多出十六进制切换按钮——设备手册用十六进制写地址时很省事。


五、显示格式:17 种,够你把任何设备的数据看明白

这是 OpenModScan 相比 ModScan 提升最明显的地方。17 种显示模式,直接从源码的枚举里列出来:

类别

可选格式

占用寄存器数

位 / 原始

BinaryHex

1

16 位整数

UInt16Int16

1

32 位整数

Int32UInt32、以及各自的 Swapped 版本

2

64 位整数

Int64UInt64、以及各自的 Swapped 版本

4

浮点

FloatingPtSwappedFP(单精度 32 位)、DblFloatSwappedDbl(双精度 64 位)

2 / 4

字符串

Ansi

1(逐寄存器拼)

有一条换算规则必须记住:显示格式决定了每个值占几个寄存器——32 位类型占 2 个,64 位类型占 4 个。所以 Length=100 时,看 16 位整数有 100 个值,看 32 位浮点只有 50 个,看 64 位只剩 25 个。长度不够时数据会显示不全,看起来像"设备没返回"。

每个数据窗口都可以独立设一种格式,同一个设备的寄存器用 16 位看、另一段用浮点看,互不干扰。


六、地址基准与字序:把 ModScan 那两大坑正面解决掉

坑一:地址差 1(Base0 / Base1)

Modbus 的地址有两套数法,中间差 1:

  • 0 基(Base0):协议报文里真正的地址,第一个寄存器是 0;

  • 1 基(Base1):很多设备手册的写法,第一个寄存器叫 1;手册上那种 40001 的写法,开头的 4 是"区号前缀"(表示保持寄存器),后面的 0001 才是 1 基地址。

OpenModScan 的做法是给你一个切换开关,而不是像 ModScan 那样写死 1 基。对照关系:

设备手册写法

协议真实地址

选 Base0 时填

选 Base1 时填

40001

0

0

1

40103

102

102

103

30001

0

0

1

00001 / 10001

0

0

1

实操顺序:先按手册的基准选,读出来的数据整体错位 1 格,就切换另一个基准。别去翻文档争论——切换一次只要两秒

(源码里 AddressBase 的枚举值是 Base0 / Base1,其中 Base0 = 0。以你装机后的界面实际选择为准。)

坑二:32 位值的字序(MSRF / LSRF)

一个 32 位值(浮点或长整数)要跨两个寄存器。哪个是高位?没有一个统一约定,于是每个设备厂商自己决定:

选项

全称

含义

等价说法

MSRF

Most Significant Register First

字在前(hi, lo)

Word Normal / 大端字序 / ABCD

LSRF

Least Significant Register First

字在前(lo, hi)

Word Reversed / 字序对调 / CDAB

在 OpenModScan 里,最简单的方式是直接选带 Swapped 的显示格式——FloatingPt 对应 MSRF、SwappedFP 对应 LSRF,枚举注释里就是这么标的。需要全局调整时还可以配合字节序设置(Direct / Swapped)。

典型误判:某个寄存器读出来是 1644826112 这种离谱大数,第一反应是"通信坏了"。其实通信完全正常,只是字序选错了——换成另一个选项,往往就是那个真实的 25.6

判断顺序永远是:先确认通不通(看日志有无响应、有没有异常响应),再确认怎么解释(字序、格式)。 顺序反了会在错误的方向上耗半天。


七、看报文:Data 和 Traffic 两副面孔

数据窗口有一个显示模式开关,两档(源码里的枚举就是这两个):

模式

显示什么

什么时候用

Data

解析后的数值表格

日常监控、读数

Traffic

原始收发报文

排障:确认发出的地址对不对、CRC 对不对

这相当于 ModScan 的"显示数据流"。它有额外的价值:因为你能看见实际发出的帧,所以地址基准这类问题可以自证。比如读线圈、起始地址 0、数量 100,发出的帧是:

01 01 00 00 00 64 3D E1

字节

含义

从站地址

01

站号 1

功能码

01

读线圈

起始地址

00 00

协议里的地址是 0

数量

00 64

100 个点(0x64 = 100)

CRC

3D E1

RTU 校验,低字节在前

你在界面上填的地址和这里看到的是否差 1,一眼就清楚了——这是判断基准对不对最快的方法,不用猜

主界面下方的通讯日志更进一步:按字段拆开每一帧(事务 ID、协议 ID、从站地址、功能码、PDU 数据),原始十六进制就在旁边,还能直接复制出来贴到工单里。日志有行数上限(可调),长时间观察记得留意,别让早期记录被顶掉。


八、三个"找不到东西"时的救命工具

这三样是 ModScan 没有的,恰好对应现场最费时间的三类问题:

1. Address Scan(地址扫描)——不知道设备有哪些寄存器

对已连上的从站按地址段发读取请求,把返回有效数据的地址挑出来高亮。比从 0 盲读到 9999 高效得多。新接手一台不明设备时,这是第一个该跑的功能。

2. Modbus Scanner(设备扫描)——不知道总线上有哪些设备

支持 RTU / TCP / RTU over TCP 三种协议,可批量扫 IP 段和从站 ID 段,并发探测(不是一个个排队)。适合新系统普查、或者"这台网关后面到底挂了几个站"这种问题。扫描结果可以导出 CSV(1.15.1 新增),直接进表格统计。

扫描参数里有单点超时和并发连接数两个旋钮:现场线路慢就把超时调大,网络塞就把并发调小。

3. Message Parser + User Message(报文解析与自定义报文)

  • Message Parser:把一段裸十六进制报文粘进去,帮你解析成字段——写文档、对协议、分析别人抓的包时特别有用。

  • User Message:手工构造并发送自定义报文,用于协议一致性测试和厂商私有扩展的验证。


九、从 ModScan 迁过来:字段对照

老用户不用重新学,一一对应:

ModScan

OpenModScan

说明

Data Definition

Display Definition

配置入口,含地址空间选择

Address(最小填 1)

起始地址 + Base0/Base1

不再写死 1 基

Modbus Point Type(01~04)

功能码 / 数据区选择

同样四选一

Floating Pt. / Swapped FP.

FloatingPt / SwappedFP

还多了 64 位版本

显示数据流

Traffic 模式

看原始帧

显示选项(十进制/十六进制/二进制/浮点)

17 种显示格式

种类大幅增加

双击写入 → Write Register

Write Coil / Holding Register / Multiple / Mask Write

写入对话框重做过(1.14.0)

Address Scan / Scanner / Parser

全新能力


十、常见坑

现象

原因

解法

读出来整体错位 1

地址基准选反了

切 Base0 / Base1

数值是离谱大数(如 1644826112)

32 位值字序不对

换 Swapped 版本,或改字序设置

改了格式后数据变少

32 位占 2 个、64 位占 4 个寄存器

把读取长度按倍数放大

地址填不进去(超过 9999)

地址空间选了 5 位

切回 6 位

直接报异常响应(码 02)

地址或功能码超出设备点表

用 Address Scan 扫一下真实范围

Linux 串口打不开

用户不在 dialout 组(Flatpak 装法尤其明显)

sudo usermod -a -G dialout $USER,重新登录

界面能连、但一直没响应

波特率/校验位/数据位与从站不一致

逐项对齐,最常见是校验位(N/E/O)选错

长时间开着 CPU 占用高

旧版本问题

升到 1.15.1 以上(该版本专门修了这个)

TCP 扫描时程序崩

旧版本问题

升到 1.14.0 以上(修了扫描崩溃)

写入后设备行为异常

参数写进了 EEPROM 或触发了联锁

写前记下原值、确认写 RAM 还是 EEPROM


十一、上手路径

阶段

做什么

检验标准

第 1 步

装好后先用 Scanner 扫一遍本机网段(或自己的测试设备)

能列出在线从站和站号

第 2 步

建一个数据窗口,读保持寄存器;切到 Traffic 看发出的帧

能对上"界面地址 → 报文地址"的关系

第 3 步

Address Scan 扫一段地址范围

能看出设备真实点表的边界

第 4 步

故意把格式在 FloatingPt / SwappedFP 之间切换

能一眼认出字序问题

这四步走完,现场遇到"连不上"或"数不对",基本能当场定性——而且全程没有授权时限在背后催你。


十二、参考

  • 项目仓库(MIT 许可,作者 Alexandr Ananev):https://github.com/sanny32/OpenModScan

  • 最新版本下载:https://github.com/sanny32/OpenModScan/releases/latest

  • 版本变更记录(判断某功能从哪个版本开始有):Release 页的 Changelog

  • 支持的平台:Windows 7+、Debian 11+、Ubuntu 22.04+、Mint 22、Fedora 41、Rocky 9.7、openSUSE 15.6、Zorin 18、Alt Linux 11、Astra 1.7、RedOS 8

  • 命令行工具备选(脚本化、进 CI):mbpoll(libmodbus 系,跨平台,持续维护)