Пришло время рассмотреть еще одну вариацию протокола Modbus – Modbus ASCII. Эта версия протокола использует для передачи данных только символы ASCII, которыми кодирует шестнадцатеричное представление бинарных данных. Немного не понятно и запутано? Это ничего, welcome под кат и давайте рассмотрим, с чем же мы имеем дело.
Первое отличие протокола Modbus ASCII от Modbus RTU – у него есть разделитель между пакетами. Если в Modbus RTU все пакеты шли один за одним (практически, там должна быть небольшая задержка на линии между пакетами, порядка 2-5мс), то в Modbus ASCII каждый новый пакет должен начинаться со специального символа разделителя.
По стандарту Modbus RTU между пакетами нужна задержка в 3.5 символа (это время, которое нужно для передачи 3.5 символов по линии связи, зависит от скорости передачи). Эта задержка используется, что бы детектировать новый запрос от мастера. Т.е. эта задержка указывает начало нового запроса. Но когда стали использовать модемы, это перестало работать. На модеме невозможно выдержать нужное время. Поэтому решили использовать новый вариант протокола —
Так вот, таким символом начала пакета служит символ двоеточие с шестнадцатеричным кодом 0x3A. А конец каждого пакета помечается символами новой строки и перевода каретки – 0x0D 0x0A. Таким образом, из протокола полностью убирается зависимость от задержек между байтами. Т.е. если модем задержит байт, это не вызовет недопонимания на стороне клиента. И он будет ждать окончания пакета байтами 0x0D 0x0A. А если встретит символ разделителя 0х3А – сбросит буфер и начнем формировать пакет заново. Кроме того нет необходимости в экранировании спец символов модема, так как данные не используют символы из начальной секции ASCII таблицы.
В Modbus ASCII протоколе каждый байт данных представлен в виде 2 байтов. Каждый байт представляет собой ASCII символ в шестнадцатеричном представлении. Что бы легче было понять, приведем пример:
Modbus Протокол | Данные (ASCII) | Данные (HEX) | Данные (Двоичные) |
Modbus RTU | # | 23 | 0010 0011 |
Modbus ASCII | 2, 3 | 32, 33 | 0011 0010, 0011 0011 |
Например, нам нужно передать байт данных, который хранит символ #. Этот символ имеет в таблице ASCII шестнадцатеричный код 0x23. В протоколе Modbus RTU мы просто передаем байт со значением 0x23.
Если мы хоти передать тот же символ через протокол
Таким образом, диапазон значений для байта данных в протоколе Modbus RTU – 0 .. 0xFF
Диапазон значений для байта данных в протоколе Modbus ASCII – только символы, необходимые для отображения шестнадцатеричных цифр, т.е. 0 – 9, A, B, C, D, E, F (все заглавные).
В протоколе Modbus RTU используется 2 байтная контрольная сумма, которая помогает детектировать поврежденные запросы. В протоколе Modbus ASCII так же есть контрольная сумма – LRC (Longitudinal Redundancy Check).
Вычисление LRC намного проще, чем вычисление CRC. Что бы высчитать LRC вам нужно сделать следующие:
Таким образом, если затем сложить все байты пакета данных и байт LRC мы получим в результате 0. Это и есть самая быстрая проверка корректности пакета данных.
Ниже приведен пример вычисления LRC для конкретного запроса Modbus ASCII.
Для примера возьмем запрос на чтение регистров #40108 — #40110 с устройства с адресом 17
Запрос: 11 03 00 6B 00 03
Данные (Десятичные) | Данные (HEX) | Данные (Двоичные) |
17 | 11 | 0001 0001 |
3 | 03 | 0000 0011 |
0 | 00 | 0000 0000 |
107 | 6B | 0110 1011 |
0 | 00 | 0000 0000 |
3 | 03 | 0000 0011 |
Теперь посчитаем сумму всех байт
Данные (Десятичные) | Данные (HEX) | Данные (Двоичные) |
130 | 82 | 1000 0010 |
Следующий шаг – сделаем полученную сумму отрицательной
Данные (Десятичные) | Данные (HEX) | Данные (Двоичные) |
-130 | 7E | 0111 1110 |
Эта контрольная сумма добавляется к запросу в виде 2 ASCII символов – 7 и E.
Т.е. в конце запроса нужно добавить 2 байта со значением 37 и 45.
Что бы лучше понять, как все это работает, посмотрите пару простых примеров.
Возьмем наш запрос на чтение регистров #40108 — #40110 с устройства с адресом 17
Запрос: 11 03 00 6B 00 03
Это Modbus RTU запрос без последних двух байтов CRC. Теперь преобразуем этот запрос из Modbus RTU в Modbus ASCII. Для этого добавляем в начало запроса символ двоеточия, в конец запроса символ перевода строки и возврата каретки, а каждый байт представим в виде ASCII символов, соответствующих шестнадцатеричному представлению каждого байта запроса. В итоге у нас получиться такой запрос (в виде ASCII символов, или попросту в виде текстовой строки). Так же в конец запроса добавляем
: 1 1 0 3 0 0 6 B 0 0 0 3 7 E CR LF
Теперь просто нужно передать данный запрос в порт, используя коды ASCII символов. В бинарном виде запрос будет выглядеть так:
3A 3131 3033 3030 3642 3030 3033 3745 0D 0A
Индекс байта | Значение HEX | ASCII | Описание |
0 | 3A | : | Символ начала |
1-2 | 31 31 | 11 | Адрес устройства |
3-4 | 30 33 | 03 | Код команды |
5-8 | 30 30 36 42 | 00 6B | Адрес HOLDING регистра, с которого нужно начинать чтение. В данном случае 0х006B = 107. Но это не адрес, а смещение от адреса 40001. Т.е. реальный адрес = 107+ 40001 = 40108. |
9-12 | 30 30 30 33 | 00 03 | Количество регистров, которые нужно прочитать. 0х0003 = 3. Т.е. читать нужно регистры 40108– 40110. |
13 – 14 | 37 45 | 7E | LRC запроса |
15 | CR | 0D | Символ перевода каретки |
16 | LF | 0A | Символ новой строки |
www.siv-blog.com
Modbus ASCII – это спецификация сетевого протокола обмена данных, разработанная компанией Modicon в 1979 году, для обеспечения сетевой связи между интеллектуальными устройствами. Так же как и все другие спецификации Modbus ASCII является одномастерным протоколом, функционирующим по принципу «ведущий-ведомый».
Modbus ASCII использует шинную топологию, с использованием сетевых интерфейсов RS-232 или RS-485. Возможно использование преобразователей RS-485/Ethernet, так как Modbus ASCII и TCP используют одинаково реализованые уровни сетевой модели OSI.
Основным отличием Modbus ASCII от RTU является использование специальной таблицы значений. Каждому символу отвечают 2 байта данных, соответственно их используется в 2 раза больше, однако расшифровка и сетевое управление осуществляется намного проще. Задержка между кадрами допустима в пределах 1 секунды.
Сеть, построенная на использовании этой версии протокола, может включать в себя до 31 узла.
Структура сообщения имеет следующий вид: каждый байт передается в шестнадцатеричном представлении. В таком случае байты данных, код функции и байт поля проверки передаются в виде 0-9, A-F.
Для разграничения отдельных кадров используется символ «:» и специализированная последовательность «CR LF». Формат кадра представляет собой следующую последовательность: 1 стартовый, 7 битов данных 1 бит паритета + 1 стоповый или без паритета + 2 стоповых.
Специальные приемники на шине отслеживают символ «:», который указывает на начало кадра. По принятию символа, отлавливаются поля адресации. Таким образом, легко реализовывается синхронизация устройств.
Так как, в Modbus ASCII используется стартовая и столбовая последовательность в разграничении, спецификация не чувствительна к значительным паузам между символами.
Tags Modbus
autoworks.com.ua
В предыдущих статьях описывался формат запросов и ответов для Modbus RTU и Modbus ASCII протоколов. В этих протоколах для подтверждения целостности данных используются контрольные суммы, которые вычисляются по специальным алгоритмам. В тех статьях я не описывал их, так что сейчас я приведу пример функций который это делают. Я собираюсь написать их на двух языках —
Читать далее →
Опубликовано в .NET/C#, C/C++, Modbus и отмечено C/C++, C#, CRC16, LRC, Modbus, Modbus ASCII, Modbus RTU в slepchenkov. 3 комментарияКак и в любой системе при общении по протоколу Modbus могут возникать ошибки и непредвиденные ситуации. Для обработки таких случаев в протоколе предусмотрены специальные ответы, которые помогают мастеру, отправившему запрос, узнать какого именно рода ошибка или исключительная ситуация произошла.
Читать далее →
Пришло время рассмотреть еще одну вариацию протокола Modbus – Modbus ASCII. Эта версия протокола использует для передачи данных только символы ASCII, которыми кодирует шестнадцатеричное представление бинарных данных. Немного не понятно и запутано? Это ничего, welcome под кат и давайте рассмотрим, с чем же мы имеем дело.
Читать далее →
Опубликовано в Modbus и отмечено Modbus ASCII, Modbus Protocol, Modbus RTU в slepchenkov. КомментироватьВ этой статье я попытаюсь рассказать как устроен протокол Modbus, какие данные он может хранить, в каком виде они могут храниться, как они могут быть считаны. Эта статья даст представление о том, что же такое Modbus протокол и как он может применяться.
Читать далее →
Опубликовано в Modbus и отмечено Modbus ASCII, Modbus Protocol, Modbus RTU, Modbus TCP, RTU в slepchenkov. 5 комментариевwww.siv-blog.com
[0000…002F] | Изменяется часто, 1 секунда, например | чтение | Текущая температура |
[0030…005F] | В общем случае – изменяется раз в секунду. | чтение | Текущая уставка |
[0060…008F] | изменяется раз в секунду. | чтение | Текущая мощность |
[0090…00CF] | чтение | Температура найденная в архиве | |
[00D0…00FF] | чтение | Уставка найденная в архиве | |
[0100…012F] | чтение | Мощность найденная в архиве | |
0130 | чтение/запись | Количество каналов | |
0131 | чтение | Модель прибора | |
0132 | чтение | Модель прибора | |
0133 | чтение | Версия ПО | |
[0134…013F] | РЕЗЕРВ | ||
Текущие ДАТА/ВРЕМЯ | |||
0140 | чтение/запись | Год | |
0141 | чтение/запись | Месяц | |
0142 | чтение/запись | Число | |
0143 | чтение/запись | Часы | |
0144 | чтение/запись | Минуты | |
0145 | чтение/запись | Секунды | |
Адреса для работы с Архивом | |||
0146 | Год | ||
0147 | Месяц | ||
0148 | Число | ||
0149 | Часы | ||
014A | Минуты | ||
014B | Секунды | ||
014C | Интервал времени для поиска в АРХИВЕ | ||
014D | Запись значений по этому адресу приводит к установке времени в [0146…014B] : 0-Время начала архива. 1-Время конца арива. |
||
014E | |||
014F | |||
0150 | |||
[0151…015F] | РЕЗЕРВ | ||
Регистры для редактирования ПРОГРАММ | |||
0160 | Номер программы | ||
0161 | Номер шага | ||
0162 | Тип шага | ||
0163 | Параметр 1 | ||
0164 | Параметр 2 | ||
0165 | Условие перехода на следующий шаг | ||
0166 | Дополнительные параметры : 0 – общие 1 – частные |
||
0167 | Частный пропорциональный коэффициент ПИД | ||
0168 | Частный интегральный коэффициент ПИД | ||
0169 | Частный дифференциальный коэффициент ПИД | ||
016A | Частное ограничение выводимой мощности | ||
[016B…016F] | РЕЗЕРВ | ||
Область адресов для работы с параметрами, зависящими от номера канала | |||
0170 | Изменяется часто, 1 секунда, например | чтение | Текущее значение температуры |
0171 | В общем случае – изменяется раз в секунду. | чтение | Текущая Уставка регулирования |
0172 | изменяется раз в секунду. | чтение | Текущая выводимая мощность |
0173 | чтение/запись | Заданная Уставка | |
0174 | чтение/запись | Заданная Уставка 2 | |
0175 | чтение/запись | Диапазон изменения уставки | |
0176 | чтение/запись | Минимальная уставка | |
0177 | Максимальная уставка | ||
0178 | чтение | Текущее значение времени (для программных приборов) | |
[0179…017F] | РЕЗЕРВ | ||
0180 | чтение/запись | Включение выключение регулирования | |
0181 | РЕЗЕРВ | ||
0182 | чтение/запись | Пропорциональный коэффициент | |
0183 | чтение/запись | Время интегрирования | |
0184 | чтение/запись | Время дифференцирования | |
0185 | чтение/запись | Закон регулирования нагревателя | |
0186 | чтение/запись | Метод вывода мощности на нагреватель | |
0187 | чтение/запись | Максимальная мощность нагревателя | |
0188 | чтение/запись | Минимальная мощность нагревателя | |
0189 | чтение/запись | Номер выхода нагревателя | |
018A | чтение/запись | Период ШИМ нагревателя | |
018B | чтение/запись | Закон регулирования охладителя | |
018C | чтение/запись | Соотношение мощностей охладитель/нагреватель | |
018D | чтение/запись | Выход охладителя | |
018E | чтение/запись | Период ШИМ охладителя | |
018F | чтение/запись | Гистерезис нагревателя | |
0190 | чтение/запись | Гистерезис охладителя | |
[0191…0199] | РЕЗЕРВ | ||
019A | чтение/запись | Тип АВАРИИ А | |
019B | чтение/запись | Уставка АВАРИИ А | |
019C | чтение/запись | Гистерезис АВАРИИ А | |
019D | чтение/запись | Выход АВАРИИ А | |
019E | чтение/запись | Блокировка АВАРИИ А | |
019F | чтение/запись | Глубина фильтра | |
01A0 | чтение/запись | Тип АВАРИИ B | |
01A1 | чтение/запись | Уставка АВАРИИ B | |
01A2 | чтение/запись | Гистерезис АВАРИИ B | |
01A3 | чтение/запись | Выход АВАРИИ B | |
01A4 | чтение/запись | Блокировка АВАРИИ B | |
01A5 | чтение/запись | Глубина фильтра | |
[01A6…01AF] | РЕЗЕРВ | ||
01B0 | чтение/запись | Тип датчика | |
01B1 | чтение/запись | Номер датчика в выбранном типе | |
01B3 | чтение/запись | Компенсация холодного спая (ON/OFF) | |
01B4 | чтение/запись | Температура компенсации холодного спая | |
01B5 | чтение/запись | R0 | |
01B6 | чтение/запись | Разрешение | |
01B7 | чтение/запись | Выход обрыва датчика | |
01B8 | чтение/запись | Мощность выводимая при обрыве датчика | |
[01B9…01BF] | РЕЗЕРВ | ||
01С0 | чтение/запись | Точка-1 ток | |
01С1 | чтение/запись | Температура-1 | |
01C2 | чтение/запись | Точка-2 ток | |
01С3 | чтение/запись | Температура-2 | |
01С4 | чтение/запись | Позиция точки ток | |
01С5 | чтение/запись | Уровень обрыва | |
01С6 | чтение/запись | Точка-1 напряжение | |
01С7 | чтение/запись | Температура-1 | |
01С8 | чтение/запись | Точка-2 напряжение | |
01С9 | чтение/запись | Температура-2 | |
01СA | чтение/запись | Позиция точки напряжение | |
[01CB…01CF] | РЕЗЕРВ | ||
01D0 | чтение/запись | Время плавного разогрева | |
01D1 | чтение/запись | Контроль обрыва контура (ON/OFF) | |
01D2 | чтение/запись | Время обрыва контура | |
01D3 | чтение/запись | Выход обрыва контура | |
01D4 | чтение/запись | Ручное регулирование(HAND/AUTO) | |
01D5 | чтение/запись | Мощность в ручном режиме(PID) | |
01D6 | чтение/запись | Мощность в ручном режиме(ON/OFF) | |
Область адресов для работы с параметрами, не зависящими от номера канала | |||
0200 | чтение/запись | Режим работы таймера | |
0201 | чтение/запись | Уставка таймера | |
0203 | чтение/запись | Режим работы (часы/минуты-минуты/секунды) | |
0204 | чтение/запись | Сетевой адрес прибора | |
0205 | чтение/запись | Период записи в архив |
media.ls.urfu.ru
Modbus —коммуникационный протокол, основан на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP (протокол Modbus TCP).
Сообщение Modbus RTU состоит из адреса устройства SlaveID, кода функции, специальных данных в зависимости от кода функции и CRC контрольной суммы.
SlaveID | Код функции | Специальные данные | CRC |
Если отбросить SlaveID адрес и CRC контрольную сумму, то получится PDU, Protocol Data Unit.
SlaveID – это адрес устройства, может принимать значение от 0 до 247, адреса с 248 до 255 зарезервированы.
Данные в модуле хранятся в 4 таблицах.
Две таблицы доступны только для чтения и две для чтения-записи.
В каждой таблице помещается 9999 значений.
Номер регистра | Адрес регистра HEX | Тип | Название | Тип |
---|---|---|---|---|
1-9999 | 0000 до 270E | Чтение-запись | Discrete Output Coils | DO |
10001-19999 | 0000 до 270E | Чтение | Discrete Input Contacts | DI |
30001-39999 | 0000 до 270E | Чтение | Analog Input Registers | AI |
40001-49999 | 0000 до 270E | Чтение-запись | Analog Output Holding Registers | AO |
В сообщении Modbus используется адрес регистра.
Например, первый регистр AO Holding Register, имеет номер 40001, но его адрес равен 0000.
Разница между этими двумя величинами есть смещение offset.
Каждая таблица имеет свое смещение, соответственно: 1, 10001, 30001 и 40001.Ниже приведен пример запроса Modbus RTU для получения значения AI аналогового выхода (holding registers) из регистров от #40108 до 40110 с адресом устройства 17.
11 03 006B 0003 7687
11 | Адрес устройства SlaveID (17 = 11 hex) |
03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
7687 | Контрольная сумма CRC |
В ответе от Modbus RTU Slave устройства мы получим:
11 03 06 AE41 5652 4340 49AD
Где:
11 | Адрес устройства (17 = 11 hex) | SlaveID |
03 | Функциональный код | Function Code |
06 | Количество байт далее (6 байтов идут следом) | Byte Count |
AE | Значение старшего разряда регистра (AE hex) | Register value Hi (AO0) |
41 | Значение младшего разряда регистра (41 hex) | Register value Lo (AO0) |
56 | Значение старшего разряда регистра (56 hex) | Register value Hi (AO1) |
52 | Значение младшего разряда регистра (52 hex) | Register value Lo (AO1) |
43 | Значение старшего разряда регистра (43 hex) | Register value Hi (AO2) |
40 | Значение младшего разряда регистра (40 hex) | Register value Lo (AO2) |
49 | Контрольная сумма | CRC value Hi |
AD | Контрольная сумма | CRC value Lo |
Регистр аналогового выхода AO0 имеет значение AE 41 HEX или 44609 в десятичной системе.
Регистр аналогового выхода AO1 имеет значение 56 52 HEX или 22098 в десятичной системе.
Регистр аналогового выхода AO2 имеет значение 43 40 HEX или 17216 в десятичной системе.
Значение AE 41 HEX — это 16 бит 1010 1110 0100 0001, может принимать различное значение, в зависимости от типа представления.
Значение регистра 40108 при комбинации с регистром 40109 дает 32 бит значение.
Пример представления.
Тип представления | Диапазон значений | Пример в HEX | Будет в десятичной форме |
---|---|---|---|
16-bit unsigned integer | 0 до 65535 | AE41 | 44,609 |
16-bit signed integer | -32768 до 32767 | AE41 | -20,927 |
two character ASCII string | 2 знака | AE41 | ® A |
discrete on/off value | 0 и 1 | 0001 | 0001 |
32-bit unsigned integer | 0 до 4,294,967,295 | AE41 5652 | 2,923,517,522 |
32-bit signed integer | -2,147,483,648 до 2,147,483,647 | AE41 5652 | -1,371,449,774 |
32-bit single precision IEEE floating point number | 1,2·10−38 до 3,4×10+38 | AE41 5652 | -4.395978 E-11 |
four character ASCII string | 4 знака | AE41 5652 | ® A V R |
Приведем таблицу с кодами функций чтения и записи регистров Modbus RTU.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
01 (0x01) | Чтение DO | Read Coil Status | Дискретное | Чтение |
02 (0x02) | Чтение DI | Read Input Status | Дискретное | Чтение |
03 (0x03) | Чтение AO | Read Holding Registers | 16 битное | Чтение |
04 (0x04) | Чтение AI | Read Input Registers | 16 битное | Чтение |
05 (0x05) | Запись одного DO | Force Single Coil | Дискретное | Запись |
06 (0x06) | Запись одного AO | Preset Single Register | 16 битное | Запись |
15 (0x0F) | Запись нескольких DO | Force Multiple Coils | Дискретное | Запись |
16 (0x10) | Запись нескольких AO | Preset Multiple Registers | 16 битное | Запись |
Эта команда используется для чтения значений дискретных выходов DO.
В запросе PDU задается начальный адрес первого регистра DO и последующее количество необходимых значений DO. В PDU значения DO адресуются, начиная с нуля.
Значения DO в ответе находятся в одном байте и соответствуют значению битов.
Значения битов определяются как 1 = ON и 0 = OFF.
Младший бит первого байта данных содержит значение DO адрес которого указывался в запросе. Остальные значения DO следуют по нарастающей к старшему значению байта. Т.е. справа на лево.
Если запрашивалось меньше восьми значений DO, то оставшиеся биты в ответе будут заполнены нулями (в направлении от младшего к старшему байту). Поле Byte Count Количество байт далее указывает количество полных байтов данных в ответе.
Пример запроса DO с 20 по 56 для SlaveID адреса устройства 17. Адрес первого регистра будет 0013 hex = 19, т.к. счет ведется с 0 адреса (0014 hex = 20, -1 смещение нуля = получаем 0013 hex = 19).
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
01 | Функциональный код | 01 | Функциональный код |
00 | Адрес первого регистра Hi байт | 05 | Количество байт далее |
13 | Адрес первого регистра Lo байт | CD | Значение регистра DO 27-20 (1100 1101) |
00 | Количество регистров Hi байт | 6B | Значение регистра DO 35-28 (0110 1011) |
25 | Количество регистров Lo байт | B2 | Значение регистра DO 43-36 (1011 0010) |
0E | Контрольная сумма CRC | 0E | Значение регистра DO 51-44 (0000 1110) |
84 | Контрольная сумма CRC | 1B | Значение регистра DO 56-52 (0001 1011) |
45 | Контрольная сумма CRC | ||
E6 | Контрольная сумма CRC |
Состояния выходов DO 27-20 показаны как значения байта CD hex, или в двоичной системе 1100 1101.
В регистре DO 56-52 5 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (0001 1011).
Каналы | — | — | — | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
---|---|---|---|---|---|---|---|---|
Биты | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
Hex | 1B |
Эта команда используется для чтения значений дискретных входов DI.
Пример запроса DI с регистров от #10197 до 10218 для SlaveID адреса устройства 17. Адрес первого регистра будет 00C4 hex = 196, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
02 | Функциональный код | 02 | Функциональный код |
00 | Адрес первого регистра Hi байт | 03 | Количество байт далее |
C4 | Адрес первого регистра Lo байт | AC | Значение регистра DI 10204-10197 (1010 1100) |
00 | Количество регистров Hi байт | DB | Значение регистра DI 10212-10205 (1101 1011) |
16 | Количество регистров Lo байт | 35 | Значение регистра DI 10218-10213 (0011 0101) |
BA | Контрольная сумма CRC | 20 | Контрольная сумма CRC |
A9 | Контрольная сумма CRC | 18 | Контрольная сумма CRC |
Эта команда используется для чтения значений аналоговых выходов AO.
Пример запроса AO с регистров от #40108 до 40110 для SlaveID адреса устройства 17. Адрес первого регистра будет 006B hex = 107, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
03 | Функциональный код | 03 | Функциональный код |
00 | Адрес первого регистра Hi байт | 06 | Количество байт далее |
6B | Адрес первого регистра Lo байт | AE | Значение регистра Hi #40108 |
00 | Количество регистров Hi байт | 41 | Значение регистра Lo #40108 |
03 | Количество регистров Lo байт | 56 | Значение регистра Hi #40109 |
76 | Контрольная сумма CRC | 52 | Значение регистра Lo #40109 |
87 | Контрольная сумма CRC | 43 | Значение регистра Hi #40110 |
40 | Значение регистра Lo #40110 | ||
49 | Контрольная сумма CRC | ||
AD | Контрольная сумма CRC |
Эта команда используется для чтения значений аналоговых входов AI.
Пример запроса AI с регистра #30009 для SlaveID адреса устройства 17. Адрес первого регистра будет 0008 hex = 8, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
04 | Функциональный код | 04 | Функциональный код |
00 | Адрес первого регистра Hi байт | 02 | Количество байт далее |
08 | Адрес первого регистра Lo байт | 00 | Значение регистра Hi #30009 |
00 | Количество регистров Hi байт | 0A | Значение регистра Lo #30009 |
01 | Количество регистров Lo байт | F8 | Контрольная сумма CRC |
B2 | Контрольная сумма CRC | F4 | Контрольная сумма CRC |
98 | Контрольная сумма CRC |
Эта команда используется для записи одного значения дискретного выхода DO.
Значение FF 00 hex устанавливает выход в значение включен ON.
Значение 00 00 hex устанавливает выход в значение выключен OFF.
Все остальные значения недопустимы и не будут влиять значение на выходе.
Нормальный ответ на такой запрос — это эхо (повтор запроса в ответе), возвращается после того, как состояние DO было изменено.
Пример записи в DO с регистром #173 для SlaveID адреса устройства 17. Адрес регистра будет 00AC hex = 172, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
05 | Функциональный код | 05 | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
AC | Адрес первого регистра Lo байт | AC | Адрес первого регистра Lo байт |
FF | Значение Hi байт | FF | Значение Hi байт |
00 | Значение Lo байт | 00 | Значение Lo байт |
4E | Контрольная сумма CRC | 4E | Контрольная сумма CRC |
8B | Контрольная сумма CRC | 8B | Контрольная сумма CRC |
Эта команда используется для записи одного значения аналогового выхода AO.
Пример записи в AO с регистром #40002 для SlaveID адреса устройства 17. Адрес первого регистра будет 0001 hex = 1, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
06 | Функциональный код | 06 | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
01 | Адрес первого регистра Lo байт | 01 | Адрес первого регистра Lo байт |
00 | Значение Hi байт | 00 | Значение Hi байт |
03 | Значение Lo байт | 03 | Значение Lo байт |
9A | Контрольная сумма CRC | 9A | Контрольная сумма CRC |
9B | Контрольная сумма CRC | 9B | Контрольная сумма CRC |
Эта команда используется для записи нескольких значений дискретного выхода DO.
Пример записи в несколько DO с регистрами от #20 до #29 для SlaveID адреса устройства 17. Адрес регистра будет 0013 hex = 19, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
0F | Функциональный код | 0F | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
13 | Адрес первого регистра Lo байт | 13 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
0A | Количество регистров Lo байт | 0A | Кол-во записанных рег. Lo байт |
02 | Количество байт далее | 26 | Контрольная сумма CRC |
CD | Значение байт DO 27-20 (1100 1101) | 99 | Контрольная сумма CRC |
01 | Значение байт DO 29-28 (0000 0001) | ||
BF | Контрольная сумма CRC | ||
0B | Контрольная сумма CRC |
Эта команда используется для записи нескольких значений аналогового выхода AO.
Пример записи в несколько AO с регистрами #40002 и #40003 для SlaveID адреса устройства 17. Адрес первого регистра будет 0001 hex = 1, т.к. счет ведется с 0 адреса.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
11 | Адрес устройства | 11 | Адрес устройства |
10 | Функциональный код | 10 | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
01 | Адрес первого регистра Lo байт | 01 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
02 | Количество регистров Lo байт | 02 | Кол-во записанных рег. Lo байт |
04 | Количество байт далее | 12 | Контрольная сумма CRC |
00 | Значение Hi 40002 | 98 | Контрольная сумма CRC |
0A | Значение Lo 40002 | ||
01 | Значение Hi 40003 | ||
02 | Значение Lo 40003 | ||
C6 | Контрольная сумма CRC | ||
F0 | Контрольная сумма CRC |
Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки.
Ответ будет содержать измененный Функциональный код, старший бит будет равен 1.
Пример:
Было | Стало |
---|---|
Функциональный код в запросе | Функциональный код ошибки в ответе |
01 (01 hex) 0000 0001 | 129 (81 hex) 1000 0001 |
02 (02 hex) 0000 0010 | 130 (82 hex) 1000 0010 |
03 (03 hex) 0000 0011 | 131 (83 hex) 1000 0011 |
04 (04 hex) 0000 0100 | 132 (84 hex) 1000 0100 |
05 (05 hex) 0000 0101 | 133 (85 hex) 1000 0101 |
06 (06 hex) 0000 0110 | 134 (86 hex) 1000 0110 |
15 (0F hex) 0000 1111 | 143 (8F hex) 1000 1111 |
16 (10 hex) 0001 0000 | 144 (90 hex) 1001 0000 |
Пример запроса и ответ с ошибкой:
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
0A | Адрес устройства | 0A | Адрес устройства |
01 | Функциональный код | 81 | Функциональный код с измененным битом |
04 | Адрес первого регистра Hi байт | 02 | Код ошибки |
A1 | Адрес первого регистра Lo байт | B0 | Контрольная сумма CRC |
00 | Количество регистров Hi байт | 53 | Контрольная сумма CRC |
01 | Количество регистров Lo байт | ||
AC | Контрольная сумма CRC | ||
63 | Контрольная сумма CRC |
Расшифровка кодов ошибок
01 | Принятый код функции не может быть обработан. |
02 | Адрес данных, указанный в запросе, недоступен. |
03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для неуспешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
golf2109.blogspot.com
Modbus — коммуникационный протокол, основанный на клиент-серверной архитектуре. Разработан фирмой Modicon для использования в контроллерах с программируемой логикой (PLC). Стал стандартом де-факто в промышленности и широко применяется для организации связи промышленного электронного оборудования. Использует для передачи данных последовательные линии связи RS-485, RS-422, RS-232, а также сети TCP/IP. В настоящее время поддерживается некоммерческой организацией Modbus-IDA.
Протокол Modbus описывает единый простой формат передачи данных PDU, который в свою очередь входит в полный пакет ADU. Формат ADU меняется в зависимости от типа линии связи. Существуют три режима протокола: Modbus RTU, Modbus ASCII, Modbus TCP. Первые два используют последовательные линии связи (в основном RS-485, реже RS-422/RS-232), последний использует для передачи данных по сетям TCP/IP.
Протокол Modbus RTU предполагает одно активное (запрашивающее) устройство в линии (master), которое может передавать команды одному или нескольким пассивным устройствам (slave), обращаясь к ним по уникальному в линии адресу. Синтаксис команд протокола позволяет адресовать 247 устройств на одной линии связи стандарта RS-485 (реже RS-422 или RS-232).
Инициатива проведения обмена всегда исходит от ведущего устройства. Ведомые устройства прослушивают линию связи. Мастер подаёт запрос (посылка, последовательность байт) в линию и переходит в состояние прослушивания линии связи. Ведомое устройство отвечает на запрос, пришедший в его адрес. Окончание ответной посылки мастер определяет, определяя временные интервалы между окончанием приёма предыдущего байта и началом приёма следующего. Если этот интервал превысил время, необходимое для приёма двух байт на заданной скорости передачи, приём кадра ответа считается завершённым. Кадры запроса и ответа по протоколу modbus имеют фиксированный формат, приведённый в (Таблица 1-1).
адрес подчиненного устройства | номер функции | данные | CRC |
---|---|---|---|
1 байт | 1 байт | N < 253 (байт) | 2 байта |
где:
Следует отметить, что поле CRC записывается младшим байтом вперёд. Алгоритм расчёта CRC может отличаться для разных устройств.
Все операции с данными привязаны к нулю, каждый вид данных (регистр, выходное/входное значение) начинаются с адреса 0000. Адресация к ячейке начинается с 1.
Например: Флаг номер 1 программируемого контроллера имеет адрес 0000 (указывается в поле «Адрес»).
Флаг номер 127 (DEC) имеет адрес 0x007E hex (126 dec) (указывается в поле «Адрес»).
Запоминающий регистр 40001 будет иметь адрес 0000 в поле «Адрес» команды. Потому что код операции уже содержит в себе необходимую информацию об адресе. Операции с этими регистрами имеют смещение Адрес_регистра — 40000 = Значение Используемое В Поле «Адрес». Тип адресации команд в дальнейшем будем помечать т.о.
смещение | обозначение |
-40000 | 4x |
-10000 | 1x |
Запоминающий регистр 40108 будет иметь адрес 006B hex (107 dec)
Во время обмена данными могут возникать ошибки двух типов:
Ошибки первого типа обнаруживаются при помощи фреймов символов, контроля чётности и циклической контрольной суммы CRC-16-IBM (используется число-полином = 0xA001).
В RTU режиме сообщение начинается с интервала тишины равного времени передачи 3.5 символов при данной скорости передачи в сети. Первым полем затем передается адрес устройства.
Вслед за последним передаваемым символом также следует интервал тишины продолжительностью не менее 3.5 символов. Новое сообщение может начинаться после этого интервала.
Фрейм сообщения передается непрерывно. Если интервал тишины продолжительностью 1.5 возник во время передачи фрейма, принимающее устройство заканчивает прием сообщения и следующий байт будет воспринят как начало следующего сообщения.
Таким образом, если новое сообщение начнется раньше 3.5 интервала, принимающее устройство воспримет его как продолжение предыдущего сообщения. В этом случае устанавливается ошибка, так как будет несовпадение контрольных сумм.
Для сообщений об ошибках второго типа протокол Modbus RTU предусматривает, что устройства могут отсылать ответы, свидетельствующие об ошибочной ситуации. Признаком того, что ответ содержит сообщение об ошибке, является установленный старший бит кода команды. Пример кадра при выявлении ошибки ведомым устройством, в ответ на запрос приведён в (Таблица 2-1).
1. Если Slave принимает корректный запрос и может его нормально обработать, то возвращает нормальный ответ.
2. Если Slave не принимает какого либо значения, никакого ответа не отправляется. Master диагностирует ошибку по таймауту.
3. Если Slave принимает запрос, но обнаруживает ошибку (parity, LRC, or CRC), никакого ответа не отправляется. Master диагностирует ошибку по таймауту.
4. Если Slave принимает запрос, но не может его обработать (обращение к несуществующему регистру и т.д.), отправляется ответ содержащий в себе данные об ошибке.
Направление передачи | адрес подчинённого устройства | номер функции | данные (или код ошибки) | CRC |
---|---|---|---|---|
Запрос (Master→Slave) | 0x01 | 0x77 | 0xDD | 0xC7 0xA9 |
Ответ (Slave→Master) | 0x01 | 0xF7 | 0xEE | 0xE6 0x7C |
01 Принятый код функции не может быть обработан на подчиненном. 02 Адрес данных указанный в запросе не доступен данному подчиненному. 03 Величина содержащаяся в поле данных запроса является не допустимой величиной для подчиненного. 04 Невосстанавливаемая ошибка имела место пока подчиненный пытался выполнить затребованное действие. 05 Подчиненный принял запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет главного от генерации ошибки таймаута. 06 Подчиненный занят обработкой команды. Главный должен повторить сообщение позже, когда подчиненный освободится. 07 Подчиненный не может выполнить программную функцию, принятую в запросе. Этот код возвращается для неудачного программного запроса, использующего функции с номерами 13 или 14. Главный должен запросить диагностическую информацию или информацию об ошибках с подчиненного. 08 Подчиненный пытается читать расширенную память, но обнаружил ошибку паритета. Главный может повторить запрос, но обычно в таких случаях требуется ремонт.
В протокол Modbus можно выделить несколько подмножеств команд ( Таблица 3-1).
Подмножество команд | Диапазон кодов команд |
---|---|
Стандартные команды | 1-21 |
Резерв для расширенных функций | 22-64 |
Пользовательские | 65-119 |
Резерв для внутренних нужд | 120-255 |
Тип адресации 4x
Значения регистров передаются в линию начиная с указанного адреса, следующие значения регистров передаются после него (см. поле «Данные»). Ниже приведены примеры команда ведущего устройства (таблица 3-2) и ответ ведомого (таблица 3-3):
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Кол. регистров ст. байт | 05 Кол. регистров мл. байт | 06 Кол. байт | 07 Данные ст. байт | 08 Данные мл. байт | 09 CRC мл. байт | 10 CRC ст. байт |
---|---|---|---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x10 | 0x00 | 0x01 | 0x00 | 0x01 | 0x02 | 0xFF | 0xFF | 0xA6 | 0x31 |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Кол. регистров ст. байт | 05 Кол. регистров мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x10 | 0x00 | 0x01 | 0x00 | 0x01 | 0x1C | 0x90 |
Тип адресации 4x
Ниже приведены примеры команда ведущего устройства (таблица 3-4) и ответ ведомого (таблица 3-5):
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Кол. регистров ст. байт | 05 Кол. регистров мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x03 | 0x00 | 0x01 | 0x00 | 0x01 | 0xD5 | 0xCA |
Значения регистров передаются в линию начиная с указанного адреса, следующие значения регистров передаются после него (см. поле «Данные»).
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Кол. Байт | 03 Данные ст. байт | 04 Данные мл. байт | 05 CRC мл. байт | 06 CRC ст. байт |
---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x03 | 0x02 | 0xFF | 0xFF | 0xB9 | 0xF4 |
Тип адресации 4x
Ниже приведены примеры команда ведущего устройства (таблица 3-2) и ответ ведомого (таблица 3-3):
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Данные ст. байт | 05 Данные мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x06 | 0x00 | 0x01 | 0xFF | 0xFF | 0xD9 | 0xBA |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Данные ст. байт | 05 Данные мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x06 | 0x00 | 0x01 | 0xFF | 0xFF | 0xD9 | 0xBA |
Тип адресации 0x
Запрос:
Состоит из адреса флага и количества считываемых флагов. Адресация флагов начинается с 0, количество флагов с 1.
Ответ:
Значение флагов передается в одном бите в поле «Данные». Трактовка флагов: 1 = ON; 0 = OFF. 0-й бит первого байта данных содержит значение флага указанного в поле «Адрес». Если запросить состояние одного флага, то в младшем бите будет возвращено значение флага, а все остальные старшие биты заполнены нулями.
Ниже приведены примеры запроса ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7). В примере запрашивается состояние 9 флагов с адреса 1. В ответе содержится 2 байта данных, для большей ясности будем считать что все запрашиваемые флаги находятся в состоянии ON, а все остальные в состоянии OFF.
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Кол. флагов ст. байт | 05 Кол. флагов мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x01 | 0x00 | 0x01 | 0x00 | 0x09 | 0x | 0x |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Количество байт | 03 Данные (флаги 0-7) | 04 Данные (флаги 8-15) | 05 CRC мл. байт | 06 CRC ст. байт |
---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x01 | 0x02 | 0xFF | 0x01 | 0x | 0x |
Тип адресации 0x
Команда:
Состоит из адреса флага, количества изменяемых флагов, количества передаваемых байт устанавливаемых значений. Адресация флагов начинается с 0, количество флагов с 1. Устанавливаемые значения передаются начиная с байта, в котором находится младшим битом значение, устанавливаемое по адресу указываемому в поле «00 адрес подчиненного устройства».
Ответ:
Состоит из начального адреса флага и количества записанных флагов. Адресация флагов начинается с 0, количество флагов с 1.
Ниже приведены примеры команды ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7).
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Количество флагов ст. байт | 05 Количество флагов мл. байт | 06 Количество байт данных | 07 Данные (значения для флагов биты 0-7) | 08 Данные (значения для флагов биты 8-15) | 09 CRC мл. байт | 0A CRC ст. байт |
---|---|---|---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x0F | 0x00 | 0x13 | 0x00 | 0x0A | 0x02 | 0xCD | 0x01 | 0x72 | 0xCB |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Количество флагов ст. байт | 05 Количество флагов мл. байт | 05 CRC мл. байт | 06 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x0F | 0x00 | 0x13 | 0x00 | 0x0A | 0x24 | 0x09 |
Команда:
Состоит из адреса флага и устанавливаемого значения. Поле «Значение флага мл. байт» всегда равно нулю (0x00), поле «Значение флага ст. байт» принимает значения 0xFF если флаг устанавливается в «1»(ON) или 0x00 если флаг устанавливается в «0»(OFF), другие значения недопустимы и не влияют на значение флага. Адресация флагов начинается с 0.
Ответ:
Состоит из начального адреса флага и количества записанных флагов. Адресация флагов начинается с 0, количество флагов с 1.
Ниже приведены примеры команды ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7).
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Значение флага ст. байт | 05 Значение флага мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x05 | 0x00 | 0x13 | 0xFF | 0x00 | 0x7D | 0xFF |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Адрес ст. байт | 03 Адрес мл. байт | 04 Значение флага ст. байт | 05 Значение флага мл. байт | 06 CRC мл. байт | 07 CRC ст. байт |
---|---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x05 | 0x00 | 0x13 | 0xFF | 0x00 | 0x7D | 0xFF |
Ниже приведены примеры команда ведущего устройства (таблица 5-4) и ответ ведомого (таблица 5-5):
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Час [0..23] | 03 Минута [0..59] | 04 Секунды [0..59] | 05 День [1..31] | 06 Месяц [1..12] | 07 Год [0..99] | 08 Столетие [19-20] | 09 CRC мл. байт | 10 CRC ст. байт |
---|---|---|---|---|---|---|---|---|---|---|---|
Master→Slave | 0x01 | 0x50 | 0x0A | 0x01 | 0x00 | 0x01 | 0x0A | 0x02 | 0x14 | 0x89 | 0x1C |
Направление передачи | 00 адрес подчиненного устройства | 01 номер функции | 02 Час [0..23] | 03 Минута [0..59] | 04 Секунды [0..59] | 05 День [1..31] | 06 Месяц [1..12] | 07 Год [0..99] | 08 Столетие [19-20] | 09 CRC мл. байт | 10 CRC ст. байт |
---|---|---|---|---|---|---|---|---|---|---|---|
Slave→Master | 0x01 | 0x50 | 0x0A | 0x01 | 0x00 | 0x01 | 0x0A | 0x02 | 0x14 | 0x89 | 0x1C |
mediaknowledge.ru
В этой статье я расскажу какие есть функции в протоколе Modbus и какой формат они используют. Вначале будут показаны функции с форматом для Modbus RTU. В конце статьи я покажу разницу в формате для Modbus TCP и Modbus ASCII.
Небольшое примечание. Все примеры команд будут данные в шестнадцатеричном виде без приставки 0х. Например, 05 означает 0х05, а 0А означает 0х0А (10 в десятичной системе). Все байт идут с лева на право (самый левый – первый байт, самый правый – последний байт).
Отдельно будут показан формат запроса и формат ответа. А так же будут приведены конкретные примеры.
Самая первая функция, которую мы рассмотрим – это чтение состояния COIL, т.е. чтение состояния цифрового выхода (Digital Output). Состояние цифрового выхода может быть последнее записанное в него значение (как вы должны помнить, 1 или 0). Эта команда может читать несколько регистров сразу. В команде указывается адрес первого регистра, с которого нужно начинать чтение, и общее количество регистров, которые нужно прочитать. Максимально количество регистров, которое можно прочитать одной командой – 2048. Это связано с тем, что максимальное количество байт в ответе может быть 256. Соответственно, так как 1 байт хранит значения 8 регистров, общее количество регистров равно 2048.
Запрос: 11 01 0013 0025 0E84
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 01 | Код команды |
2-3 | 0013 | Адрес COIL регистра, с которого нужно начинать чтение. В данном случае 0х0013 = 19. Но это не адрес, а смещение от адреса 1. Т.е. реальный адрес = 19 + 1 = 20. |
4-5 | 0025 | Количество регистров, которые нужно прочитать. 0х0025 = 37. Т.е. читать нужно регистры 20 – 56. |
6-7 | 0E84 | CRC16 значение байтов 0-5 |
Ответ: 11 01 05 CD6BB20E1B 45E6
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 01 | Код команды. Должен быть таким-же как и в запросе. |
2 | 05 | Количество байт в ответе, которые хранят значения прочитанных регистров. Каждый бит хранит значение одного регистра. Т.е. в нашем случае для 37 регистров нужно: 37 / 8 + 1 = 5 байт |
3 | CD | Значение регистров 27 — 20 (1100 1101) |
4 | 6B | Значение регистров 35 — 28 (0110 1011) |
5 | B2 | Значение регистров 43 — 36 (1011 0010) |
6 | 0E | Значение регистров 51 — 44 (0000 1110) |
7 | 1B | Значение регистров 56 — 52 (0001 1011) |
8-9 | 45E6 | CRC16 значение байтов 0-7 |
Байты данных в ответе хранят значения с младшего бита к старшему.
Регистр 20 –> байт #3, бит #0
Регистр 21 –> байт #3, бит #1
Регистр 22 –> байт #3, бит #2
…
Регистр 27 –> байт #3, бит #7
Так же в байте #7 нам нужно сохранить значения только для 5 регистров. Поэтому мы используем только 5 младших битов, а старшие 3, которые не используются, устанавливаем в 0.
Эта команда используется для чтения цифровых входов устройства. По формату и значению эта команда практически идентична команде чтение состояния COIL регистра. Отличия только в коде команды и адресации регистров.
Значение цифрового входа может быть 0 или 1. Эта команда может читать несколько регистров сразу. В команде указывается адрес первого регистра, с которого нужно начинать чтение, и общее количество регистров, которые нужно прочитать. Максимально количество регистров, которое можно прочитать одной командой – 2048. Это связано с тем, что максимальное количество байт в ответе может быть 256. Соответственно, так как 1 байт хранит значения 8 регистров, общее количество регистров равно 2048.
Запрос: 11 02 00C4 0016 BAA9
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 02 | Код команды |
2-3 | 00C4 | Адрес INPUT регистра, с которого нужно начинать чтение. В данном случае 0х00C4 = 196. Но это не адрес, а смещение от адреса 10001. Т.е. реальный адрес = 196+ 10001 = 10197. |
4-5 | 0016 | Количество регистров, которые нужно прочитать. 0х0016 = 22. Т.е. читать нужно регистры 10197– 10218. |
6-7 | BAA9 | CRC16 значение байтов 0-5 |
Ответ: 11 02 03 ACDB35 2018
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 02 | Код команды. Должен быть таким-же как и в запросе. |
2 | 03 | Количество байт в ответе, которые хранят значения прочитанных регистров. Каждый бит хранит значение одного регистра. Т.е. в нашем случае для 22 регистров нужно: 22 / 8 + 1 = 3 байта |
3 | AC | Значение регистров 10204 — 10197 (1010 1100) |
4 | DB | Значение регистров 10212 — 10205 (1101 1011) |
5 | 35 | Значение регистров 10218 — 10213 (0011 0101) |
6-7 | 2018 | CRC16 значение байтов 0-5 |
Байты данных в ответе хранят значения с младшего бита к старшему.
Регистр 10197 –> байт #3, бит #0
Регистр 10198 –> байт #3, бит #1
Регистр 10199 –> байт #3, бит #2
…
Регистр 10204 –> байт #3, бит #7
Так же в байте #5 нам нужно сохранить значения только для 6 регистров. Поэтому мы используем только 6 младших битов, а старшие 2, которые не используются, устанавливаем в 0.
Эта команда используется для чтения HOLDING регистров на устройстве. Значение HOLDING регистра может быть любое 16 битное число. Эта команда может читать несколько регистров сразу. В команде указывается адрес первого регистра, с которого нужно начинать чтение, и общее количество регистров, которые нужно прочитать. Максимально количество регистров, которое можно прочитать одной командой – 128. Это ограничение вызвано тем, что в ответе указывается количество байт данных. Для этого используется только один байт, т.е. количество байтов данных может быть максимум 256. Каждый регистр содержит двухбайтное значение, т.е всего может быть возвращено 128 регистров.
Запрос: 11 03 006B 0003 7687
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 03 | Код команды |
2-3 | 006B | Адрес HOLDING регистра, с которого нужно начинать чтение. В данном случае 0х006B = 107. Но это не адрес, а смещение от адреса 40001. Т.е. реальный адрес = 107+ 40001 = 40108. |
4-5 | 0003 | Количество регистров, которые нужно прочитать. 0х0003 = 3. Т.е. читать нужно регистры 40108– 40110. |
6-7 | 7687 | CRC16 значение байтов 0-5 |
Ответ: 11 03 06 AE41 5652 4340 49AD
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 03 | Код команды. Должен быть таким-же как и в запросе. |
2 | 06 | Количество байт в ответе, которые хранят значения прочитанных регистров. Так как читали мы 3 регистра, то нам нужно 3 * 2 байта = 6 байт |
3-4 | AE41 | Значение регистров 40108 |
5-6 | 5652 | Значение регистров 40109 |
7-8 | 4340 | Значение регистров 40110 |
9-10 | 2018 | CRC16 значение байтов 0-8 |
Эта команда используется для чтения INPUT регистров на устройстве. Значение INPUT регистра может быть любое 16 битное число. Эта команда может читать несколько регистров сразу. В команде указывается адрес первого регистра, с которого нужно начинать чтение, и общее количество регистров, которые нужно прочитать. Максимально количество регистров, которое можно прочитать одной командой – 128. Это ограничение вызвано тем, что в ответе указывается количество байт данных. Для этого используется только один байт, т.е. количество байтов данных может быть максимум 256. Каждый регистр содержит двухбайтное значение, т.е всего может быть возвращено 128 регистров.
Запрос: 11 04 0008 0001 B298
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 04 | Код команды |
2-3 | 0008 | Адрес INPUT регистра, с которого нужно начинать чтение. В данном случае 0х0008 = 8. Но это не адрес, а смещение от адреса 30001. Т.е. реальный адрес = 8+ 30001 = 30008. |
4-5 | 0001 | Количество регистров, которые нужно прочитать. 0х0001 = 1. Т.е. читать нужно регистр 30008. |
6-7 | B298 | CRC16 значение байтов 0-5 |
Ответ: 11 04 02 000A F8F4
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 04 | Код команды. Должен быть таким-же как и в запросе. |
2 | 02 | Количество байт в ответе, которые хранят значения прочитанных регистров. Так как читали мы 1 регистр, то нам нужно 1 * 2 байта = 2 байта |
3-4 | 000A | Значение регистров 30008 |
5-6 | F8F4 | CRC16 значение байтов 0-4 |
Эта команда используется для записи COIL регистров на устройстве. Значение COIL регистра может быть 1 или 0 (ON или OFF). Эта команда может записывать только один регистр за раз. В команде указывается адрес регистра и значение, которое нужно записать в регистр. Значения могут быть следующие:
0x0000 — OFF (логический 0)
0x FF00 – ON (логическая 1)
Как видите, значения двухбайтные.
Запрос: 11 05 00AC FF00 4E8B
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 05 | Код команды |
2-3 | 00AC | Адрес COIL регистра, который нужно записать. В данном случае 0х00AC = 172. Но это не адрес, а смещение от адреса 1. Т.е. реальный адрес = 172 + 1 = 173. |
4-5 | FF00 | Записываемое значение. 0xFF00 – логическая 1 |
6-7 | 4E8B | CRC16 значение байтов 0-5 |
Ответ: 11 05 00AC FF00 4E8B
Как видите, это просто эхо команды, которые мы отослали. Т.е. если все прошло успешно, мы получим эхо команды.
Эта команда используется для записи HOLDING регистров на устройстве. Значение HOLDING регистра может быть любое 16 битное число. Эта команда может записывать только один регистр за раз. В команде указывается адрес регистра и значение, которое нужно записать в регистр.
Запрос: 11 06 0001 0003 9A9B
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 06 | Код команды |
2-3 | 0001 | Адрес HOLDING регистра, который нужно записать. В данном случае 0х0001 = 1. Но это не адрес, а смещение от адреса 40001. Т.е. реальный адрес = 1 + 40001 = 40002. |
4-5 | 0003 | Записываемое значение. |
6-7 | 9A9B | CRC16 значение байтов 0-5 |
Ответ: 11 06 0001 0003 9A9B
Как видите, это просто эхо команды, которые мы отослали. Т.е. если все прошло успешно, мы получим эхо команды.
Эта команда используется для записи COIL регистров на устройстве. Значение COIL регистра может быть 1 или 0 (ON или OFF). Эта команда может записывать несколько регистров за раз. В команде указывается адрес первого регистра, с которого нужно начинать запись, количество регистров, которые нужно записать и передаются значения для записи, в виде битовых значений 0 или 1.
Запрос: 11 0F 0013 000A 02 CD01 BF0B
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 0F | Код команды |
2-3 | 0013 | Адрес COIL регистра, с которого нужно начинать чтение. В данном случае 0х0013 = 19. Но это не адрес, а смещение от адреса 1. Т.е. реальный адрес = 19 + 1 = 20. |
4-5 | 000A | Количество регистров, которые нужно записать. 0х000A = 10. Т.е. писать нужно в регистры 20 – 29. |
6 | 02 | Количество байт данных в команде. 10 регистров требуют 2 байта (8 в первом и 2 во втором) |
7 | CD | Байты данных. Первый байт для регистров 20 – 27 1100 1101 |
8 | 01 | Байты данных. Второй байт для регистров 28 – 29 0000 0001 |
9-10 | BF0B | CRC16 значение байтов 0-8 |
Байты данных в запросе хранят значения с младшего бита к старшему.
Регистр 20 –> байт #7, бит #0
Регистр 21 –> байт #7, бит #1
Регистр 22 –> байт #7, бит #2
…
Регистр 28 –> байт #8, бит #0
Регистр 29 –> байт #8, бит #1
Неиспользуемые биты нужно установить в 0.
Ответ: 11 0F 0013 000A 2699
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 0F | Код команды. Должен быть таким-же как и в запросе. |
2-3 | 0013 | Адрес COIL регистра, с которого начиналась запись. Такое же значение как и в запросе. |
3-4 | 000A | Количество записанных регистров |
5-6 | 2699 | CRC16 значение байтов 0-4 |
Эта команда используется для записи HOLDING регистров на устройстве. Значение HOLDING регистра может быть любое значение. Эта команда может записывать несколько регистров за раз. В команде указывается адрес первого регистра, с которого нужно начинать запись, количество регистров, которые нужно записать и передаются значения для записи.
Запрос: 11 10 0001 0002 04 000A 0102 C6F0
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое должно обработать команду. |
1 | 10 | Код команды |
2-3 | 0001 | Адрес HOLDING регистра, с которого нужно начинать чтение. В данном случае 0х0001 = 1. Но это не адрес, а смещение от адреса 40001. Т.е. реальный адрес = 1 + 40001 = 40002. |
4-5 | 0002 | Количество регистров, которые нужно записать. 0х0002 = 2. Т.е. писать нужно в регистры 40002– 40003. |
6-7 | 04 | Количество байт данных в команде. 2 регистра требуют 4 байта |
8-9 | 000A | Байты данных. Значение которое будет записано в регистр 40002 |
10-11 | 0102 | Байты данных. Значение которое будет записано в регистр 40003 |
12-13 | C6F0 | CRC16 значение байтов 0-11 |
Ответ: 11 10 0001 0002 1298
Индекс байта | Значение | Описание |
0 | 11 | Адрес конечного устройства, которое обработало команду. Должно быть таким-же как и в запросе. |
1 | 10 | Код команды. Должен быть таким-же как и в запросе. |
2-3 | 0001 | Адрес HOLDING регистра, с которого начиналась запись. Такое же значение как и в запросе. |
3-4 | 0002 | Количество записанных регистров |
5-6 | 1298 | CRC16 значение байтов 0-4 |
Как видите, протокол Modbus имеет небольшой набор команд, всего 7. Большинство команд очень похожи, а структура их очень проста. Так же, это формат для команд протокола Modbus RTU. Но те же самые команды используются и в протоколе Modbus TCP, лишь с небольшими изменениями. То же самое относится и к Modbus ASCII. Я это опишу в отдельных статьях, посвященных каждому протоколу в отдельности.
Кроме того, если на конечном устройстве происходит ошибка, Modbus устройство должно вернуть Exception (исключение) – просто код ошибки. Этот случай так же будет рассмотрен в отдельной статье.
www.siv-blog.com