8-900-374-94-44
[email protected]
Slide Image
Меню

Описание протокола modbus ascii на русском – Особенности протокола Modbus ASCII — Блог Домашнего Программиста

Содержание

Особенности протокола Modbus ASCII - Блог Домашнего Программиста

Пришло время рассмотреть еще одну вариацию протокола ModbusModbus ASCII. Эта версия протокола использует для передачи данных только символы ASCII, которыми кодирует шестнадцатеричное представление бинарных данных. Немного не понятно и запутано? Это ничего, welcome под кат и давайте рассмотрим, с чем же мы имеем дело.

Разделитель пакетов

Первое отличие протокола Modbus ASCII от Modbus RTU – у него есть разделитель между пакетами. Если в Modbus RTU все пакеты шли один за одним (практически, там должна быть небольшая задержка на линии между пакетами, порядка 2-5мс), то в Modbus ASCII каждый новый пакет должен начинаться со специального символа разделителя.

По стандарту Modbus RTU между пакетами нужна задержка в 3.5 символа (это время, которое нужно для передачи 3.5 символов по линии связи, зависит от скорости передачи). Эта задержка используется, что бы детектировать новый запрос от мастера. Т.е. эта задержка указывает начало нового запроса. Но когда стали использовать модемы, это перестало работать. На модеме невозможно выдержать нужное время. Поэтому решили использовать новый вариант протокола —

Modbus ASCII. Этот вариант устраняет многие неудобства при работе с модемом: есть специальный символ разделитель пакетов и используются только видимые символы ASCII.

Так вот, таким символом начала пакета служит символ двоеточие с шестнадцатеричным кодом 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 ASCII, нам нужно уже передавать 2 байта. На первом этапе мы получаем шестнадцатеричный код символа, 0x23. На втором этапе мы кодируем это значение при помощи двух символов ASCII – 2 и 3. И на третьем этапе мы передаем два байта данных, первый  — это шестнадцатеричное значение символа 2, второй байт — это шестнадцатеричное значение символа

3.

Таким образом, диапазон значений для байта данных в протоколе Modbus RTU0 .. 0xFF

Диапазон значений для байта данных в протоколе Modbus ASCII – только символы, необходимые для отображения шестнадцатеричных цифр, т.е. 0 – 9, A, B, C, D, E, F (все заглавные).

 

Контрольная сумма для Modbus ASCII

В протоколе Modbus RTU используется 2 байтная контрольная сумма, которая помогает детектировать поврежденные запросы. В протоколе Modbus ASCII так же есть контрольная сумма – LRC (Longitudinal Redundancy Check).

Вычисление LRC намного проще, чем вычисление CRC. Что бы высчитать LRC вам нужно сделать следующие:

  • Сложить вместе все байты в сообщении Modbus ASCII, до того, как они сконвертированы в в символы ASCII. Не включаются в вычисления стартовый символ двоеточия и завершающие символы CR/LF.
  • Обнулить все биты больше 8 (т.е. оставить младший байт)
  • Сделать результирующий байт отрицательным чтобы получить
    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

Вот это отрицательное число (-130 или 0x7E) и есть LRC запроса.

Эта контрольная сумма добавляется к запросу в виде 2 ASCII символов – 7 и E.

Т.е. в конце запроса нужно добавить 2 байта со значением 37 и 45.

 

Примеры Modbus RTU и Modbus ASCII запросов

Что бы лучше понять, как все это работает, посмотрите пару простых примеров.

Возьмем наш запрос на чтение регистров #40108 — #40110 с устройства с адресом 17

Запрос: 11 03 00 6B 00 03

Это Modbus RTU запрос без последних двух байтов CRC. Теперь преобразуем этот запрос из Modbus RTU в Modbus ASCII. Для этого добавляем в начало запроса символ двоеточия, в конец запроса символ перевода строки и возврата каретки, а каждый байт представим в виде ASCII символов, соответствующих шестнадцатеричному представлению каждого байта запроса. В итоге у нас получиться такой запрос (в виде ASCII символов, или попросту в виде текстовой строки). Так же в конец запроса добавляем

LRC.

: 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

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 ASCII Archives - Блог Домашнего Программиста

В предыдущих статьях описывался формат запросов и ответов для Modbus RTU и Modbus ASCII протоколов. В этих протоколах для подтверждения целостности данных используются контрольные суммы, которые вычисляются по специальным алгоритмам. В тех статьях я не описывал их, так что сейчас я приведу пример функций который это делают. Я собираюсь написать их на двух языках — C# и C/C++. Думаю они будут полезны.

