Перейти к содержанию
    

Зависание микроконтроллера

Есть более простой способ решающий эту проблему - байт стаффинг.

Никаких задержек и никаких лишних включений "перед отправкой пакета" не потребуется. Не потребуется также отмерять точные интервалы.

Нет, не работает. В ситуации, когда помеха запускает UART ложным старт-битом незадолго до байта заголовка (soh), ваш пакет бyдет испорчен, поскольку заголовочный байт не будет принят. Значит, при определенном уровне помех, когда ложный запуск происходит часто, связи вообще не будет, все пакеты бyдут испорчены. Правильный протокол в этой ситуации будет работать как ни в чем не бывало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В ситуации, когда помеха запускает UART ложным старт-битом незадолго до байта заголовка (soh), ваш пакет бyдет испорчен, поскольку заголовочный байт не будет принят.

Не будет ничего испорчено. Последовательность такая:

Передатчик посылает 1-2 байта преамбулы 0xFF, открывающую стаффинг последовательность, RTU пакет, закрывающую стаффинг последовательность, и байт преамбулы. Использую этот подход в радио каналах и серьезно задумываюсь над переносом этого протокола в 485 сети потому что жесткие времянки модбаса слегка достают уже (при том что против формата RTU пакетов я ничего не имею - формат грамотный).

Плюсы:

1. Передатчик волен вставлять любые паузы между символами (актуально когда хост - компьютер с не реал-тайм драйвером UART'a),

2. Четко выделяется начало и конец пакета, к обработке можно переходить немедленно после приема закрывающего флага, не нужно считать CRC в прерывании на слейве.

3. Опять же хост - тот же компьютер с не риалтайм приемником вместо непрогнозируемого таймаута четко распознает конец пакета - что уменьшает время реакции.

 

Минусы

Избыточность. (в худшем случае 2х кратное увеличение количества передаваемых данных на 1 пакет).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Передатчик посылает 1-2 байта преамбулы 0xFF, открывающую стаффинг последовательность

Если передатчик посылает всего 1 байт преамбулы 0xFF:

- Помеха, которая создаст ложный старт-бит незадолго до этого, запустит UART

- В момент прихода байтa преамбулы 0xFF, UART, находящийся где-то в середине приема байта, "не увидит" 0xFF, а увидит некий ложный байт. Пакет будет испорчен.

 

Если передатчик посылает 2 байтa преамбулы 0xFF, то ситуация лучше: первый байт может быть испорчен, но второй "прочистит" приемник, так что пакет будет принят правильно. Однако по затратам времени два байта преамбулы ничем не лучше паузы в 2 байт-интервала. Что же касается накладных расходов, то ваши затраты на парсенье эскэйп-последовательностей выглядят не меньшими, чем затраты на проверку тайм-аутов между байтами. Разница в основном в том, что вы парсите софтом, а тайм-ауты проверяются в основном железом (таймером). Поэтому вам нужно меньше таймеров, но более производительный проц. В принципе шило на мыло, примерно тож на тож получится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

- Помеха, которая создаст ложный старт-бит незадолго до этого, запустит UART

Для того, чтобы не оказаться в такой ситуации я использую простой приём - ведущий тоже слушает линию в т.ч. и при своей передаче. Т.е. приёмник USART ведущего так-же будет запущен перед тем, как он начнёт передавать. Применительно к RS485 получится, что переданный и самопринятый байты ведущего не будут совпадать. В этом случае передатчик прерывает свою передачу и начинает всё заново. Временные затраты в этом случае минимальны.

:bb-offtopic:

Но если вся сеть своя, и подключение чужих устройств не планируется, то есть НЕСРАВНЕННО ЛУЧШИЙ СПОСОБ - использование CAN-овских приёмопередатчиков. В этом случае приёмник может остановить передачу глючного пакета. Вообще при использовании CAN-овских приёмопередатчиков сплошные достоинства, и никаких недостатков - я когда-то давно эту тему поднимал. Кстати будет работать (не очень хорошо) сеть, где часть приёмопередатчиков RS485, а часть CAN.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для того, чтобы не оказаться в такой ситуации я использую простой приём - ведущий тоже слушает линию в т.ч. и при своей передаче. Т.е. приёмник USART ведущего так-же будет запущен перед тем, как он начнёт передавать. Применительно к RS485 получится, что переданный и самопринятый байты ведущего не будут совпадать. В этом случае передатчик прерывает свою передачу и начинает всё заново. Временные затраты в этом случае минимальны.

Это будет работать при условии, что помехи во всей сети совершенно одинаковы, что, в общем-то, совсем не очевидно, особенно при больших длинах кабеля и пр. Кроме того, ввиду разброса параметров (порогов срабатывания) приемников, это вообще-то требует их индивидуального отбора. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Однако по затратам времени два байта преамбулы ничем не лучше паузы в 2 байт-интервала.

 

Есть одна тонкость - если у вас безмозглый репитер (срабатывающий по старту), то удержание выхода в 1 заранее от начала посылки после репитера будет поломано - он же не умеет смотреть в будущее. Т.е. можно конечно добавить мозг репитеру и задержать пакет на время предварительного удержания, но иногда - это не выход (например, если надо обеспечить макс. быстродействие сети при ограниченной битовой скорости). Тут способ с двумя байтами 0xFF вне конкуренции, конечно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это будет работать при условии, что помехи во всей сети совершенно одинаковы, что, в общем-то, совсем не очевидно, особенно при больших длинах кабеля и пр.

Нет не так. Правильнее сказать так - это срабатывает не в 100% случаев. Но в случае не срабатывания этого приёма - сработает "классический" способ.

Кроме того, ввиду разброса параметров (порогов срабатывания) приемников, это вообще-то требует их индивидуального отбора. :)

