|
|
  |
Помехозащищенный RS-485 |
|
|
|
Nov 26 2015, 20:32
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(Сергей Борщ @ Nov 26 2015, 21:08)  Так подключите MAX485 прямо к FT232R или CP2103 или возьмите готовый переходник, а всю обработку делайте на компьютере. Зачам там еще МК? А этот преобразователь, он же только данные отправляет? А счетчик USB фрейма?
|
|
|
|
|
Nov 26 2015, 21:17
|

pontificator
     
Группа: Свой
Сообщений: 3 055
Регистрация: 8-02-05
Из: страны Оз
Пользователь №: 2 483

|
Цитата(Atlantis- @ Nov 26 2015, 22:44)  А мне удобнее COBS преобразование сделать в датчике, а в МК1 добавить байт - номер датчика. А почему датчик не может сразу добавить свой номер и CRC, а потом закодировать сообщение? Добавить байт (т.е номер датчика) к уже закодированному COBS сообщению - вообще-то проблема, даже если этот номер не равен 0. Потому что в корректной реализации при раскодировании сообщения на месте этого байта должен быть или 0 (это значит, что сообщение закончено), или число последующих ненулевых байт в сообщении. Конечно, можно наставить костылей, например, если длина сообщения фиксирована, то последний байт обрабатывать не так, как остальные. Только нехорошо это. Цитата(Atlantis- @ Nov 26 2015, 22:44)  почему? данных же мало, всего то 12 байт. Потому иначе намного больше вероятность, что что среди ложных сообщений будет такое, что пройдет проверку. Цитата(Atlantis- @ Nov 27 2015, 07:02)  А этот преобразователь, он же только данные отправляет? А счетчик USB фрейма? SOF-ы автоматически считаются "на нижнем уровне". А накой вам этот счетчик?
|
|
|
|
|
Nov 26 2015, 22:22
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(=AK= @ Nov 27 2015, 00:17)  А почему датчик не может сразу добавить свой номер и CRC, а потом закодировать сообщение? а как? датчик же не знает какой у него номер. все датчики одинаковые, воткнул в 1-е гнездо, значит датчик №1, если в о 2-е, то №2 Цитата(=AK= @ Nov 27 2015, 00:17)  SOF-ы автоматически считаются "на нижнем уровне". А накой вам этот счетчик? Для синхронизации. У меня в USB МК отправляется сначала счетчик фрейма (2 байта), потом данные
|
|
|
|
|
Nov 27 2015, 03:16
|

pontificator
     
Группа: Свой
Сообщений: 3 055
Регистрация: 8-02-05
Из: страны Оз
Пользователь №: 2 483

