Modbus_Rus (1031648), страница 8
Текст из файла (страница 8)
Скорость передачи
(C) Modbus сообщение обрабатывается в конце скана контроллера. В худшем случае задержка будет равна времени одного скана. В среднем задержка составляет 0.5 скана.
Время, выделяемое для обслуживания портов Modbus в конце каждого скана контроллера(перед началом нового), зависит от модели контроллера. Время для каждой модели описано ниже.Для 484 контроллера это время составляет приблизительно 1.5 мс.
Для 584 и 984 контроллера время составляет приблизительно 1.5 мс. Порты обслуживаются последовательно, начиная с порта 1.
Для 184/384 контроллеров время зависит от количества принимаемых данных. Это время варьируется от минимального 0.5 мс до максимального около 6.0 мс (для 100 регистров), или 7.0 мс (для 800 выходов).Если с контроллером используется программная панель, то Modbus порт отключается.
(D) Modbus Функции с 1 по 4, 15 и 16 позволяет главному устройству запросить больше данных чем то количество, которое может обработать контроллер в течении времени выделяемого на обслуживание портов. Если подчиненный не успел обработать все данные, он может буферизировать их и обработать позже.
Ниже приведены данные, которые могут быть обработаны за один цикл обслуживания Modbus порта.
Дискреты | Регистры | |
Micro 84 | 16 | 4 |
184/384 | 800 | 100 |
484 | 32 | 16 |
584 | 64 | 32 |
984A/B/X | 64 | 32 |
984-X8X | 1000 | 125 |
Примечание: '984-X8X' ссылается на slot-mount модели(984-385, -685 и т.д.).
Для 884, время обработки множественных данных следующее: Чтение 700 выходов: 14 сканов Установка единич. выхода: 3 скана Чтение 256 входов: 7 сканов Установка регистра: 3 скана Чтение 125 вых. рег-ов: 5 сканов Установка 768 выходов: 18 сканов Чтение 125 вх. рег-ов: 8 сканов Установка 100 рег.: 10 сканов
(E) Вычисление контрольной суммы LRC - около 1 мс. Вычисление контрольной суммы CRC - около 0.3 мс для каждых 8-ми бит данных возвращаемых в ответе.
ПРИМЕЧАНИЯ ДЛЯ 584 И 984A/B/X
Это примечание касается только 584 и 984A/B/X контроллеров.
СКОРОСТЬ ПЕРЕДАЧИ: Когда используются оба Modbus порта 1 и 2, максимальная доступная скорость передачи - 19 200 бод.
БЛОКИРОВКА ПОРТА: Когда вы используете ASCII режим, избегайте посылки сообщений с 'нулевой длиной данных', или сообщений без адреса устройства. Например, это неправильное сообщение:
: CR LF
При использовании такого рода сообщений может иметь место случайная блокировка порта.
ПРИЗНАК КОНЦА ASCII СООБЩЕНИЯ: Нормальное ASCII сообщение должно заканчиваться парой CRLF. При использовании контроллеров 584 и 984A/B/X, ASCII сообщение может заканчиваться после поля контрольной суммы LRC (без установки символов CRLF), если после поля LRC имеет место интервал по крайней мере 1 сек. Если это случилось, контроллер считает что сообщение закончилось нормально.
ПРИЛОЖЕНИЕ C
ГЕНЕРАЦИЯ LRC/CRC
Генерация LRC
Longitudinal Redundancy Check(LRC) это один байт. LRC вычисляется передающим устройством и добавляется к концу сообщения. Принимающее устройство также вычисляет LRC в процессе приема и сравнивает вычисленную величину с полем контрольной суммы пришедшего сообщения. Если суммы не совпали - то имеет место ошибка.
LRC вычисляется сложением последовательности байтов сообщения, отбрасывая все переносы, и затем двойным дополнением результата. LRC - это 8-ми битовое поле, где каждое новое прибавление символа, приводящее к результату более чем 255, приводит к простому перескакиванию через 0. Так как это поле не является 9-ти битовым, перенос отбрасывается автоматически.
Алгоритм генерации LRC:
1. Сложить все байты сообщения, исключая стартовый символ ':' и конечные CRLF, складывая их так, чтобы перенос отбрасывался.
2. Отнять получившееся значение от числа FF(Hex) - это является первым дополнением.
3. Прибавить к получившемуся значению 1 - это второе дополнение.
РАЗМЕЩЕНИЕ LRC В СООБЩЕНИИ
Когда 8-ми битовое поле LRC (2 ASCII символа) передается в сообщении, то старший символ будет передан первым, а за ним - младший. Например, если значение LRC 61 hex(0110 0001):
':' | Адрес | Функ ция | Сч-к байт | Байт | Байт | Байт | Байт | LRC Ст. | LRC Мл. | CR | LF | |
6 | 1 |
Пример функции на языке C реализующей генерацию LRC приведен ниже. Функция принимает два аргумента:
unsigned char *auchMsg; Указатель на буфер данных
unsigned short usDataLen; Количество байт в буфере
Функция возвращает LRC как тип unsigned char.
ПРИМЕР
static unsigned char LRC(auchMsg, usDataLen)
unsigned char *auchMsg;/* Сообщение над которым */
/* вычисляется LRC */
unsigned char usDataLen; /* Количество байт в сообщении */
{
unsigned char uchLRC=0; /* Инициализация LRC */
while(usDataLen)
uchLRC+=*auchMsg++;
return((unsigned char)(-((char uchLRC)));
}
Генерация CRC
CRC это 16-ти разрядная величина т.е. два байта. CRC вычисляется передающим устройством и добавляется к сообщению.Принимающее устройство также вычисляет CRC в процессе приема и сравнивает вычисленную величину с полем контрольной суммы пришедшего сообщения. Если суммы не совпали - то имеет место ошибка.
16-ти битовый регистр CRC предварительно загружается числом FF hex. Процесс начинается с добавления байтов сообщения к текущему содержимому регистра. Для генерации CRC используются только 8 бит данных. Старт и стоп биты, бит паритета, если он используется, не учитываются в CRC.
В процессе генерации CRC, каждый 8-ми битовый символ складывается по ИСКЛЮЧАЮЩЕМУ ИЛИ с содержимым регистра. Результата сдвигается в направлении младшего бита, с заполнением 0 старшего бита. Младший бит извлекается и проверяется. Если младший бит равен 1, то содержимое регистра складывается с определенной ранее, фиксированной величиной, по ИСКЛЮЧАЮЩЕМУ ИЛИ. Если младший бит равен 0, то ИСКЛЮЧАЮЩЕЕ ИЛИ не делается.
Этот процесс повторяется пока не будет сделано 8 сдвигов. После последнего (восьмого) сдвига, следующий байт складывается с содержимым регистра и процесс повторяется снова. Финальное содержание регистра, после обработки всех байтов сообщения и есть контрольная сумма CRC.
Алгоритм генерации CRC:
1. 16-ти битовый регистр загружается числом FF hex (все 1), и используется далее как регистр CRC.
2. Первый байт сообщения складывается по ИСКЛЮЧАЮЩЕМУ ИЛИ с содержимым регистра CRC. Результат помещается в регистр CRC.
3. Регистр CRC сдвигается вправо(в направлении младшего бита) на 1 бит, старший бит заполняется 0.
4. (Если младший бит 0): Повторяется шаг 3 (сдвиг)
(Если младший бит 1): Делается операция ИСКЛЮЧАЮЩЕЕ ИЛИ регистра CRC и полиномиального числа A001 hex.
5. Шаги 3 и 4 повторяются восемь раз.
6. Повторяются шаги со 2 по 5 для следующего сообщения. Это повторяется до тех пор пока все байты сообщения не будут обработаны.
7. Финальное содержание регистра CRC и есть контрольная сумма.
РАЗМЕЩЕНИЕ CRC В СООБЩЕНИИ
При передаче 16 бит контрольной суммы CRC в сообщении, сначала передается младший байт, затем старший. Например, если CRC равна 1241 hex :
Адрес | Функция | Счетчикк байт | Данные | Данные | Данные | Данные | CRC Ст. | CRC Мл. |
41 | 12 |
ПРИМЕР
Пример функции на языке C реализующей генерацию CRC приведен ниже. Все возможные величины CRC загружены в два массива. Один массив содержит все 256 возможных комбинаций CRC для старшего байта поля CRC, другой массив содержит данные для младшего байта. Идексация CRC в этом случая обеспечивает быстрое выполнение вычислений новой величины CRC для каждого нового байта из буфера сообщения.
Функция принимает два аргумента:
unsigned char *puchMsg; /* Указатель на буфер */
unsigned short usDataLen; /* Количество байтов в буфере */
Функция возвращает CRC как тип unsigned short.
static unsigned char auchCRCHi[] = { 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, 0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01, 0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80, 0x22,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01, 0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, 0x40,0x01,0xC0,0x80,0x41,0x00,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01, 0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40
}
static char auchCRCLo[] = { 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05, 0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA, 0xCB,0x0B,0xC9,0x09,0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA, 0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15, 0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,0xF0, 0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35, 0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B, 0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA, 0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27, 0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60, 0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64, 0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB, 0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE, 0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,0x77,0xB7, 0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91, 0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54, 0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99, 0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E, 0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,0x44,0x84,0x85,0x45,0x87,0x47,0x46, 0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40
}
unsigned short CRC16(puchMsg, usDataLen)
unsigned char *puchMsg;
unsigned short usDataLen;
{
unsigned char uchCRCHi = 0xFF;
unsigned char uchCRCLo = 0xFF;
while (usDataLen--)
{
uIndex = uchCRCHi
*puchMsg++;
uchCRCHi = uchCRCLo
auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex];
}
return (uchCRCHi << 8 | uchCRCLo);
}