Сакральный алгоритм расчёта CRC16, описанный в литературе и связанный с побитовым сдвигом, плохо вписывается в формат вычислительных возможностей ПЛК и МК. Во-первых, постольку, поскольку его реализация отнимает изрядный объем вычислительных ресурсов вышеозначенных устройств, во-вторых, потому что в ходе такого расчета существенно растягивается время скана программы по причине того, что, вследствие словной или байтовой организации аккумулятора арифметико-логического устройства, результирующие битовые операции со словами/байтами в нём выполняются гораздо дольше операций со словами/байтами целиком, а в отдельных устройствах эти операции и вовсе не поддерживаются, тогда как алгоритм подразумевает выполнение восьми циклов с такими операциями.
В целях сокращения объема вычислений и, как следствие, времени сканирования при обработке CRC, часто применяется иной алгоритм — табличный, когда таблица масок рассчитывается и заполняется единожды в первом скане программы. Тем не менее, и этот способ не лишён недостатка, ибо также потребляет ресурсы. 256 байт (или аналогичное количество двухбайтных слов), порою, отнюдь не лишние.
А можно ли видоизменить алгоритм расчёта CRC таким образом, чтобы отказаться от применения побитовых сдвигов и таблиц? Безусловно, да. Достаточно лишь внимательно приглядеться к алгоритму с побитовым сдвигом.
Напомню его суть:
- осуществляется сложение по модулю 2 очередного байта массива посылки с младшим байтом двухбайтной CRC;
- осуществляется ациклический сдвиг CRC на один бит от старшего 15-го разряда к младшему, нулевому, с выдвижением младшего бита, при этом старший разряд обнуляется;
- если значение выдвинутого бита единичное, выполняется сложение CRC по модулю 2 c полиномом 16#A001.
- шаги 2 и 3 повторяются ещё 7 раз.
Почему это реализовано так, а не иначе? Да потому, что такая алгоритмизация представлялась наиболее подходящей для реализации посредством аппаратной логики.
Внимательно взглянув на этот алгоритм, нетрудно обнаружить, что на самом-то деле мы имеем дело с циклическим побитовым сдвигом слова. За его цикличность отвечает старший бит полинома. В результате, значение старшего битового разряда CRC после каждого сдвига идентично значению выдвинутого младшего. Таким образом, при осуществлении циклического побитового сдвига, полином, с которым затем необходимо производить сложение по модулю 2, трансформируется в 16#2001.
Подобных сдвигов выполняется восемь… Проще говоря, в глобальном плане имеет место перемена местами младшего байта CRC со старшим её байтом. А это наводит на мысль, что, после сложения по модулю 2 очередного байта массива посылки с младшим байтом CRC, достаточно поменять местами младший и старший байт CRC, а затем, последовательно проанализировав восемь бит старшего её байта, начав с младшего его разряда, восьмого, произвести сложение СRC по модулю 2 c известными константами, предопределёнными значением полинома, значение которого для Modbus CRC16, как уже указано выше, эквивалентно 16#2001.
Итоговый алгоритм для учёта в CRC очередного байта массива посылки выглядит следующим образом:
Осуществляется сложение по модулю 2 очередного байта массива посылки с младшим байтом двухбайтовой CRC, после чего младший и старший байт CRC меняются местами;
- Если значение 8-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#0240;
- Если значение 9-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#0480;
- Если значение 10-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#0900;
- Если значение 11-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#1200;
- Если значение 12-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#2400;
- Если значение 13-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#4800;
- Если значение 14-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#9000;
- Если значение 15-го бита СRC единичное, выполняется её сложение по модулю 2 с константой 16#2001, расчёт окончен.
Преимущества такого способа расчёта:
1) По сравнению с алгоритмом побитового сдвига:
а) предложенный алгоритм позволяет избавиться от команд вложенного цикла FOR-NEXT и команд побитового сдвига в таком цикле, при том, число количество исполняемых команд сложения по модулю 2 сохраняется неизменным;
б) в контроллерах c поддержкой команды SWAP, восьмикратный побитовый сдвиг CRC заменяется единственной командой, а в контроллерах, такую команду не поддерживающих, — одной или двумя командами пересылки, входящими в число базовых команд контроллера и отнимающими минимальное время;
2) По сравнению с табличным методом расчёта, этот метод не нуждается в выделении места в памяти данных под таблицу, в её предварительном заполнении, в выборке соответствующей маски из таблицы с последующим ее наложением на байт CRC.
Проработка предложенного алгоритма расчёта СRC16 изначально велась для ПЛК Mitsubishi моделей FX3S/3G, не поддерживающих инструкций расчёта СRC, инструкций побитового сдвига и перемены местами байт в слове, между тем, предельное суммарное время расчета СRC с применением указанного алгоритма для массива посылки, состоящего из 128 байт, не превышает 2,4мс.
Автор: AssemblerKing