功能码决定做什么
功能码是 Modbus 请求的第一个字节,决定对哪类数据区执行什么操作。常用功能码可分为读类与写类:读线圈、读离散输入、读保持寄存器、读输入寄存器用于采集;写单个与多个线圈、写单个与多个寄存器用于控制与参数下发;另有掩码写寄存器、读写多个寄存器与设备识别等特殊功能。理解功能码的实际意义是:在网关或防火墙上限制可用功能码,本身就是一种有效的访问控制。
常用功能码
| 0x01 读线圈 | 读取开关量输出状态 |
|---|---|
| 0x02 读离散输入 | 读取开关量输入状态 |
| 0x03 读保持寄存器 | 读取可写参数与设定值 |
| 0x04 读输入寄存器 | 读取测量值 |
| 0x05 写单个线圈 | 控制单个开关量 |
| 0x06 写单个寄存器 | 写单个参数 |
| 0x0F 写多个线圈 | 批量控制开关量 |
| 0x10 写多个寄存器 | 批量下发参数 |
| 0x16 掩码写寄存器 | 按位修改寄存器内容 |
| 0x17 读写多个寄存器 | 一次完成读与写 |
| 0x2B 设备识别 | 读取设备信息,子功能区分用途 |
读类与写类的用法
| 类别 | 功能码 | 使用场合 | 注意 |
|---|---|---|---|
| 读开关量 | 01、02 | 状态采集与画面显示 | 区分只读区与可读写区 |
| 写开关量 | 05、0F | 设备启停与阀门控制 | 写操作应有授权与审计 |
| 读寄存器 | 03、04 | 测量值、参数与状态读取 | 注意数据类型与字节序 |
| 写寄存器 | 06、10、16 | 参数下发与设定值修改 | 写操作影响物理行为,需审批 |
| 组合操作 | 17 | 需要读改写连续进行 | 部分设备不支持复杂功能码 |
使用与限制建议
- 采集只使用读类功能码,写类功能码单独授权并记录
- 设备对不支持的功能码返回异常码 01,属于正常的保护行为
- 批量读取要遵守各功能码的单次数量上限,具体数值以协议规范为准
- 掩码写等复杂功能码并非所有设备支持,上线前需实测
- 在网络侧尽量按功能码做白名单,只放行业务必需的操作
只限制端口不限制功能码是常见的防护缺口:放行 502 端口就等于允许设备支持的读写类功能码。具备协议级过滤能力的工业防火墙或网关可以把限制收敛到功能码与地址范围。
写类功能码直接影响物理过程:一条 0x10 指令可一次改动多个寄存器。默认把写类功能码一并开放给采集系统,是工控环境里比较危险的权限设计。