Modbus是一种单主站的主/从通讯模式。Modbus网络上只有一个主站,主站在Modbus网络上没有地址,从站的地址范围为0-247,其中0为广播地址,从站的实际地址范围为1-247。
| 代码 | 名称 | 作用 |
| 01 | 读取线圈状态 | 取得一组逻辑线圈的当前状态(ON/OFF) |
| 02 | 读取输入状态 | 取得一组开关输入的当前状态(ON/OFF) |
| 03 | 读取保持寄存器 | 在一个或多个保持寄存器中取得当前的二进制值 |
| 04 | 读取输入寄存器 | 在一个或多个输入寄存器中取得当前的二进制值 |
| 05 | 强制单线圈 | 强置一个逻辑线圈的通断状态 |
| 06 | 预置单寄存器 | 放置一个热定特定的二进制值到一个单寄存器中 |
| 07 | 读取异常状态 | 取得8个内部线圈的通断状态 |
| 15 | 强置多线圈 | 强置一串连续逻辑线圈的通断 |
| 16 | 预置多寄存器 | 放置一系列特定的二进制值到一系列多寄存器中 |
| 17 | 报告从机标识 | 可使主机判断编址从机的类型及该从机运行指示灯的状态 |
读取从机离散量输出口的(ON/OFF)状态,不支持广播。
查询:查询信息规定了要读的起始线圈和线圈量,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H-0015H(DO1=0000H,DO2=0001H,以此类推)。
例子:从地址为17的从机读取D01至D06的状态。
| addr | Fun | D0 start reg hi | D0 start reg lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 起始线圈地址高8位 | 起始线圈地址低8位 | 线圈量高8位 | 线圈量低8位 | 校验高8位 | 校验低8位 |
| 11H | 01H | 00H | 00H | 00H | 06H | XXH | XXH |
响应:响应信息中的各线圈的状态与数据区的每一位的值相对应,即每个D0占用一位(1=ON,0=OFF),第一个数据字节的LSB为查询中的寻址地址,其他的线圈按顺序在该字节中由低位向高位排序,直至8个为止,下一个字节也是从低位向高位排列。若返回的线圈数不是8的倍数,则在最后的数据字节中的剩余位至字节的最高位全部填0,字节数区说明全部的字节数。
| addr | Fun | Byte count | Data | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 字节数 | 数据位 | 校验高8位 | 校验低8位 |
| 11H | 01H | 01H | 2AH | XXH | XXH |
数据:
| 0 | 0 | 0 | 0 | 0 | 0 | D02 | D01 |
| MSB | 7 | 6 | 5 | 4 | 3 | 2 | LSB |
读取从机离散量输入信号(ON/OFF)的状态,不支持广播。
查询:查询信息规定了要读的输入起始地址,以及输入信号的数量。输入的起始地址为0000H,1-16个输入口的地址分别为0-15(DO1=0000H,DO2=0001H,以此类推)。
例子:从地址为17的从机读取D01至D16的状态。
| addr | Fun | D0 start reg hi | D0 start reg lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 起始线圈地址高8位 | 起始线圈地址低8位 | 线圈量高8位 | 线圈量低8位 | 校验高8位 | 校验低8位 |
| 11H | 02H | 00H | 00H | 00H | 10H | XXH | XXH |
响应:响应信息中的各输入口的状态,分别对应于数据区中的每一位值,1=ON,0=OFF,第一个数据字节的LSB为查询中的寻址地址,其他输入口按顺序在该字节中由低位向高位排序,直至8个为止,下一个字节中的8个输入位也是从低位向高位排列。若返回的输入位数不是8的倍数,则在最后的数据字节中的剩余位直至字节的最高位全部填0,字节数区说明了全部数据的字节数。
| addr | Fun | Byte count | Data1 | Data2 | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 字节数 | 数据位 | 数据位 | 校验高8位 | 校验低8位 |
| 11H | 02H | 02H | 33H | CCH | XXH | XXH |
数据1:
| DI8 | DI7 | DI6 | DI5 | DI4 | DI3 | DI2 | DI1 |
| MSB | LSB |
数据2:
| DI16 | DI15 | DI14 | DI13 | DI12 | DI11 | DI10 | DI9 |
| MSB | LSB |
读取从机保持寄存器的二进制数据,不支持广播。
查询:查询信息规定了要读的保持寄存器起始地址及保持寄存器的数量,保持寄存器寻址其实地址为0000H,寄存器1-16所对应的地址分别为0000H-0015H。
例子:从17号从机读3个采集到的基本数据U1、U2、U3,U1的地址为0000H,U2的地址为0001H,U3的地址为0002H。
| addr | Fun | Data start addr hi | Data start addr lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器起始地址高8位 | 寄存器起始地址低8位 | 寄存器数量高8位 | 寄存器数量低8位 | 校验高8位 | 校验低8位 |
| 11H | 03H | 00H | 00H | 00H | 03H | XXH | XXH |
响应:响应信息中的寄存器数据位二进制数据,每个寄存器分别对应2个字节,第一个字节为高位值数据,第二个字节为低位数据。
读取U1、U2、U3(U1=03E8H,U2=03E7H,U3=03E9H)的响应。
| addr | Fun | Byte count | Data1 hi | Data1 lo | Data2 hi | Data2 lo | Data3 hi | Data3 lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 字节数 | 数据1高8位 | 数据1低8位 | 数据2高8位 | 数据2低8位 | 数据3高8位 | 数据3低8位 | 校验高8位 | 校验低8位 |
| 11H | 03H | 06H | 03H | E8H | 03H | E7H | 03H | E6H | XXH | XXH |
读取从机输入寄存器中的二进制数据,不支持广播。
查询:查询信息规定了要读的寄存器起始地址及寄存器的数量,寻址起始地址为0,寄存器1-16所对应的地址分别为0000H-0015H。
例子:请求17号从机的0009寄存器。
| addr | Fun | D0 addr hi | D0 addr lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器起始地址高8位 | 寄存器起始地址低8位 | 寄存器数量高8位 | 寄存器数量低8位 | 校验高8位 | 校验低8位 |
| 11H | 04H | 00H | 08H | 00H | 03H | XXH | XXH |
响应:响应信息中的寄存器为每个寄存器分别对应2个字节,第一个字节为高位数据,第二个字节为低位数据。
| addr | Fun | Byte count | Data hi | Data lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 字节数 | 数据位 | 数据位 | 校验高8位 | 校验低8位 |
| 11H | 04H | 02H | 00H | 0AH | XXH | XXH |
强制单个线圈为ON或OFF状态,广播时,该功能可强制所有从机中同一类型的线圈均为ON或OFF状态。
该功能可跨过控制器内存的保护状态和线圈的禁止状态。线圈强制状态一直保持有效直至下一个控制逻辑作用于线圈为止。控制逻辑中无线圈程序时,则线圈处于强制状态。
查询:查询信息规定了需要强制一个单独线圈的类型,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H-0015H(DO1=0000H,DO2=0001H,以此类推)。
由查询数据区中的一个常量,规定请求线圈的ON/OFF状态,FF00H值请求线圈处于ON状态,0000H值请求线圈处于OFF状态,其他值对线圈无效,不起作用。
例子:请求17号从机开D01的ON状态。
| addr | Fun | D0 addr hi | D0 addr lo | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器地址高8位 | 寄存器地址低8位 | 寄存器值高8位 | 寄存器值低8位 | 校验高8位 | 校验低8位 |
| 11H | 05H | 00H | 00H | FFH | 00H | XXH | XXH |
响应:对这个命令请求的正常响应是在D0状态改变后传送接收到的数据。
| addr | Fun | D0 addr hi | D0 addr lo | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器地址高8位 | 寄存器地址低8位 | 寄存器值高8位 | 寄存器值低8位 | 校验高8位 | 校验低8位 |
| 11H | 05H | 00H | 00H | FFH | 00H | XXH | XXH |
把一个值预置到一个保持寄存器中,广播时,该功能把值预置到所有从机的相同类型的寄存器中。
该功能可跨过控制器的内存保护。使寄存器中的预置值保持不变。只能由控制器的下一个逻辑信号来处理该预置值。若控制逻辑中无寄存器程序时,则寄存器中的值保持不变。
查询:查询信息规定了要预置寄存器的类型,寄存器寻址起始地址为0000H,寄存器1所对应的地址为0000H。
例子:请求17号从机0040H的值为2177.
| addr | Fun | Data start addr hi | Data start addr lo | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器地址高8位 | 寄存器地址低8位 | 数据高8位 | 数据低8位 | 校验高8位 | 校验低8位 |
| 11H | 06H | 00H | 40H | 0AH | 9DH | XXH | XXH |
响应:对于预置单寄存器请求的正常响应是在寄存器的值改变以后 将接受到的数据传送回去。
| addr | Fun | Data start addr hi | Data start addr lo | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器地址高8位 | 寄存器地址低8位 | 数据高8位 | 数据低8位 | 校验高8位 | 校验低8位 |
| 11H | 06H | 00H | 40H | 0AH | 9DH | XXH | XXH |
读从机中8个不正常状态线圈的数据,某些线圈号已在不同型号的控制器中预定义,而其他的线圈由用户编程,作为有关控制器的状态信息,如“machien ON/OFF”,“heads retraced”,(缩回标题),“safeties satisfied”(安全性满意),“error conditions”(存在错误条件)或其它用户定义的标志等。该功能码不支持广播。
该功能码为存取该类信息提供了一种简单的方法,不正常线圈的类型是已知的(在功能代码中不需要线圈类型)预定义的不正常线圈号如下:
| 控制器型号 | 线圈 | 设定 |
| M84,184/384,584,984 | 1-8 | 用户定义 |
| 484 | 257 | 电池状态 |
| 258-264 | 用户定义 | |
| 884 | 761 | 电池状态 |
| 762 | 内存保护状态 | |
| 763 | R10工况状态 | |
| 764-768 | 用于预定义 |
查询:请求读从机设备17中的不正常状态。
| addr | Fun | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 校验高8位 | 校验低8位 |
| 11H | 06H | XXH | XXH |
响应:正常响应包含8个不正常的线圈状态,为一个数据字节,每个线圈一位。LSB对应为最低线圈类型的状态。
按查询要求返回响应:
| addr | Fun | D0 Data | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 数据 | 校验高8位 | 校验低8位 |
| 11H | 06H | 6DH | XXH | XXH |
该例子中,线圈数据为6DH(二进制0110,1101),从左到右(最高位至最低位)的线圈状态分别为:OFF-ON-ON-OFF-ON-ON-OFF-ON。若控制器型号为984,这些位表示线圈8至1的状态;若控制器型号为484则表示线圈264至257的状态。
按线圈的顺序把各线圈强制成ON或OFF。广播时,该功能代码可对各从机中相同类型的线圈起强制作用。
该功能代码可跨过内存能保护和线圈的进制状态线圈。保持强制状态有效,并只能由空、感知器的下一个逻辑来处理。若无线圈控制逻辑程序时,线圈将保持强制状态。
查询:查询信息规定了被强制线圈的类型,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H-0015H(DO1=0000H,DO2=0001H,以此类推)。
查询数据区规定了被请求线圈的ON/OFF状态,如数据区的某位值为“1”表示请求的响应线圈状态为ON,位值为“0”,则为OFF状态。
例子:请求从机设备17中一组10个线圈为强制状态,起始线圈为20(则寻址地址为19或13H),查询的数据为2个字节,CD01H(二进制1100 1101 0000 0001)响应线圈的二进制位排序如下:
| Bit: | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| Coil: | 27 | 26 | 25 | 24 | 23 | 33 | 21 | 20 | - | - | - | - | - | - | 29 | 28 |
传送的第一个字节CDH对应线圈为27-20,LSB对应线圈20,传送的第二个字节为01H,对应的线圈为29-28,LSB为对应线圈28,其余未使用的位均填“0”。
| addr | Fun | D0 addr hi | D0 addr lo | D0 #of regs hi | D0 #of regs lo | Byte count | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 起始地址高8位 | 起始地址低8位 | 寄存器数量高8位 | 寄存器数量低8位 | 字节数 | 数据高8位 | 数据低8位 | 校验高8位 | 校验低8位 |
| 11H | 0FH | 00H | 13H | 00H | 0AH | 02H | CDH | 01H | XXH | XXH |
响应:正常响应返回从机地址,功能码,起始地址以及强制线圈数。
| addr | Fun | D0 addr hi | D0 addr lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器地址高8位 | 寄存器地址低8位 | 寄存器值高8位 | 寄存器值低8位 | 校验高8位 | 校验低8位 |
| 11H | 0FH | 00H | 13H | 00H | 0AH | XXH | XXH |
把数据按顺序预置到各寄存器中,广播时该功能代码可把数据预置到全部从机中的相同类型King的寄存器中。
该功能代码可跨过控制器的内存保护,在寄存器中的预置值一直保持有效,只能由控制器的下一个逻辑来处理寄存器的内容,控制逻辑中无该寄存器程序时,则寄存器中的值保持不变。
查询:查询信息规定了要预置寄存器的类型,寄存器寻址起始地址为0000H,寄存器1所对应的地址为0000H。
例子:请求17号从机0040H的值为178077833.(十六进制为 0A9D 4089)
| addr | Fun | Data start reg hi | Data start reg lo | D0 #of regs hi | D0 #of regs lo | Byte count | Value hi | Value lo | Value hi | Value lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器起始地址高8位 | 寄存器起始地址低8位 | 寄存器数量高8位 | 寄存器数量低8位 | 字节数 | 数据高8位 | 数据低8位 | 数据高8位 | 数据低8位 | 校验高8位 | 校验低8位 |
| 11H | 10H | 00H | 40H | 00H | 02H | 04H | 40H | 89H | 0AH | 9DH | XXH | XXH |
响应:对于预置单寄存器请求的正常响应是在寄存器值改变以后将接受到的数据传送回去。
| addr | Fun | Data start reg hi | Data start reg lo | D0 #of regs hi | D0 #of regs lo | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 寄存器起始地址高8位 | 寄存器起始地址低8位 | 寄存器数量高8位 | 寄存器数量低8位 | 校验高8位 | 校验低8位 |
| 11H | 10H | 00H | 40H | 00H | 02H | XXH | XXH |
返回一个从机地址控制器的类型,从机的当前状态,以及有关从机的其他说明,不支持广播。
查询:请求报告从机设备17的表示ID和状态。
| addr | Fun | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 校验高8位 | 校验低8位 |
| 11H | 11H | XXH | XXH |
响应:正常响应格式,数据内容对应每台控制器的类型。
| addr | Fun | byte Count | Slave ID | Run Indicator Status | Additfional Data | CRC16 hi | CRC16 lo |
| 地址 | 功能码 | 字节数 | 校验高8位 | 校验低8位 | |||
| 11H | 11H | XXH | XXH | XXH | XXH | XXH | XXH |
从机ID总结
数据区第一个字节为Modicon控制器返回的从机ID
| Slave ID | Controller |
| 0 | Micro 84 |
| 1 | 484 |
| 2 | 184/384 |
| 3 | 584 |
| 8 | 884 |
| 9 | 984 |
特注:详细信息见Modbus协议英文版或中文版。
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
在Rails自动生成的功能测试(test/functional/products_controller_test.rb)中,我看到以下代码:classProductsControllerTest我的问题是:方法调用products()在哪里/如何定义?products(:one)到底是什么意思?看代码,大概意思是“创建一个产品”,但是它是如何工作的呢?注意我是Ruby/Rails的新手,如果这些是微不足道的问题,我深表歉意。 最佳答案 如果您查看test/fixtures文件夹,您会看到一个products.yml文件。这是在您创建
我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有
在我的一些Controller中,我有一个before_filter检查用户是否登录?用于CRUD操作。application.rbdeflogged_in?unlesscurrent_userredirect_toroot_pathendendprivatedefcurrent_user_sessionreturn@current_user_sessionifdefined?(@current_user_session)@current_user_session=UserSession.findenddefcurrent_userreturn@current_userifdefine
我使用Ruby编程已经有一段时间了,现在只使用Ruby的标准MRI实现,但我一直对我经常听到的其他实现感到好奇。前几天我在读有关Rubinius的文章,这是一个用Ruby编写的Ruby解释器。我试着在不同的地方查找它,但我很难弄清楚这样的东西到底是如何工作的。我在编译器或语言编写方面从来没有太多经验,但我真的很想弄明白。一门语言究竟如何才能被自己解释?编译中是否有一个我不明白这有意义的基本步骤?有人可以像我是个白痴一样向我解释这个吗(因为无论如何这都不会太离谱) 最佳答案 它比你想象的要简单。Rubinius并非100%用Ruby编