Читать далее →

Опубликовано в .NET/C#, C/C++, Modbus и отмечено C/C++, C#, CRC16, LRC, Modbus, Modbus ASCII, Modbus RTU в slepchenkov. 3 комментария

Как и в любой системе при общении по протоколу Modbus могут возникать ошибки и непредвиденные ситуации. Для обработки таких случаев в протоколе предусмотрены специальные ответы, которые помогают мастеру, отправившему запрос, узнать какого именно рода ошибка или исключительная ситуация произошла.
Читать далее →

Опубликовано в Modbus и отмечено Modbus ASCII, Modbus Protocol, Modbus RTU, Modbus TCP в slepchenkov. Комментировать

Пришло время рассмотреть еще одну вариацию протокола ModbusModbus 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

Описание протокола MODBUS-ASCII для приборов Термодат

[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

Embedded systems: MODBUS

Описание протокола Modbus RTU

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-99990000 до 270EЧтение-записьDiscrete Output CoilsDO
10001-199990000 до 270EЧтениеDiscrete Input ContactsDI
30001-399990000 до 270EЧтениеAnalog Input RegistersAI
40001-499990000 до 270EЧтение-записьAnalog Output Holding RegistersAO

В сообщении 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 integer0 до 65535AE4144,609
16-bit signed integer-32768 до 32767AE41-20,927
two character ASCII string2 знакаAE41® A
discrete on/off value0 и 100010001
32-bit unsigned integer0 до 4,294,967,295AE41 56522,923,517,522
32-bit signed integer-2,147,483,648 до 2,147,483,647AE41 5652-1,371,449,774
32-bit single precision IEEE floating point number1,2·10−38 до 3,4×10+38AE41 5652-4.395978 E-11
four character ASCII string4 знакаAE41 5652® A V R

Какие бывают команды Modbus RTU?

Приведем таблицу с кодами функций чтения и записи регистров Modbus RTU.

Код функцииЧто делает функцияТип значенияТип доступа
01 (0x01)Чтение DORead Coil StatusДискретноеЧтение
02 (0x02)Чтение DIRead Input StatusДискретноеЧтение
03 (0x03)Чтение AORead Holding Registers16 битноеЧтение
04 (0x04)Чтение AIRead Input Registers16 битноеЧтение
05 (0x05)Запись одного DOForce Single CoilДискретноеЗапись
06 (0x06)Запись одного AOPreset Single Register16 битноеЗапись
15 (0x0F)Запись нескольких DOForce Multiple CoilsДискретноеЗапись
16 (0x10)Запись нескольких AOPreset Multiple Registers16 битноеЗапись

Как послать команду Modbus RTU на чтение дискретного вывода? Команда 0x01

Эта команда используется для чтения значений дискретных выходов 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Контрольная сумма CRC0EЗначение регистра DO 51-44 (0000 1110)
84Контрольная сумма CRC1BЗначение регистра DO 56-52 (0001 1011)
45Контрольная сумма CRC
E6Контрольная сумма CRC

Состояния выходов DO 27-20 показаны как значения байта CD hex, или в двоичной системе 1100 1101.

В регистре DO 56-52 5 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (0001 1011).

Каналы---DO 56DO 55DO 54DO 53DO 52
Биты00011011
Hex1B

Как послать команду Modbus RTU на чтение дискретного ввода? Команда 0x02

Эта команда используется для чтения значений дискретных входов 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Контрольная сумма CRC20Контрольная сумма CRC
A9Контрольная сумма CRC18Контрольная сумма CRC

Как послать команду Modbus RTU на чтение аналогового вывода? Команда 0x03

Эта команда используется для чтения значений аналоговых выходов 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Контрольная сумма CRC52Значение регистра Lo #40109
87Контрольная сумма CRC43Значение регистра Hi #40110
40Значение регистра Lo #40110
49Контрольная сумма CRC
ADКонтрольная сумма CRC

Как послать команду Modbus RTU на чтение аналогового ввода? Команда 0x04

Эта команда используется для чтения значений аналоговых входов 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Контрольная сумма CRCF4Контрольная сумма CRC
98Контрольная сумма CRC

Как послать команду Modbus RTU на запись дискретного вывода? Команда 0x05

Эта команда используется для записи одного значения дискретного выхода 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Контрольная сумма CRC4EКонтрольная сумма CRC
8BКонтрольная сумма CRC8BКонтрольная сумма CRC
Состояние выхода DO173 поменялось с выключен OFF на включен ON.

Как послать команду Modbus RTU на запись аналогового вывода? Команда 0x06

Эта команда используется для записи одного значения аналогового выхода 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Контрольная сумма CRC9AКонтрольная сумма CRC
9BКонтрольная сумма CRC9BКонтрольная сумма CRC

Как послать команду Modbus RTU на запись нескольких дискретных выводов? Команда 0x0F

Эта команда используется для записи нескольких значений дискретного выхода 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
В ответе возвращается количество записанных регистров.

Как послать команду Modbus RTU на запись нескольких аналоговых выводов? Команда 0x10

Эта команда используется для записи нескольких значений аналогового выхода 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 4000298Контрольная сумма CRC
0AЗначение Lo 40002
01Значение Hi 40003
02Значение Lo 40003
C6Контрольная сумма CRC
F0Контрольная сумма CRC

Какие бывают ошибки запроса Modbus?

Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки.

Ответ будет содержать измененный Функциональный код, старший бит будет равен 1.

Пример:

БылоСтало
Функциональный код в запросеФункциональный код ошибки в ответе
01 (01 hex) 0000 0001129 (81 hex) 1000 0001
02 (02 hex) 0000 0010130 (82 hex) 1000 0010
03 (03 hex) 0000 0011131 (83 hex) 1000 0011
04 (04 hex) 0000 0100132 (84 hex) 1000 0100
05 (05 hex) 0000 0101133 (85 hex) 1000 0101
06 (06 hex) 0000 0110134 (86 hex) 1000 0110
15 (0F hex) 0000 1111143 (8F hex) 1000 1111
16 (10 hex) 0001 0000144 (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

Modbus — коммуникационный протокол, основанный на клиент-серверной архитектуре. Разработан фирмой Modicon для использования в контроллерах с программируемой логикой (PLC). Стал стандартом де-факто в промышленности и широко применяется для организации связи промышленного электронного оборудования. Использует для передачи данных последовательные линии связи RS-485, RS-422, RS-232, а также сети TCP/IP. В настоящее время поддерживается некоммерческой организацией Modbus-IDA.

Общее описание протокола Modbus RTU

Протокол 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).

Таблица 1-1. Кадр посылки modbus RTU
адрес подчиненного устройства номер функции данные CRC

1 байт

1 байт

N < 253 (байт) 2 байта

где:

  • адрес подчинённого устройства — первое однобайтное поле кадра. Оно содержит адрес подчинённого устройства, к которому адресован запрос. Подчинённые устройства отвечают только на запросы, поступившие только в их адрес. Ответ также начинается с адреса отвечающего устройства, который может изменяться от 1 до 254. Адрес 0 используется для широковещательной передачи, его распознаёт каждое устройство;
  • номер функции — это следующее однобайтное поле кадра. Оно говорит подчинённому устройству, какие данные или выполнение какого действия требует от него ведущее устройство;
  • данные — поле содержит информацию, необходимую подчиненному устройству для выполнения заданной мастером функции или содержит данные, передаваемые подчинённым устройством в ответ на запрос ведущего. Длина и формат поля зависит от номера функции;
  • CRC — (контрольная сумма) заключительное двухбайтное поле кадра. Контрольная сумма завершает кадры запроса и ответа.

Следует отметить, что поле CRC записывается младшим байтом вперёд. Алгоритм расчёта CRC может отличаться для разных устройств.

Адресация данных в протоколе Modbus RTU

Все операции с данными привязаны к нулю, каждый вид данных (регистр, выходное/входное значение) начинаются с адреса 0000. Адресация к ячейке начинается с 1.

Например: Флаг номер 1 программируемого контроллера имеет адрес 0000 (указывается в поле "Адрес").

Флаг номер 127 (DEC) имеет адрес 0x007E hex (126 dec) (указывается в поле "Адрес").

Запоминающий регистр 40001 будет иметь адрес 0000 в поле "Адрес" команды. Потому что код операции уже содержит в себе необходимую информацию об адресе. Операции с этими регистрами имеют смещение Адрес_регистра - 40000 = Значение Используемое В Поле "Адрес". Тип адресации команд в дальнейшем будем помечать т.о.

смещение обозначение
-40000 4x
-10000 1x

Запоминающий регистр 40108 будет иметь адрес 006B hex (107 dec)

Контроль ошибок в протоколе Modbus RTU

Во время обмена данными могут возникать ошибки двух типов:

  • ошибки, связанные с искажениями при передаче данных;
  • логические ошибки.

Ошибки первого типа обнаруживаются при помощи фреймов символов, контроля чётности и циклической контрольной суммы CRC-16-IBM (используется число-полином = 0xA001).

RTU фрейм

В 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 принимает запрос, но не может его обработать (обращение к несуществующему регистру и т.д.), отправляется ответ содержащий в себе данные об ошибке.

Таблица 2-1. Кадр ответа (Slave→Master) при возникновении ошибки modbus RTU
Направление передачи адрес подчинённого устройства номер функции данные (или код ошибки) 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

В протокол Modbus можно выделить несколько подмножеств команд ( Таблица 3-1).

Таблица 3-1
Подмножество команд Диапазон кодов команд

Стандартные команды

1-21

Резерв для расширенных функций

22-64

Пользовательские

65-119

Резерв для внутренних нужд

120-255

0x10 Preset Multiple Registers (Установка значений в несколько регистров)

Тип адресации 4x

Значения регистров передаются в линию начиная с указанного адреса, следующие значения регистров передаются после него (см. поле "Данные"). Ниже приведены примеры команда ведущего устройства (таблица 3-2) и ответ ведомого (таблица 3-3):

Таблица 3-2. Пример установки значения в один регистр
Направление передачи 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

Таблица 3-3.Ответ на команду установки значения в один регистр
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Кол. регистров ст. байт 05 Кол. регистров мл. байт 06 CRC мл. байт 07 CRC ст. байт

Slave→Master

0x01

0x10

0x00

0x01

0x00

0x01

0x1C

0x90

0x03 Read Holding Registers (Чтение значений из нескольких регистров)

Тип адресации 4x

Ниже приведены примеры команда ведущего устройства (таблица 3-4) и ответ ведомого (таблица 3-5):

Таблица 3-4. Пример чтения значения из одного регистра
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Кол. регистров ст. байт 05 Кол. регистров мл. байт 06 CRC мл. байт 07 CRC ст. байт

Master→Slave

0x01

0x03

0x00

0x01

0x00

0x01

0xD5

0xCA


Значения регистров передаются в линию начиная с указанного адреса, следующие значения регистров передаются после него (см. поле "Данные").

Таблица 3-5. Ответ на команду чтения значения из одного регистра
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Кол. Байт 03 Данные ст. байт 04 Данные мл. байт 05 CRC мл. байт 06 CRC ст. байт

Slave→Master

0x01

0x03

0x02

0xFF

0xFF

0xB9

0xF4

0x06 Preset Single Register (Установка значения в один регистр)

Тип адресации 4x

Ниже приведены примеры команда ведущего устройства (таблица 3-2) и ответ ведомого (таблица 3-3):

Таблица 3-6. Пример установки значения в один регистр
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Данные ст. байт 05 Данные мл. байт 06 CRC мл. байт 07 CRC ст. байт

Master→Slave

0x01

0x06

0x00

0x01

0xFF

0xFF

0xD9

0xBA

Таблица 3-7. Ответ на команду установки значения в один регистр
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Данные ст. байт 05 Данные мл. байт 06 CRC мл. байт 07 CRC ст. байт

Slave→Master

0x01

0x06

0x00

0x01

0xFF

0xFF

0xD9

0xBA

0x01 Read Coil Status (Чтение значений из нескольких регистров флагов)

Тип адресации 0x

Запрос:

Состоит из адреса флага и количества считываемых флагов. Адресация флагов начинается с 0, количество флагов с 1.

Ответ:

Значение флагов передается в одном бите в поле "Данные". Трактовка флагов: 1 = ON; 0 = OFF. 0-й бит первого байта данных содержит значение флага указанного в поле "Адрес". Если запросить состояние одного флага, то в младшем бите будет возвращено значение флага, а все остальные старшие биты заполнены нулями.

Ниже приведены примеры запроса ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7). В примере запрашивается состояние 9 флагов с адреса 1. В ответе содержится 2 байта данных, для большей ясности будем считать что все запрашиваемые флаги находятся в состоянии ON, а все остальные в состоянии OFF.