Приёмники можно не подбирать - применительно к АВР можно проинициализировать USART ведущего с U2X=1, а ведомого с U2X=0. При этом приёмник ведущего начнёт приём при более коротком (на 10%) импульсе помехи. Ещё можно не ставить у ведущего подтягивающих резисторов и т.д.

 

Я вобщем-то и говорил, что такой способ был-бы вне конкуренции при использовании CAN-овских приёмопередатчиков. При этом приёмник, приняв помеху за стартовый бит, сам остановил-бы передачу ведущего. Но и при использовании RS485 результат лучше, чем при байт стаффинге и при передаче 1 перед передачей. Его можно ещё улучшить если параллельно приёмнику подать сигнал на вход прерывания или захвата.

 

А насчёт способа с двумя FF - он не будет работать при контроле четности (или нечётности?) т.к. бит чётности будет 0. И приёмник может до бесконечности принимать его за стартовый бит (если передатчик использует 1 стоп-бит).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть одна тонкость - если у вас безмозглый репитер (срабатывающий по старту)... Тут способ с двумя байтами 0xFF вне конкуренции.

Если помеха незадолго до начала пакета переключит такой репитер в нежелательное направление, то все 0xFF будут испорчены. То есть, использование такого репитера резко снижает помехоустойчивость сети - до уровня, обеспечиваемого непомехоустойчивыми протоколами, которым нужны растяжки. После чего спорить о преимуществах или недостатках того или иного помехоустойчивого протокола не имеет смысла, поскольку теряется сам смысл их использования.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если передатчик посылает всего 1 байт преамбулы 0xFF:

- Помеха, которая создаст ложный старт-бит незадолго до этого, запустит UART

- В момент прихода байтa преамбулы 0xFF, UART, находящийся где-то в середине приема байта, "не увидит" 0xFF, а увидит некий ложный байт. Пакет будет испорчен.

не будет пакет испорчен, так как приемник не ловит преамбулу. Преамбула используется для синхронизации. Приемник "ловит" (лучше сказать выделяет из потока мусора) только стаффинг последовательность.

Один байт 0xFF даст возможность приемнику правильно принять стаффинг последовательность, т.к. гарантируется высокий уровень (СТОП) в линии на протяжении минимум 9 битов.

 

Если передатчик посылает 2 байтa преамбулы 0xFF, то ситуация лучше: первый байт может быть испорчен, но второй "прочистит" приемник, так что пакет будет принят правильно.

Первый байт, а не второй "прочищает" приемник.

Если для устойчивого приема достаточно преамбулы в 1 байт, то два байта будет более чем достаточно.

Что же касается временных затрат на посылку преамбулы и стаффинг последовательности - да они имеют место быть, но см. выше, такой подход в некоторых случаях (мастер PC) наоборот повышает скорость обмена, за счет:

1. пресечения таймаутов между пакетами;

