Протокол LinkBell
предназначен для организации передачи небольших объёмов информации в сетях устройств, содержащих в своём составе микроконтроллеры и компьютеры.
К сожалению сайт, от куда я в своё время скопировал описание протокола я найти не смог. Поэтому располагаю эти материалы у себя. Оригинальные страницы
(с) Michael G. Belousoff, mickbell@mail.ru
Официальное описание
Протокол LinkBell
предназначен для организации передачи небольших объёмов информации в сетях устройств, содержащих в своём составе микроконтроллеры и компьютеры.
Протокол LinkBell
относится к протоколам пакетного типа, то есть подлежащая передаче информация разбивается на дискретные блоки (кадры), сопровождаемые служебной информацией.
Протокол LinkBell
является байт-ориентированным, информация передаётся байтами последовательно с обрамлением старт-бита и одного стоп-бита.
Особенность сигнала, формируемого протоколом LinkBell: в любом месте сигнала подряд следует не более двух одинаковых битов, а число нулей равно числу единиц на любом промежутке времени длиной не менее байта. Протокол LinkBell обеспечивает прозрачность передачи данных.
Ограничения
Сетевой идентификатор (адрес) любого устройства представлен числом длиной 2 байта, старший бит адреса устройства должен быть всегда равен нулю. Адрес 0000h
запрещён, адрес 7FFFh
- широковещательный. Остальные значения могут быть использованы. Таким образом, в одной сети может быть адресовано до 32766
устройств.
Протокол LinkBell обеспечивает возможность ретрансляции передаваемых данных. Список сетевых идентификаторов (адресов) ретрансляторов может включать не более чем 5
ретрансляторов.
Уровни протокола
В рамках протокола LinkBell задействовано 4
уровня из семи, предусмотренных семиуровневой моделью протокола.
Прикладной уровень
Информация прикладного уровня - информация, подлежащая доставке от источника к приёмнику. Протокол LinkBell обеспечивает прозрачность передачи информации, то есть она может представлять собой любое количество байтов (реально оно ограничено возможностями аппаратуры), а каждый байт может принимать любое значение.
Сетевой уровень
На сетевом уровне указывается сетевой идентификатор (адрес) получателя информации прикладного уровня, а также (при необходимости) маршрут ретрансляции, то есть список сетевых идентификаторов (адресов) устройств, которые должны доставить информацию получателю. Протокол LinkBell предусматривает только последовательную ретрансляцию.
Формат сетевого уровня следующий: первые несколько (от 6
до 16
) байтов представляют собой заголовок сетевого уровня, за ним следует информация прикладного уровня. Заголовок состоит из следующего (в порядке следования):
- один байт - длина заголовка в байтах;
- один байт - флаги (в данной версии протокола LinkBell флаги не определены, значение байта флагов должно быть равно 00h);
- два байта - сетевой идентификатор устройства-получателя;
- два байта - сетевой идентификатор устройства-отправителя;
далее следует список ретрансляторов (количеством не более 5
), сетевой идентификатор каждого занимает два байта. Список начинается с последнего (самого ближнего к получателю) ретранслятора, а заканчивается первым (самым ближним к отправителю информации).
Значения всех сетевых идентификаторов могут быть в диапазоне от 1
до 32766
(в шестнадцатиричном виде от 0001h
до 7FFEh
), то есть старший бит адреса всегда должен быть нулевым. Единица в старшем бите адреса означает, что уазанный адрес является групповым. В данной версии протокола LinkBell групповая адресация не поддерживается.
Сетевой идентификатор 32767
(7FFFh
) - широковещательный адрес, то есть пакет с этим адресом получателя должен быть принят всеми устройствами данной сети. Сетевой идентификатор 0
(0000h
) - адрес пустого устройства, этим значением допускается подменять адреса в списке ретрансляторов по мере прохождения пакета через ретрансляторы.
Все адреса размещаются в заголовке, начиная со старшего байта.
Канальный уровень
Информация канального уровня, называемая кадром, готовится следующим образом. Информация сетевого уровня делится на блоки по 16 байт
. Каждый (в том числе последний, который может быть длиной менее 16 байт
) блок защищается кодом CRC16
, определяемым по полиному X16+X15+X2+X0
, или (в виде двоичного значения) 11000000000000101b
.
Перед вычислением переменная CRC
должна быть инициализирована значением, равным (FFFFh-SYSID
), где SYSID
(двухбайтовое число) - идентификатор сети. Для проводных сетей значение идентификатора сети устанавливается равным нулю, для радиосетей - уникальному (отличному от других сетей, использующих протокол LinkBell) числу, начиная от 1
. В смешанных сетях (часть сети - радиоканальная, часть - проводная) идентификатор сети устанавливается как в радиосетях, то есть ненулевой. Если в сети исключается взаимное (с другими сетями) проникновение сигналов, то для неё идентификатор сети устанавливается равным нулю.
Процедура расчёта CRC
(за основу взято описание процедуры расчёта CRC
из описания протокола [[ModBus]]):
- Подготовить значение полинома: удалить старший бит полинома и переставить остальные биты в обратной последовательности, получив таким образом число
1010000000000001b
=A001h
. - Загрузить 16-разрядный регистр числом (
FFFFh-SYSID
). - Выполнить операцию XOR над первым байтом данных и старшим байтом регистра. Поместить результат в регистр.
- Сдвинуть регистр на один разряд вправо.
- Если выдвинутый вправо (из регистра) бит - единица, то выполнить операцию
XOR
между регистром и значением полинома (A001h
). - Повторять шаги 3 и 4 до тех пор, пока не будут выполнены 8 сдвигов регистра.
- Выполнить операцию XOR над следующим байтом данных и регистром.
- Повторять шаги 4…7 до тех пор, пока не будет выполнена операция
XOR
над всеми байтами и регистром. - Содержимое регистра представляет собой двухбайтовое значение
CRC
.
Здесь XOR
означает операцию побитового исключающего ИЛИ.
Двухбайтовое значение CRC передаётся начиная со старшего байта. Порядок следования битов в байтах CRC аналогичен порядку передачи любых других байтов, то есть начиная с младшего бита. В отличие от общепринятого положения, код CRC передаётся перед защищаемым блоком.
Подготовленная таким образом информация далее обрабатывается следующим образом. Каждый байт разбивается на два ниббла((тетрады, последовательности из четырёх битов)) - старший и младший, после чего каждый ниббл кодируется байтом в соответствии со следующим:
Значение ниббла | Значение байта |
---|---|
0h | 55h |
1h | 56h |
2h | 59h |
3h | 5Ah |
4h | 65h |
5h | 66h |
6h | 69h |
7h | 6Ah |
8h | 95h |
9h | 96h |
Ah | 99h |
Bh | 9Ah |
Ch | A5h |
Dh | A6h |
Eh | A9h |
Fh | AAh |
Байт кодируется двумя байтами, причём вначале следует байт, соответствующий старшему нибблу, затем - младшему.
Перед полученной таким образом последовательностью байтов помещается маркер начала кадра - байт, значение которого 2Bh, после неё – маркер конца кадра - байт, значение которого 4Bh.
Общая длина кадра не должна превышать значения, установенного для конретного устройства.
Физический уровень
Перед передачей кадра может передаваться преамбула – повторяющаяся последовательность из байтов со значениями B2h
и 4Dh
. Длина преамбулы определяется временем выхода передающих и приёмных устройств на рабочий режим, но не должна быть короче четырёх указанных последовательностей, то есть восьми байтов. В сетях, в которых отсутствуют шумы и помехи в отсутствие сигнала, а также между кадрами, идущими без промежутка, преамбулу разрешается не передавать. Допускается в качестве преамбулы применять и другие значения байтов, если они не совпадают со значениями байтов, кодирующих нибблы, а также со значениями маркеров начала и конца кадра.
Каждый байт передаётся в обрамлении старт-бита и одного стоп-бита. Значение старт-бита - нуль, стоп-бита - единица. Байт передаётся начиная с младшего бита. Количество битов в байте - 8, бит контроля чётности не передаётся. Скорость передачи информации определяется для каждой сети, исходя из возможностей канала связи, и в процессе работы не меняется.
Физическая реализация каналов связи может быть любой, позволяющей организовать передачу последовательных данных.
Контроль валидности информации
Устройство, осуществляющее приём информации, производит проверку на канальном уровне:
- каждого байта, находящегося между маркерами начала и конца кадра, на соответствие их значениям, указанным в таблице;
- совпадения значения
CRC16
, подсчитанного для каждого полного и неполного 16-байтного блока, со значением, переданным перед этим блоком; - максимального количества байтов, находящихся между маркерами начала и конца кадра.
Кадр, не удовлетворяющий хотя бы одному условию, считается повреждённым и не должен обрабатываться.
Комментарии к официальному описанию протокола LinkBell
Протокол LinkBell предназначен для применения в устройствах, содержащих микроконтроллеры, и поэтому не должен требовать для работы значительных ресурсов, особенно памяти. С другой стороны, он должен выполнять задачу, возлагаемую на протокол - “прозрачно” передать информацию от отправителя к получателю по имеющимся линиям связи. Нередко линии связи накладывают ограничение на сигнал: например, независимость постоянной составляющей сигнала от передаваемой информации, или узкий частотный диапазон. Когда такие требования есть, может применяться, например, кодирование типа //“Манчестер-2”//. Сигнал, формируемый с применением протокола LinkBell, этим требованиям удовлетворяет. Разумеется, ничего не даётся бесплатно, и расплачиваться приходится в два раза более низкой пропускной способностью канала при заданной скорости передачи битов. Впрочем, это же характерно и для “Манчестера-2”. Для приёма и передачи информации можно применять //UART// - приёмопередатчик последовательных данных, имеющийся в большинстве микроконтроллеров, а также //COM-порт// компьютера. Это упрощает реализацию протокола в устройствах.
Коды CRC для блоков по 16 байтов определяются по методу и с применением образующего полинома, взятых из описания протокола [[Modbus]] RTU. Порядок битов в байтах кода CRC соответствует порядку битов в остальных байтах. Код CRC
так же, как адреса устройств, передаётся начиная со старшего байта. Это вызвано желанием упростить отладку программного обеспечения пользователем, ведь такой порядок привычнее для восприятия. Процедура подсчёта CRC может быть выполнена, например, так (пример функции на языке Си):
#define CRC_POLYNOME 0xA001 //corresponds to X^16+X^15+X^2+X^0
unsigned int common_flags;
unsigned int CalcCrc(unsigned int crc, unsigned char data)
{
unsigned int result;
char i;
result=crc^(unsigned int)data;
for (i=0;i<8;i++)
{
if (result%2) common_flags|=(1<<CRC_AUX_FLAG);
else common_flags&=~(1<<CRC_AUX_FLAG);
result=result>>1;
if (common_flags&(1<<CRC_AUX_FLAG))
result=result^CRC_POLYNOME;
}
return result;
}
Здесь common_flags
- глобальная переменная, один бит которой (CRC_AUX_FLAG
) выделен для потребности функции CalcCrc
.
Перед расчётом CRC
для принятого или передаваемого блока байтов следует инициализировать переменную crc
значением, равным FFFFh
для проводных сетей или (FFFFh-SYSNO
) для радиосетей. SYSNO
- идентификатор сети, его значение у сетей, в которых возможно попадание сигнала из одной в другую, должно различаться. Тогда данные из “чужой” сети не будут обработаны, так как подсчитанный код CRC
не совпадёт с переданным. После инициализирования переменной crc
следует вызвать функцию CalcCrc
столько раз, сколько байтов защищается кодом CRC
.
Контрольный пример. Расчёт CRC16
для двух байтов 02h
и 07h
, если SYSNO=0
, должен дать значение crc=1241h
, расчёт CRC16 для байтов 02h
, 07h
, 41h
и 12h
должен дать значение crc=0000h
.
Кодирование информации сетевого уровня на канальном призвано, во-первых, обеспечить свойства сигнала, подобные кодировке “Манчестер-2” (описанные выше), во-вторых, получить значения байтов для маркеров начала и конца кадра и преамбулы, отличающиеся от любых значений байтов внутри кадра. Кодирование нибблов в байты выполняется так, что из двух идущих подряд битов второй является инверсией первого:
Разряд ниббла | Разряды байта |
---|---|
N0 | B1 = N0, B0 = /N0((Здесь “/” означает инверсию значения бита.)) |
N1 | B3 = N1, B2 = /N1 |
N2 | B5 = N2, B4 = /N2 |
N3 | B7 = N3, B6 = /N3 |
Первым кодируется старший ниббл, затем младший, это требуется для упрощения восприятия кодированной последовательности программистом при отладке. Значения, выбранные для маркеров начала и конца кадров и преамбулы, обладают свойствами любого байта канального уровня: наличие одинакового количества нулей и единиц, а также наличие не более двух идущих подряд битов с одинаковым значением.
Передача преамбулы преследует две цели. Во-первых, нельзя передавать информацию сразу же после включения передатчика, ведь и он, и иногда какие-то устройства в приёмнике должны выйти на установившийся режим, а на это требуется определённое время, до десятков и даже сотен миллисекунд. Во-вторых, в некоторых каналах имеется или возможен шум, который UART
контроллера может воспринимать как биты сигнала, в том числе старт- и стоп-биты. После подачи в канал осмысленной информации UART
может не найти старт-бит. Поэтому в начале передачи следует подать такую последовательность единиц и нулей, чтобы UART
смог найти в ней правильное положение старт- и стоп-битов, то есть синхронизироваться. Принятая последовательность байтов преамбулы (B2h
и 4Dh
) обладает свойством самосинхронизации на периоде в 4 повтора этих кодов, то есть после передачи B2h 4Dh B2h 4Dh B2h 4Dh B2h 4Dh
//UART// готов к приёму байтов.
В некоторых случаях возможен выбор других значений байтов преамбулы. Это может оказаться необходимым, например, в случаях, когда UART приёмного устройства испытывает затруднения, выполняя синхронизацию по байтам преамбулы. В этом случае рекомендуется значение байтов преамбулы F0h. Разумеется, в этом случае речи об узкополосности сигнала идти уже не может.
Пример сборки пакета
Исходные данные: пусть в сети с идентификатором 10 (000Ah) от устройства с идентификатором 1000
(03E8h
) требуется передать устройству с идентификатором 100
(0064h
) число типа unsigned long
, равное 3735928559
, или DEADBEEFh
:-) (tnx to Oleksandr Redchuk). Ретрансляция не требуется.
Прикладной уровень: число записывается 4 байтами: EFh BEh ADh DEh
.
Сетевой уровень: добавляется заголовок длиной 6 байтов. Получается:
06h 00h 00h 64h 03h E8h EFh BEh ADh DEh
Канальный уровень: для указанной последовательности значение кода CRC16, инициализированного значением FFFFh - 000Ah = FFF5h, равно E25Dh.
Таким образом, информация перед преобразованием нибблов принимает вид:
E2h 5Dh 06h 00h 00h 64h 03h E8h EFh BEh ADh DEh
Далее происходит преобразование каждого ниббла по таблице, после чего получается:
A9h 59h 66h A6h 55h 69h 55h 55h 55h 55h 69h 65h 55h 5Ah A9h 95h A9h AAh 9Ah A9h 99h A6h A6h A9h
После того, как эта последовательность байтов заключена внутрь маркеров начала и конца кадров и предварена преамбулой из четырёх двухбайтовых комбинаций, получается последовательность, годная к передаче, а именно:
B2h 4Dh B2h 4Dh B2h 4Dh B2h 4Dh 2Bh A9h 59h 66h A6h 55h 69h 55h 55h 55h 55h 69h 65h 55h 5Ah A9h 95h A9h AAh 9Ah A9h 99h A6h A6h A9h 4Bh
comments powered by Disqus