2、万用表Modbus功能码详解:03读保持寄存器、04读输入寄存器、06写单个寄存器、16写多个寄存器

功能码,说白了就是Modbus协议里的“指令代号”。

你告诉从机(万用表)要干什么,就得先发一个功能码。比如读数据、写数据,各有各的码。今天咱们就把最常用的四个功能码掰开揉碎讲清楚。

2.1 03功能码:读保持寄存器

03功能码,用来读取保持寄存器。保持寄存器是什么?就是既能读又能写的寄存器。在万用表里,通常用来存配置参数,比如量程设置、滤波系数、通信地址等。

报文格式:

主机发送:01 03 00 00 00 02 C4 0B
从机回复:01 03 04 00 01 00 02 7A 85

我来拆解一下:

  • 01:从机地址,也就是万用表的地址
  • 03:功能码
  • 00 00:起始寄存器地址(从0x0000开始)
  • 00 02:读取2个寄存器(每个寄存器2字节)
  • C4 0B:CRC校验码

从机回复里,04表示后面跟了4个字节的数据,也就是两个寄存器的值:0x0001和0x0002。

我的经验: 我个人习惯把万用表的量程配置放在保持寄存器里。比如寄存器0x0000存电压量程,0x0001存电流量程。这样上位机随时可以修改,非常灵活。

2.2 04功能码:读输入寄存器

04功能码,读输入寄存器。输入寄存器是只读的,万用表把测量结果放在这里。比如当前电压值、电流值、温度值等。

报文格式:

主机发送:01 04 00 00 00 01 31 CA
从机回复:01 04 02 01 F4 B9 86

这里读取了1个输入寄存器,地址0x0000。从机回复了2个字节:01 F4,换算成十进制就是500。如果这个寄存器代表电压值,精度是0.01V,那实际电压就是5.00V。

注意: 03和04功能码虽然都是读,但千万别搞混。03读的是可写的配置参数,04读的是只读的测量数据。我曾经见过有人用03去读测量值,结果读回来一堆乱码,折腾了半天才发现是功能码用错了。

2.3 06功能码:写单个寄存器

06功能码,写单个寄存器。一次只能写一个寄存器,适合修改单个参数。

报文格式:

主机发送:01 06 00 01 00 0A 18 0A
从机回复:01 06 00 01 00 0A 18 0A

这个例子是把寄存器0x0001的值改成0x000A(也就是10)。注意看,从机回复的报文和主机发送的完全一样,这叫“回显确认”。

嗯,这里要注意:06功能码的回复是原样返回的。如果回复和发送不一致,说明写入失败了。

避坑指南: 我曾经在项目里用06功能码修改万用表的通信波特率,结果写完寄存器后,万用表立刻切换了波特率,但上位机没反应过来,直接通信中断了。所以,修改这类关键参数时,一定要做好“先确认、后切换”的逻辑。

2.4 16功能码:写多个寄存器

16功能码,也叫10功能码(0x10),用来一次写多个寄存器。适合批量配置参数。

报文格式:

主机发送:01 10 00 00 00 02 04 00 01 00 02 7A 85
从机回复:01 10 00 00 00 02 10 08

拆解一下:

  • 01 10:从机地址 + 功能码
  • 00 00:起始寄存器地址
  • 00 02:写2个寄存器
  • 04:后面跟了4个字节的数据
  • 00 01 00 02:要写入的数据(寄存器0x0000写0x0001,寄存器0x0001写0x0002)
  • 7A 85:CRC

从机回复里,10 08是CRC校验码,表示写入成功。

我的建议: 如果你要一次性配置万用表的多个参数,比如同时设置量程、滤波、通信地址,用16功能码最合适。一次搞定,效率高。但要注意,写入的数据长度不能超过寄存器范围,否则从机会报异常。

2.5 功能码对比总结

功能码 名称 读写属性 一次操作 典型用途
03 读保持寄存器 可读可写 1~125个寄存器 读取配置参数
04 读输入寄存器 只读 1~125个寄存器 读取测量数据
06 写单个寄存器 只写 1个寄存器 修改单个参数
16 写多个寄存器 只写 1~123个寄存器 批量配置参数

你想想看,这四个功能码基本覆盖了万用表Modbus通信的所有需求。读数据用03或04,写参数用06或16。搞清楚了它们,你的万用表通信就成功了一大半。

核心要点:
  • 03读配置,04读测量,别搞反
  • 06写单个,16写多个,按需选择
  • CRC校验不能省,否则通信不稳定
  • 修改关键参数后,记得重新确认

下一章,咱们聊聊具体的代码实现,看看怎么在嵌入式系统里把这些功能码跑起来。