Таблица 3-8. Пример чтения значения из одного регистра флагов
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Кол. флагов ст. байт 05 Кол. флагов мл. байт 06 CRC мл. байт 07 CRC ст. байт

Master→Slave

0x01

0x01

0x00

0x01

0x00

0x09

0x

0x

Таблица 3-9. Пример ответа на запрос чтения значения из одного регистра флагов
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Количество байт 03 Данные (флаги 0-7) 04 Данные (флаги 8-15) 05 CRC мл. байт 06 CRC ст. байт

Slave→Master

0x01

0x01

0x02

0xFF

0x01

0x

0x

0x0F Force Multiple Coils (Запись значений в несколько регистров флагов)

Тип адресации 0x

Команда:

Состоит из адреса флага, количества изменяемых флагов, количества передаваемых байт устанавливаемых значений. Адресация флагов начинается с 0, количество флагов с 1. Устанавливаемые значения передаются начиная с байта, в котором находится младшим битом значение, устанавливаемое по адресу указываемому в поле "00 адрес подчиненного устройства".

Ответ:

Состоит из начального адреса флага и количества записанных флагов. Адресация флагов начинается с 0, количество флагов с 1.

Ниже приведены примеры команды ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7).

Таблица 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

Таблица 3-7. Пример команды записи значения в один из регистр флагов
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Количество флагов ст. байт 05 Количество флагов мл. байт 05 CRC мл. байт 06 CRC ст. байт

