ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Modbus地址规则详解:协议地址与PLC地址换算及调试避坑指南

Modbus地址规则详解:协议地址与PLC地址换算及调试避坑指南 1. 工控人绕不开的Modbus地址规则到底在讲什么搞工控的尤其是做PLC、变频器、仪表、传感器这些设备通讯的Modbus协议几乎是入门第一课。但很多人第一次接触Modbus地址的时候脑子里全是问号为什么有的地方写40001有的地方写0x0000有的地方又写400001同一个寄存器怎么地址看起来完全不一样更让人头疼的是设备手册上写的是40001你按这个地址去读结果读出来一堆乱七八糟的数据或者干脆通讯超时。这不是你代码写错了十有八九是地址规则没搞明白。Modbus地址规则这件事说大不大说小也不小。它本质上就是一套“门牌号”体系告诉你数据存在设备的哪个位置。但问题在于Modbus协议本身定义的是“功能码数据地址”的通讯格式而不同厂家在手册里呈现地址的方式千差万别。有的用协议地址有的用PLC地址有的用十进制有的用十六进制还有的加偏移量。你如果分不清这些区别调试的时候就会像无头苍蝇一样乱撞。这篇文章适合所有跟Modbus打交道的工控人看不管你是刚入行的新手还是已经调过几十台设备的老手都能从里面找到一些之前没注意到的细节。我会从地址的基本分类讲起把线圈、离散输入、输入寄存器、保持寄存器这四类数据的地址规则掰开揉碎说清楚然后重点讲协议地址和PLC地址之间的换算关系再结合我实际调试中踩过的坑给你一套可以直接抄作业的排查方法。看完之后你拿到任何一台Modbus设备的手册都能快速定位到正确的地址不再被那些五花八门的写法绕晕。2. Modbus地址的四类数据区先搞清楚门牌号分几个区2.1 四类数据区的本质区别Modbus协议在设计的时候把设备里的数据分成了四个独立的区域每个区域有自己的功能码和地址范围。你可以把它想象成一栋楼里的四个房间线圈是你可以远程控制的开关离散输入是只能看不能动的状态指示输入寄存器是设备采集回来的实时数据保持寄存器是你可以读写、用来存参数的地方。这四类数据区的核心区别在于两个维度一个是“可读还是可写”另一个是“是位数据还是字数据”。线圈和离散输入都是位数据一个地址对应一个bit要么是0要么是1。输入寄存器和保持寄存器都是字数据一个地址对应两个字节也就是16位。线圈和保持寄存器是可读可写的离散输入和输入寄存器是只读的。很多新手容易搞混的地方在于为什么要有两个只读区域和两个可读写区域直接分可读写和只读不就行了吗这里面的逻辑是离散输入和输入寄存器通常对应的是设备的物理状态比如限位开关的通断、传感器的模拟量采集值这些数据由设备本身产生上位机只能读取不能修改。而线圈和保持寄存器对应的是控制指令和配置参数上位机需要写入来改变设备的行为。分开设计的好处是设备内部可以用不同的存储介质和处理逻辑来管理这些数据同时功能码也区分开了读线圈用01读离散输入用02读保持寄存器用03读输入寄存器用04写单个线圈用05写单个寄存器用06写多个线圈用15写多个寄存器用16。2.2 地址范围与功能码的对应关系在Modbus协议规范里这四类数据区各自有明确的地址范围。线圈的协议地址范围是00000到09999离散输入是10000到19999输入寄存器是30000到39999保持寄存器是40000到49999。注意这里说的是协议地址也就是在通讯报文里实际传输的那个数值。但实际使用中很多设备支持的地址数量远没有这么多比如一个简单的温控仪表可能只有十几个保持寄存器地址从40001到40015。功能码和地址范围是严格对应的。你不可能用功能码03去读线圈也不可能用功能码01去读保持寄存器。如果你发错了功能码设备要么返回异常码要么直接不响应。我见过有人用03功能码去读一个只支持01功能码的设备结果一直超时查了半天以为是接线问题最后发现是功能码用错了。这里有一个容易忽略的点协议地址是从0开始计数的但很多手册上写的地址是从1开始的。比如保持寄存器的协议地址范围是40000到49999但手册上可能写40001到40016。这个“1”的差异就是后面要讲的PLC地址和协议地址换算的核心问题。2.3 为什么地址规则这么容易让人迷糊地址规则让人迷糊的根本原因是Modbus协议本身只定义了通讯报文里的地址格式但没有强制规定设备手册必须怎么写地址。这就导致不同厂家、不同工具、不同文档里同一个寄存器的地址可能有五六种写法。比如一个保持寄存器在协议报文里可能是0x0000在PLC地址体系里是40001在某些组态软件里是400001在另一些工具里又变成了十进制地址0。你如果不知道这些写法之间的换算关系就会觉得每个设备都在跟你玩文字游戏。更麻烦的是有些厂家在手册里写的地址是“逻辑地址”有些写的是“物理地址”还有些写的是“偏移地址”。逻辑地址是给用户看的物理地址是设备内部实际存储的地址偏移地址是相对于某个基址的偏移量。这三种地址之间的关系如果不搞清楚调试的时候就会一直对不上。3. 协议地址与PLC地址的换算搞懂这个就通了一大半3.1 协议地址和PLC地址的本质差异协议地址是Modbus报文里实际传输的地址值它是一个16位的无符号整数范围从0到65535。在报文里这个地址是用两个字节表示的高字节在前低字节在后。比如你要读保持寄存器的第一个寄存器协议地址是0x0000报文里就是00 00。PLC地址是PLC编程软件和组态软件里使用的地址格式它是在协议地址的基础上加了一个前缀和偏移量。比如保持寄存器的PLC地址是40001其中“4”是区域前缀表示保持寄存器“0001”是寄存器序号从1开始计数。所以PLC地址40001对应的协议地址是0x000040002对应的协议地址是0x0001以此类推。这个换算关系可以用一个简单的公式表示协议地址 PLC地址 - 区域基址 - 1。对于保持寄存器区域基址是40000所以协议地址 40001 - 40000 - 1 0。对于输入寄存器区域基址是30000协议地址 30001 - 30000 - 1 0。对于线圈区域基址是00000协议地址 00001 - 00000 - 1 0。对于离散输入区域基址是10000协议地址 10001 - 10000 - 1 0。3.2 不同区域的换算实例为了让你更清楚我列一个表格把四类数据区的PLC地址、协议地址和实际报文里的地址值对应起来。数据区PLC地址示例协议地址十进制协议地址十六进制报文中的地址字节线圈0000100x000000 00线圈0001090x000900 09离散输入1000100x000000 00离散输入10016150x000F00 0F输入寄存器3000100x000000 00输入寄存器3000870x000700 07保持寄存器4000100x000000 00保持寄存器40020190x001300 13这个表格里的对应关系是标准Modbus协议的定义。但实际使用中有些厂家会打破这个规则。比如有的设备手册上写保持寄存器地址是40001但实际通讯的时候协议地址是1而不是0。这种情况通常是因为厂家在实现协议的时候没有减掉那个“1”的偏移量。遇到这种设备你就需要把协议地址加1或者减1来试直到读到正确的数据。3.3 地址偏移的常见坑地址偏移是Modbus调试中最常见的坑之一。我总结了几种典型情况你对照着排查。第一种情况手册写40001协议地址用0能读到数据。这是标准实现厂家遵循了Modbus规范。第二种情况手册写40001协议地址用1才能读到数据。这是非标准实现厂家在协议地址上加了1。这种情况在一些国产仪表和早期设备上比较常见。第三种情况手册写40001但实际对应的协议地址是40001。这种情况通常出现在一些组态软件里软件本身不做地址换算直接把PLC地址当协议地址用。这时候你需要手动把地址改成0。第四种情况手册写的是十六进制地址比如0x0000但你需要转换成十进制0再发报文。这种情况在进口设备的手册里比较常见因为国外工程师习惯用十六进制。第五种情况手册写的是偏移地址比如“保持寄存器偏移0x0000”你需要加上区域基址40000变成40001再换算成协议地址0。这五种情况我在实际项目中都遇到过。最稳妥的办法是拿到设备后先用一个通用的Modbus调试工具比如Modbus Poll或者类似的软件从协议地址0开始逐个试同时观察设备手册里哪个参数会变化。比如你读到一个寄存器的值从0变成了25而手册里写温度参数是25度那这个地址就找对了。4. 实际调试中怎么快速定位正确地址4.1 从手册到实际地址的排查流程拿到一台新设备不要急着写代码先按这个流程走一遍。第一步翻手册找到“Modbus通讯地址表”或者“寄存器列表”。通常手册里会有一个表格列出每个参数的地址、数据类型、读写权限和说明。如果手册里没有这个表那就要找“通讯协议”章节里面一般会有地址定义。第二步确认手册里的地址是哪种格式。看地址的前缀如果是4开头那就是保持寄存器如果是3开头那就是输入寄存器如果是0开头那就是线圈如果是1开头那就是离散输入。如果地址没有前缀只有一个数字那就要看上下文判断是哪个区域。第三步把手册地址转换成协议地址。按照前面讲的公式PLC地址减去区域基址再减1。比如手册写40001协议地址就是0。手册写40010协议地址就是9。第四步用调试工具发报文测试。先读一个寄存器看返回值是否合理。如果读不到尝试把协议地址加1或减1再试。如果还是读不到检查功能码是否用对波特率、数据位、停止位、校验位是否匹配。第五步确认数据格式。Modbus寄存器是16位的但实际数据可能是16位整数、32位整数、浮点数、字符串等。如果是32位数据通常占用两个连续的寄存器你需要确定高低字顺序。有的设备是高字在前有的是低字在前这个在手册里一般会说明。4.2 用调试工具验证地址的实操方法我平时用得最多的调试工具是Modbus Poll它支持四类功能码可以手动设置协议地址、数量和数据类型。下面我以读取一个保持寄存器为例说一下具体的操作步骤。打开Modbus Poll新建一个连接。设置通讯参数波特率9600数据位8停止位1校验位无。这些参数必须和设备手册一致否则连不上。然后设置读取参数。功能码选03读保持寄存器协议地址填0数量填1数据类型选16位无符号整数。点击OK如果通讯正常你会看到寄存器值在实时刷新。如果读不到数据先检查接线。A接AB接BGND接GND。如果是USB转485转换器注意转换器的A/B线序有的转换器A是正B是负有的反过来。我遇到过好几次因为A/B接反导致通讯失败的情况调了半天以为是地址问题最后发现是线接错了。如果接线没问题再检查协议地址。把地址改成1再试。改成2再试。一般试到10以内就能找到正确的地址。如果试了十几个地址都读不到那可能是功能码用错了或者设备根本不支持Modbus协议。4.3 地址换算的速查表为了方便你快速换算我整理了一个速查表把常见的PLC地址和协议地址对应起来。PLC地址协议地址十进制协议地址十六进制0000100x00000000210x00010000980x00080001090x00091000100x00001000210x00013000100x00003000210x00014000100x00004000210x00014000320x00024001090x000940020190x001340100990x0063这个表里的对应关系是标准实现。如果你遇到的设备是非标准实现比如协议地址比标准值大1那就在这个表的基础上加1。5. 那些年我踩过的地址坑每一个都是教训5.1 地址从0还是从1开始这是个问题我第一次调Modbus设备的时候手册上写保持寄存器40001是温度值。我按照标准换算协议地址用0结果读出来是0。我以为设备没数据又去读40002协议地址用1读出来还是0。折腾了一个下午最后试着用协议地址1去读40001读出来25正好是室温。原来这个设备是非标准实现协议地址从1开始。这件事给我的教训是不要假设所有设备都遵循标准。标准是标准实现是实现。遇到读不到数据的情况先怀疑地址偏移再怀疑其他。后来我养成了一个习惯拿到新设备先用调试工具从协议地址0开始连续读10个寄存器看哪些地址有数据。然后对照手册看哪个地址的数据和手册描述的参数对得上。这样比一个一个试快得多。5.2 功能码用错地址再对也白搭有一次调一个变频器手册上写频率设定值是保持寄存器40001。我用功能码03去读读不到。我以为地址不对试了好几个地址都不行。后来仔细看手册发现这个变频器的频率设定值只支持写不支持读。读的话要用功能码04去读输入寄存器地址是30001。这个坑让我明白读写权限和功能码是绑定的。读保持寄存器用03写保持寄存器用06或16。读输入寄存器用04输入寄存器通常不支持写。读线圈用01写线圈用05或15。读离散输入用02离散输入不支持写。如果你用03去读一个只支持04的寄存器设备会返回异常码02表示非法数据地址。如果你用06去写一个只读的寄存器设备会返回异常码04表示从站设备故障。这些异常码在调试的时候很有用可以帮你快速定位问题。5.3 数据类型不对读出来的数就是天书Modbus寄存器是16位的但实际数据可能是32位浮点数。比如一个流量计瞬时流量是浮点数占用两个连续的保持寄存器。手册上写40001是流量值但如果你只读一个寄存器读出来的只是浮点数的一半转换成十进制就是一个莫名其妙的整数。正确的做法是读两个连续的寄存器比如40001和40002然后把两个16位数据拼成一个32位数据再按照浮点数格式解析。这里又涉及高低字顺序的问题。有的设备是40001存高16位40002存低16位有的设备反过来。你需要看手册说明或者用调试工具试一下看哪种顺序解析出来的值合理。我遇到过一台设备手册上写40001是流量但没说是浮点数。我按16位整数读读出来是0。后来用32位浮点数读读出来是123.45正好是管道里的流量。这个坑让我养成了一个习惯拿到手册先看数据类型是16位还是32位是整数还是浮点数是 signed 还是 unsigned。5.4 地址表里的保留地址不要碰有些设备的手册里地址表会标注一些“保留”或者“Reserved”的地址。这些地址是厂家预留的可能用于内部测试或者未来扩展。你如果去读这些地址可能读到随机值也可能导致设备异常。更严重的是如果你往保留地址写数据可能会导致设备死机或者参数丢失。我见过一个案例有人往一个保留寄存器写了数据结果设备的校准参数被覆盖导致测量值全部偏移。最后只能返厂重新校准。所以地址表里标注保留的地址绝对不要读写。6. 不同工具和软件里的地址写法对照6.1 组态软件里的地址格式组态软件是工控人常用的工具但不同组态软件的Modbus地址格式不一样。有的用PLC地址有的用协议地址有的用带前缀的地址。比如某个组态软件里保持寄存器的地址格式是“4:00001”其中“4”表示保持寄存器“00001”是寄存器序号。这个地址对应的协议地址是0。另一个组态软件里地址格式是“400001”多了一个0对应的协议地址还是0。还有一个组态软件里地址格式是“0”直接就是协议地址。你在组态软件里填地址的时候一定要先看软件的帮助文档确认它用的是哪种格式。如果不确定就用调试工具先确认协议地址然后在组态软件里试填看能不能读到数据。6.2 PLC编程软件里的地址格式不同品牌的PLCModbus地址格式也不一样。有的PLC用“40001”这种格式有的用“%MW0”这种格式有的用“DB1.DBW0”这种格式。比如某个品牌的PLCModbus保持寄存器的地址是“40001”对应协议地址0。另一个品牌的PLC地址是“%MW0”对应协议地址0。还有一个品牌的PLC地址是“DB1.DBW0”对应协议地址0。你在PLC里写Modbus通讯程序的时候要注意地址格式的转换。通常PLC的Modbus库函数会要求你填协议地址而不是PLC地址。如果你填错了通讯就会失败。6.3 调试工具里的地址格式调试工具是Modbus调试的利器但不同调试工具的地址格式也不一样。有的工具用协议地址有的用PLC地址有的用带前缀的地址。比如Modbus Poll它用的是协议地址你直接填0就是读第一个寄存器。而另一个调试工具可能要求你填40001。还有一个调试工具可能要求你填400001。你在用调试工具的时候先看工具的说明确认它用的是哪种地址格式。如果不确定就用协议地址试因为协议地址是最底层的所有工具最终都会转换成协议地址。7. 地址规则背后的协议原理知道这些才算真懂7.1 Modbus报文里的地址是怎么传的Modbus RTU报文里地址是用两个字节传输的。比如你要读保持寄存器的第一个寄存器功能码03协议地址0数量1报文是这样的从站地址 03 00 00 00 01 CRC。其中“00 00”就是协议地址“00 01”是寄存器数量。从站收到这个报文后会解析出功能码03协议地址0数量1然后从保持寄存器的第一个位置读取数据返回响应报文从站地址 03 02 数据高字节 数据低字节 CRC。其中“02”是数据字节数表示后面有两个字节的数据。如果你把协议地址改成1报文就变成从站地址 03 00 01 00 01 CRC。从站会读取保持寄存器的第二个位置。所以协议地址是直接对应寄存器位置的从0开始计数。7.2 为什么要有PLC地址这种写法PLC地址这种写法最早是为了方便工程师在PLC编程软件里直观地看到地址属于哪个区域。比如40001一眼就能看出是保持寄存器的第一个寄存器。如果直接用协议地址0你还要想一下这是哪个区域的。但PLC地址这种写法也带来了混淆。不同厂家对PLC地址的定义不一样有的从1开始有的从0开始有的加前缀有的不加。所以后来Modbus协议规范里推荐使用协议地址也就是从0开始的地址。现在很多新设备的手册直接写协议地址比如“保持寄存器0x0000”这样就不会有歧义。但老设备的手册还是用PLC地址比如“40001”。你遇到哪种就按哪种的规则来换算。7.3 地址范围与设备实际容量的关系Modbus协议规定的地址范围很大线圈00000到09999离散输入10000到19999输入寄存器30000到39999保持寄存器40000到49999。但实际设备不可能支持这么多地址通常只有几十个到几百个。比如一个简单的温度变送器可能只有两个保持寄存器一个存温度值一个存设备地址。地址是40001和40002。你如果去读40003设备会返回异常码02表示非法数据地址。所以你在调试的时候不要盲目地读一大堆地址先看手册里设备支持哪些地址然后只读这些地址。如果手册里没写就用调试工具从0开始读读到异常码就停。8. 常见问题速查与避坑指南8.1 通讯超时怎么办通讯超时是最常见的问题原因可能有很多。我按排查顺序列一下。先检查接线。A接AB接BGND接GND。如果是485通讯还要检查终端电阻。短距离通讯可以不加终端电阻长距离通讯需要在两端各加一个120欧姆的电阻。再检查通讯参数。波特率、数据位、停止位、校验位必须和设备一致。常见的组合是9600-8-1-N但有的设备是19200-8-1-E或者38400-8-1-N。你如果设错了设备不会响应。然后检查从站地址。Modbus RTU报文里的第一个字节是从站地址范围1到247。你如果填0是广播地址所有从站都会收到但不会响应。你如果填248以上是保留地址设备不会响应。最后检查协议地址。如果协议地址超出了设备支持的范围设备会返回异常码而不是超时。但如果协议地址格式不对比如你填了一个负数或者填了一个超过65535的数设备可能直接不响应。8.2 读到的数据不对怎么办读到的数据不对通常有几种情况。一种是数据格式不对。比如设备返回的是32位浮点数你按16位整数解析读出来就是一个莫名其妙的整数。你需要确认数据类型然后按正确的格式解析。一种是高低字顺序不对。32位数据占用两个寄存器有的设备高字在前有的低字在前。你需要试一下两种顺序看哪种解析出来的值合理。一种是地址偏移不对。你读的地址可能不是你想要的那个参数。你需要对照手册确认地址是否正确。如果手册写40001你读协议地址0读出来不对试试协议地址1。一种是设备本身的问题。比如传感器故障或者设备处于校准模式返回的数据就是无效的。你需要检查设备状态确认设备正常工作。8.3 写数据不生效怎么办写数据不生效通常有几种情况。一种是功能码用错了。写单个寄存器用06写多个寄存器用16。你如果用03去写设备不会执行写操作。一种是地址不对。你写的地址可能不是控制参数的那个地址。你需要对照手册确认写地址是否正确。一种是数据范围不对。比如你写一个频率设定值设备支持的范围是0到50Hz你写60Hz设备可能拒绝写入或者写入后自动恢复到50Hz。一种是设备处于保护模式。有的设备有写保护功能需要先解除保护才能写入。你需要看手册确认是否需要先写某个寄存器来解除保护。8.4 常见异常码速查表Modbus协议定义了一些异常码设备返回异常码的时候你可以根据异常码快速定位问题。异常码含义可能原因01非法功能码设备不支持该功能码02非法数据地址协议地址超出设备支持范围03非法数据值写入的数据超出允许范围04从站设备故障设备内部错误无法完成操作05确认设备已收到请求正在处理06从站设备忙设备正在处理其他请求稍后重试08存储奇偶校验错误设备存储区校验失败10网关路径不可用网关无法转发请求11网关目标设备无响应网关无法连接到目标设备这个表里的异常码你在调试的时候会经常遇到。比如异常码02说明地址不对你需要检查协议地址。异常码03说明数据值不对你需要检查写入的数据范围。异常码06说明设备忙你需要等一会儿再试。9. 一套可以直接抄作业的Modbus地址调试流程9.1 调试前的准备工作在开始调试之前你需要准备这些东西设备手册、调试工具、通讯线、电脑。设备手册用来查地址表和通讯参数调试工具用来发报文和看响应通讯线用来连接设备和电脑电脑用来运行调试工具。通讯线通常是USB转485转换器或者USB转232转换器。如果是485通讯转换器的A接设备的AB接设备的BGND接设备的GND。如果是232通讯转换器的TX接设备的RXRX接设备的TXGND接设备的GND。调试工具我推荐用Modbus Poll它支持四类功能码可以手动设置协议地址、数量和数据类型还可以保存调试记录。如果你没有Modbus Poll也可以用其他类似的工具比如QModMaster、Simply Modbus等。9.2 分步调试流程第一步设置通讯参数。打开调试工具新建连接设置波特率、数据位、停止位、校验位。这些参数必须和设备手册一致。第二步设置从站地址。从站地址通常是1但有的设备是2或者3。你如果不确定可以试1到10。第三步设置功能码和协议地址。先读保持寄存器功能码03协议地址0数量1。点击发送看响应。第四步如果响应正常记录数据。如果响应异常看异常码。异常码02说明地址不对试试协议地址1。异常码01说明功能码不对试试功能码04。第五步找到正确的协议地址后对照手册确认参数。比如你读协议地址0读出来25手册里写40001是温度值那协议地址0就对应40001。第六步测试写功能。如果需要写参数用功能码06写单个寄存器或者功能码16写多个寄存器。写入后读回来确认。9.3 调试记录模板调试的时候建议你记录一下关键信息方便后续排查。我通常记录这些内容设备型号、通讯参数、从站地址、功能码、协议地址、读到的数据、异常码、备注。设备型号通讯参数从站地址功能码协议地址读到的数据异常码备注温度变送器9600-8-1-N103025无温度值温度变送器9600-8-1-N1031100无量程上限温度变送器9600-8-1-N10320无量程下限温度变送器9600-8-1-N1033无02地址超出范围这个记录模板可以帮你快速定位问题。比如你发现协议地址3返回异常码02说明设备只支持0到2这三个寄存器。你如果去读协议地址4也会返回异常码02。10. 地址规则学会了调试效率翻倍Modbus地址规则这件事说穿了就是一层窗户纸。你搞懂了协议地址和PLC地址的换算关系搞懂了四类数据区的功能码和地址范围搞懂了不同工具和软件里的地址写法调试的时候就不会再被那些五花八门的地址格式绕晕。我个人的经验是拿到新设备先别急着写代码先用调试工具把地址表过一遍。从协议地址0开始连续读几十个寄存器看哪些地址有数据哪些地址返回异常码。然后对照手册把每个地址和参数对应起来。这个过程可能花十几分钟但能帮你省下几个小时的调试时间。还有一个技巧是把常用设备的地址表整理成一个文档下次遇到同型号设备直接查文档就行。我这些年积累了几十种设备的地址表每次调试新设备先翻文档找不到再从头试。这个习惯让我在项目现场少加了很多班。最后说一个容易被忽略的点Modbus地址是16位的但有些设备支持扩展地址比如用两个寄存器表示一个32位地址。这种情况在大型PLC和远程IO模块上比较常见。你如果遇到地址超过65535的情况就要考虑是不是扩展地址需要看手册确认。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进