{"id":1298,"date":"2014-01-22T18:22:25","date_gmt":"2014-01-22T18:22:25","guid":{"rendered":"https:\/\/ibex.tech\/resources\/?p=1298"},"modified":"2022-02-18T15:05:16","modified_gmt":"2022-02-18T15:05:16","slug":"modbus-comms-general","status":"publish","type":"post","link":"https:\/\/ibex.tech\/resources\/geek-area\/communications\/modbus\/modbus-comms-general","title":{"rendered":"Modbus Comms General"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">Resources<\/h4>\n\n\n\n<p><a href=\"http:\/\/www.modbus.org\/docs\/Modbus_Application_Protocol_V1_1b.pdf\" target=\"_blank\" rel=\"noopener\">modbus.org&nbsp;Modbus&nbsp;Application&nbsp;Protocol<\/a><\/p>\n\n\n\n<p>Describes function codes<\/p>\n\n\n\n<p><a href=\"http:\/\/www.modbus.org\/docs\/Modbus_over_serial_line_V1.pdf\" target=\"_blank\" rel=\"noopener\">modbus.org Modbus&nbsp;over Serial Line&nbsp;Specification and Implementation Guide<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Register Addressing<\/h4>\n\n\n\n<p>The Modbus register number should really be thought of as an offset rather than an address, as different vendors can use different register addressing schemes. &nbsp;Firstly registers may start from 0 for some devices and 1 for others. The register addressing always starts from 0 in the Modbus protocol, but for some devices such as PLC&#8217;s it may refer to address 1. &nbsp;Modbus also uses tables to hold different values and the modbus address sent is an offset within the particular table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Coil\/Register Numbers   Data Addresses   Type           Table Name\n1-9999                  0000 to 270E     Read-Write     Discrete Output Coils\n10001-19999             0000 to 270E     Read-Only      Discrete Input Contacts\n30001-39999             0000 to 270E     Read-Only      Analog Input Registers\n40001-49999             0000 to 270E     Read-Write     Analog Output Holding Registers<\/code><\/pre>\n\n\n\n<p>So, using command which accesses Analog Output Holding Register 40001 is&nbsp;accomplished&nbsp;by specifying register number 0 in the modbus register number field.<\/p>\n\n\n\n<p>A good way to specify register numbers to avoid potential for confusion:<br>&nbsp; Register 99, Address 40100<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Function Codes \/ Message Type<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>Message Type   Action           Table Name\n0x01           Read             Discrete Output Coils\n0x02           Read             Discrete Input Contacts\n0x03           Read             Analog Output Holding Registers\n0x04           Read             Analog Input Registers\n0x05           Write single     Discrete Output Coil\n0x06           Write single     Analog Output Holding Register\n0x10           Write multiple   Analog Output Holding Registers\n0x0F           Write multiple   Discrete Output Coils<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Data Types<\/h4>\n\n\n\n<p>A register is 16 bits and can store the following:<\/p>\n\n\n\n<p>A 16-bit unsigned integer<br>A 16-bit signed integer<br>A two character ASCII string<br>A discrete on\/off value<\/p>\n\n\n\n<p>To store larger values, for instance 32bit values, float values,&nbsp;ASCII strings, etc simply use successive&nbsp;registers.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Byte Ordering<\/h5>\n\n\n\n<p>The Modbus specification doesn&#8217;t define exactly how the data is stored in the registers. Some manufacturers use HighByte|LowByte and others use LowByte|HighByte.<\/p>\n\n\n\n<p>Similarly&nbsp;when registers are combined to represent 32-bit data types some devices store the high&nbsp;16 bits in the first register and the remaining low word in the second&nbsp;while others do the opposite.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">CRC (Cyclic Redundancy Check)<\/h4>\n\n\n\n<p>If a slave receives a packet with an invalid CRC no response should be sent.<\/p>\n\n\n\n<p>How to calculate the CRC:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const UINT16 CRCTable&#91;] = {\n   0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,\n   0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,\n   0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,\n   0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,\n   0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,\n   0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,\n   0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,\n   0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,\n   0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,\n   0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,\n   0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,\n   0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,\n   0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,\n   0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,\n   0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,\n   0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,\n   0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,\n   0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,\n   0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,\n   0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,\n   0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,\n   0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,\n   0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,\n   0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,\n   0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,\n   0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,\n   0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,\n   0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,\n   0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,\n   0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,\n   0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,\n   0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };\n\nUINT16 ModbusCalculateCrc (BYTE *pTxBuffer, WORD Length)\n{\n\tunsigned char ucTemp;\n\tUINT16 CrcWord = 0xFFFF;\n\n\twhile (Length--)\n\t{\n\t\tucTemp = (*pTxBuffer++) ^ (BYTE)(CrcWord &amp; 0x00ff);\n\t\tCrcWord >>= 8;\n\t\tCrcWord  ^= CRCTable&#91;ucTemp];\n\t}\n\treturn(CrcWord);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u00a0Modbus RTU Exception Error Response<\/h4>\n\n\n\n<p>The function Code byte value is returned with bit 7 set to indicate exception.<\/p>\n\n\n\n<p>Following this a exception code is sent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0x01  Illegal Function (The function code received in the query is not an allowable action for the slave)\n0x02  Illegal Data Address (The data address received in the query is not an allowable address for the slave)\n0x03  Illegal Data Value (A value contained in the query data field is not an allowable value for the slave)\n0x04  Slave Device Failure (An unrecoverable error occurred while the slave was attempting to perform the requested action)\n0x05  Acknowledge\n0x06  Slave Device Busy\n0x07  Negative Acknowledge (the slave cannot perform the program function received in the query)\n0x08  Memory Parity Error\n0x0A  Gateway Path Unavailable\n0x0B  Gateway Target Device Failed to Respond<\/code><\/pre>\n\n\n\n<p>For example for&nbsp;a failed&nbsp;read of a word (16 bits) from a register the following is sent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Byte 1 Modbus Device Address (1 to 247)\nByte 2 Function Code \/ Message Type (0x03)\nByte 3 Register Number (high byte)\nByte 4 Register Number (low byte)\nByte 5 Data Length (high byte, specified in Words)\nByte 6 Data Length (low byte)\nByte 7 CRC of bytes 1 to 6 (high byte)\nByte 8 CRC of bytes 1 to 6 (low byte)<\/code><\/pre>\n\n\n\n<p>And this is returned<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Byte 1 Modbus Device Address\nByte 2 Function Code \/ Message Type (0x83)\nByte 3 The Exception Code\nByte 4 CRC of bytes 1 to 5 (high byte)\nByte 5 CRC of bytes 1 to 5 (low byte)<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Resources modbus.org&nbsp;Modbus&nbsp;Application&nbsp;Protocol Describes function codes modbus.org Modbus&nbsp;over Serial Line&nbsp;Specification and Implementation Guide Register Addressing The Modbus register number should really be thought of as an offset rather than an address, as different vendors can use different register addressing schemes. &nbsp;Firstly registers may start from 0 for some devices and 1 for others. The register addressing [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[78],"tags":[],"class_list":["post-1298","post","type-post","status-publish","format-standard","hentry","category-modbus"],"_links":{"self":[{"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/posts\/1298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/comments?post=1298"}],"version-history":[{"count":21,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/posts\/1298\/revisions"}],"predecessor-version":[{"id":2452,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/posts\/1298\/revisions\/2452"}],"wp:attachment":[{"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/media?parent=1298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/categories?post=1298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibex.tech\/resources\/wp-json\/wp\/v2\/tags?post=1298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}