2. простого распознаваения конца пакета - упрощение rx flow-control'a;

 

+ сводится к нулю количество потерянных пакетов, из-за неверно сформированных таймаутов, когда одно из устройств сети работает под управлением не real-time ОС (например мастер ПК под Windows) и используются передатчики с FIFO большого объема, но не позволяющие разместить пакет целиком.

 

Тут способ с двумя байтами 0xFF вне конкуренции, конечно.

С одним 0xFF. AK просто не до конца смоделировал работу.

Пусть помеха включила приемник за 2 бита до инициализации преамбулы.

Тогда на линии будет следующий (12-ти битовый) фрейм:

 

0 x 0 1 1 1 1 1 1 1 1 1 [ стаффинг ]

x - неопределенный бит

после x начинается фрейм преамбулы 0xFF

 

приемник примет байт 0xFD/0xFC вместо 0xFF, и проигнорирует его, передатчик будет удерживать высокий уровень на линии т.к. передается 0xFF + 1(2)СТОП(а), и не даст приемнику начать прием до тех пор пока не сформируется СТАРТ бит стаффинг фрейма, т.о. в 485 сети достаточно всего лишь одного байта преамбулы.

 

Допустим искаженный байт 0xFF в результате воздейтсвия помехи совпадет с первым байтом открывающей стаффинг последовательности, но и в этом случае приемник приняв за ним такой же байт, и по условию "принято 0 байт данных" пакета, просто "переоткроет" прием пакета повторно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первый байт, а не второй "прочищает" приемник.

...

Допустим искаженный байт 0xFF в результате воздейтсвия помехи совпадет с первым байтом открывающей стаффинг последовательности, но и в этом случае приемник приняв за ним такой же байт, и по условию "принято 0 байт данных" пакета, просто "переоткроет" прием пакета повторно.

Нy вот, значит, все-таки второй байт "прочистит приемник", правда? А то, что этот байт у вас не равен 0xFF - это нюанс, о котором догадаться по вашим отрывочным сообщениям было трудно. Собственно, вам ничего не мешает старт-байт сделать равным 0xFF, чтобы не плодить лишние сущности, я-то подразумевал именно этот вариант.

 

Все равно, как я и говорил, в начале вам надо передать два служебных байта, что по времени займет как минимум два байт-интервала.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нy вот, значит, все-таки второй байт "прочистит приемник", правда? А то, что этот байт у вас не равен 0xFF - это нюанс, о котором догадаться по вашим отрывочным сообщениям было трудно. Собственно, вам ничего не мешает старт-байт сделать равным 0xFF, чтобы не плодить лишние сущности, я-то подразумевал именно этот вариант.

 

Все равно, как я и говорил, в начале вам надо передать два служебных байта, что по времени займет как минимум два байт-интервала.

Ок моя вина, сильно быстро пытался изложить суть.

Да, минимум два служебных байта, да займет два байт-интервала, но...

во первых, это ровно столько же сколько и по стандарту modbus, во вторых, не нужно никакого отдельного таймера для выдержки этого интервала. В третьих, не нужен межпакетный интервал, а по стандарту modbus этот интервал не так уж и мал - минимум 3.5 байтовый. Т.е. в идеале можно добиться более высоких скоростей чем на основе modbus rtu протокола, не теряя при этом в помехоустойчивости.

 

PS: за идею сделать старт байт равным 0xFF спасибо. Получится очень удобно, тем более что RTU пакет начинается с адреса устройства и можно просто наложить ограничения на количество адресов 0x00..0xFE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

во первых, это ровно столько же сколько и по стандарту modbus, во вторых, не нужно никакого отдельного таймера для выдержки этого интервала. В третьих, не нужен межпакетный интервал, а по стандарту modbus этот интервал не так уж и мал - минимум 3.5 байтовый.

В самом Модбасе стартовая пауза тоже равна 3.5 байт-интервала. Однако я не знаю причин, почему в Модбас-подобном протоколе нельзя было бы уменьшить межпакетную паузу до, скажем, одного или даже половины байт-интервала, а стартовую - скажем, до полутора байт-интервалов. После этого, с учетом того, что потери времени на байт-стаффинг отсутствуют, средняя скорость получится немного выше, чем в вашем варианте. Который, несомненно, обладает своими преимуществами. :a14:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...