|
Цитата(Atlantis- @ Nov 27 2015, 08:52)  а как? датчик же не знает какой у него номер. все датчики одинаковые, воткнул в 1-е гнездо, значит датчик №1, если в о 2-е, то №2 Тогда пусть все датчики ставят в нужное место номер 1, кодируют и отправляют. А ваш МК1 просто заменит номер 1 в этом месте на действительный номер датчика. Если он не будет равен 0, то на COBS это никак не повлияет. Однако при этом придется обойтись без CRC на все сообщение, поскольку CRC надо добавлять до того, как кодировать по COBS. Можно, конечно, CRC считать в датчике, а "1" добавлять потом, но при этом номер датчика не будет охвачен CRC. Это не очень хорошо, но работать будет. Цитата(Atlantis- @ Nov 27 2015, 08:52)  Для синхронизации. У меня в USB МК отправляется сначала счетчик фрейма (2 байта), потом данные Какой счетчик? Взятый в тот момент, когда вы получили сообщение, или в тот момент когда вы его сформировали в буфере для отправки? Неужто вы думаете, что он будет отправлен в том же фрейме? Ведь вы же BULK используете, а он асинхронный. Специфиkация USB: 5.12.4.1.1 Asynchronous Asynchronous endpoints cannot synchronize to SOF or any other clock in the USB domain.
|
|
|
|
|
Nov 27 2015, 07:23
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(=AK= @ Nov 27 2015, 06:16)  Тогда пусть все датчики ставят в нужное место номер 1, кодируют и отправляют. А ваш МК1 просто заменит номер 1 в этом месте на действительный номер датчика. Если он не будет равен 0, то на COBS это никак не повлияет.
Однако при этом придется обойтись без CRC на все сообщение, поскольку CRC надо добавлять до того, как кодировать по COBS. Можно, конечно, CRC считать в датчике, а "1" добавлять потом, но при этом номер датчика не будет охвачен CRC. Это не очень хорошо, но работать будет. Хорошая идея, я подумаю... Нет смысла охватывать номер датчика CRC, он же все равно будет переписан. Хотя может быть испорчен дальше, но дальше все таки дифф пара RS-485. Цитата(=AK= @ Nov 27 2015, 06:16)  Какой счетчик? Взятый в тот момент, когда вы получили сообщение, или в тот момент когда вы его сформировали в буфере для отправки? Неужто вы думаете, что он будет отправлен в том же фрейме? Ведь вы же BULK используете, а он асинхронный.
Специфиkация USB:
5.12.4.1.1 Asynchronous Asynchronous endpoints cannot synchronize to SOF or any other clock in the USB domain. я использую изохронный
|
|
|
|
|
Nov 27 2015, 10:13
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(=AK= @ Nov 27 2015, 12:34)  А вы этот номер передавайте в самом байте дважды: в младших 4 битах сам номер, а в старших четырех битах - его инверсию. Так вы любые одиночные ошибки в этом байте обнаружите. Понятно, спасибо. А еще Вы писали, что в Википедии "сложный" вариант перекодировки COBS. Где тогда можно простой посмотреть?
|
|
|
|
|
Nov 27 2015, 10:58
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Опять товарища =AK= куда-то понесло - предложил для RS485 с шумами в паузах протокол канального уровня, позволяющий отловить конец пакета, но не его начало после шума. А потом еще предложил всунуть между канальным и физическим уровнями кусок транспортного (номер пакета). Аплодисменты. Atlantis-, почитайте про сетевую модель OSI. У вас есть физический уровень - RS485. Поверх него вы строите канальный, отвечающий за разбивание потока вашей информации на пакеты и контрольную сумму. COBS тут не подходит по указанной выше причине - малейший шум в паузе и пакет вы потеряли. Посмотрите на SLIP, реализуйте что-то похожее, но с отметкой не только конца, но и начала пакета. Далее строите сетевой уровень - добавляете в протокол адреса ваших датчиков. Если у вас каждый датчик воткнут в свой отдельный интерфейс - сетевой уровень на этом участке вам не нужен. Далее сверху накладываете транспортный уровень - добавляете в протокол номер пакета. И сверху водружаете прикладной уровень - собственно ваши данные. При передаче идете по модели сверху вниз: берете данные (прикладной уровень), добавляете к ним номер пакета(транспортный уровень), добавляете адрес(сетевой уровень), считаете контрольную сумму и обкладываете все это байт-стаффингом (канальный уровень, SLIP-подобные протоколы позволяют делать это побайтно, прямо в процессе передачи, не видя пакета целиком) и в конце передаете получившийся пакет данных через UART в RS-485 (физический уровень). На приемной стороне вы двигаетесь по модели снизу вверх: принимаете байты из RS-485 (физический уровень), обрабатывая SLIP-подобный протокол убираете байт-стаффинг и выделяете начало/конец пакета, считаете контрольную сумму (канальный уровень), далее отделяете и обрабатываете адрес (сетевой уровень), следом номер пакета (транспортный уровень) и в результате получаете ваши исходные данные очищенные от всей этой шелухи, т.е. в том виде, в котором эти данные поступили из прикладного уровня на передающей стороне. И все изменения данных вы делаете только двигаясь по этой цепочке. Приняли вы на физическом уровне пакет не содержащий адреса, надо вам добавить в него адрес - вы очистили пакет от обертки канального уровня (остался пакет транспортного уровня), добавли к этому пакету транспортного уровня адрес, снова завернули получившийся пакет сетевого уровня в обертку канального уровня и передали по физическому.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 27 2015, 11:05
|