Slave→Master

0x01

0x0F

0x00

0x13

0x00

0x0A

0x24

0x09

0x05 Force Single Coil (Запись значения в один флаг регистра флагов)

Команда:

Состоит из адреса флага и устанавливаемого значения. Поле "Значение флага мл. байт" всегда равно нулю (0x00), поле "Значение флага ст. байт" принимает значения 0xFF если флаг устанавливается в "1"(ON) или 0x00 если флаг устанавливается в "0"(OFF), другие значения недопустимы и не влияют на значение флага. Адресация флагов начинается с 0.

Ответ:

Состоит из начального адреса флага и количества записанных флагов. Адресация флагов начинается с 0, количество флагов с 1.

Ниже приведены примеры команды ведущего устройства (таблица 3-6) и ответ ведомого (таблица 3-7).

Таблица 4-4. Пример: команда установки значения в один флаг
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Значение флага ст. байт 05 Значение флага мл. байт 06 CRC мл. байт 07 CRC ст. байт

Master→Slave

0x01

0x05

0x00

0x13

0xFF

0x00

0x7D

0xFF

Таблица 4-4. Пример: Ответ на команду установки значения в один флаг
Направление передачи 00 адрес подчиненного устройства 01 номер функции 02 Адрес ст. байт 03 Адрес мл. байт 04 Значение флага ст. байт 05 Значение флага мл. байт 06 CRC мл. байт 07 CRC ст. байт