pontificator
     
Группа: Свой
Сообщений: 3 055
Регистрация: 8-02-05
Из: страны Оз
Пользователь №: 2 483

|
Цитата(Atlantis- @ Nov 27 2015, 20:43)  в Википедии "сложный" вариант перекодировки COBS. Где тогда можно простой посмотреть? "а это уж вы сами" © Щербаков Цитата(Сергей Борщ @ Nov 27 2015, 21:28)  предложил всунуть между канальным и физическим уровнями кусок транспортного (номер пакета).
COBS тут не подходит по указанной выше причине - малейший шум в паузе и пакет вы потеряли. К сожалению, вы ничего не поняли, даже какой-то "номер пакета" вдруг выдумали и приплели ни к селу ни к городу. Никакой шум в паузе не повлияет на прием пакета из-за того, что передатчик передает два 0 до начала пакета. После паузы приемник гарантировано получит хотя бы один 0, после чего "шумовой" пакет будет проверен и отвергнут из-за несовпадения CRC, а также из-за несоответствия правилам COBS. А следующий сразу же вслед за этим истинный пакет будет принят без искажений.
|
|
|
|
|
Nov 27 2015, 15:16
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Сергей Борщ @ Nov 27 2015, 12:58)  Посмотрите на SLIP, реализуйте что-то похожее, но с отметкой не только конца, но и начала пакета. SLIP использует разделитель фреймов, который используется и в начале и в конце пакета и в любом количестве. QUOTE (=AK= @ Nov 27 2015, 13:05)  Никакой шум в паузе не повлияет на прием пакета из-за того, что передатчик передает два 0 до начала пакета. Совет неверный. Нужен один 0xFF.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 27 2015, 18:30
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(zltigo @ Nov 27 2015, 20:16)  Совет неверный. Нужен один 0xFF. Что-то мне эта тема напомнила... Ага, вот эту тему. Там долго выясняли способ гарантированно восстановить битовую синхронизацию при непрерывной передаче потока. =AK= описал применяемый им способ посылки двух подряд символов 0x0F, при котором второй символ гарантированно ловится. Потом выяснилось, что это не так, по крайней мере, не со всеми контроллерами UART. Символ же 0xFF, переданный перед началом пакета, гарантированно восстановит битовую синхронизацию:
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 27 2015, 20:05
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(zltigo @ Nov 27 2015, 18:16)  SLIP использует разделитель фреймов, который используется и в начале и в конце пакета Цитата Как-то неразумно называть признак начала кадра именем "END". RFC 1055: Цитата The SLIP protocol defines two special characters: END and ESC. END is octal 300 (decimal 192) and ESC is octal 333 (decimal 219) not to be confused with the ASCII ESCape character; for the purposes of this discussion, ESC will indicate the SLIP ESC character. To send a packet, a SLIP host simply starts sending the data in the packet. If a data byte is the same code as END character, a two byte sequence of ESC and octal 334 (decimal 220) is sent instead. If it the same as an ESC character, an two byte sequence of ESC and octal 335 (decimal 221) is sent instead. When the last byte in the packet has been sent, an END character is then transmitted. Про признак начала ничего не сказано.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 27 2015, 20:44
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Сергей Борщ @ Nov 27 2015, 22:05)  Как-то неразумно называть признак начала кадра именем "END". Это не ко мне  . В реальные реализации протокола ПРАВИЛЬНО отрабатывают и одиночные разделители и начало-конец и любое количество "END" в качестве разделителей. Что совершенно ествественно и соответственно никаких "реализуйте что-то похожее, но с отметкой не только конца, но и начала пакета" не требуется. QUOTE (Сергей Борщ @ Nov 27 2015, 22:05)  RFC 1055 Про признак начала ничего не сказано. Из этого-же RFC: CODE /* SEND_PACKET: sends a packet of length "len", starting at * location "p". */ void send_packet(p, len) char *p; int len; {
/* send an initial END character to flush out any data that may * have accumulated in the receiver due to line noise */ send_char(END);
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|