Slave→Master

0x01

0x05

0x00

0x13

0xFF

0x00

0x7D

0xFF

0x50 Set date and time (Установка даты и времени)

Ниже приведены примеры команда ведущего устройства (таблица 5-4) и ответ ведомого (таблица 5-5):

Таблица 5-4. Пример установки даты и времени
Направление передачи 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

Таблица 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 ст. байт

Slave→Master

0x01

0x50

0x0A

0x01

0x00

0x01

0x0A

0x02

0x14

0x89

0x1C

Ссылки на используемые в статье источники

mediaknowledge.ru

Modbus Функции - Блог Домашнего Программиста

В этой статье я расскажу какие есть функции в протоколе Modbus и какой формат они используют. Вначале будут показаны функции с форматом для Modbus RTU. В конце статьи я покажу разницу в формате для Modbus TCP и Modbus ASCII.

Небольшое примечание. Все примеры команд будут данные в шестнадцатеричном виде без приставки 0х. Например, 05 означает 0х05, а 0А означает 0х0А (10 в десятичной системе). Все байт идут с лева на право (самый левый – первый байт, самый правый – последний байт).

Отдельно будут показан формат запроса и формат ответа. А так же будут приведены конкретные примеры.

Список команд:

Чтение состояния COIL регистра

Самая первая функция, которую мы рассмотрим – это чтение состояния 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.

Чтение CONTACT регистра

Эта команда используется для чтения цифровых входов устройства. По формату и значению эта команда практически идентична команде чтение состояния 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 регистров на устройстве. Значение 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 регистров на устройстве. Значение 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 регистров на устройстве. Значение 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 регистров на устройстве. Значение 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 регистров на устройстве. Значение 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 регистров на устройстве. Значение 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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *