Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Протокол modbus. Вопросы по интерфейсу
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Интерфейсы
Страницы: 1, 2
Phuntik
Здравствуйте.
На работе дали задание разработать интерфейс сообщений между устройствами на основе протокола Modbus.
Суть такова. Есть некоторое количество измерительных приборов, соединённых по RS-485. Нужно сделать так, чтобы с одного прибора можно было управлять другим - устанавливать режимы, принимать архивы измерений и т.д. За основу предложено взять протокол modbus.
Уже месяц сижу и туплю.
Вопросы:
1. Можно ли сделать так, чтобы любое устройство могло взять на себя роль главного?
2. Каким образом вообще передавать информацию главному? Через регистры, что ли?
3. С чего вообще начинать?
Подскажите, пожалуйста, ткните носом во что-нибудь готовое, описание какое-нибудь.
Протокол зачитал, но там, такое ощущение, всё привязано к конкретным контроллерам.
MrYuran
Правильный протокол - на modbus.org
Если нужно менять мастера, то модбас не катит. Скорее ProfiBUS
Информацию в модбасе можно передавать через регистры, койлы и файлы.
Phuntik
Цитата(MrYuran @ Oct 16 2008, 14:24) *
Если нужно менять мастера, то модбас не катит. Скорее ProfiBUS

Т.е. совсем не катит? Нельзя так сделать?
MrYuran
Цитата(Phuntik @ Oct 16 2008, 15:27) *
Т.е. совсем не катит? Нельзя так сделать?

Ну, всегда можно что-то сделать. Но это будет ваш собственный велосипед, не имеющий ничего общего с протоколом MODBUS (кроме формата пакетов). Стандартом передача "мастерства" не предусмотрена.
Andy Great
Цитата(MrYuran @ Oct 16 2008, 14:24) *
Если нужно менять мастера, то модбас не катит. Скорее ProfiBUS

ProfiBUS (ProfiBUS/DP по кр.мере) не мультимастер.
ЗЫ: А Модбас это и есть формат пакетов. Можно сделать пакет "передача мастера" плюс, на случай потерь, захват "мАстерства" по таймауту в зависимости от собственного адреса (ИД). В свое время интересовался мультимастерными сетями, некоторые решения были очень простыми.
MrYuran
Цитата(Andy Great @ Oct 17 2008, 11:56) *
ProfiBUS (ProfiBUS/DP по кр.мере) не мультимастер.

цитирую педию:
Цитата
PROFIBUS использует обмен данными между ведущим и ведомыми устройствами (протоколы DP и PA) или между несколькими ведущими устройствами (протоколы FDL и FMS). Требования пользователей к получению открытой, независимой от производителя системе связи, базируется на использовании стандартных протоколов PROFIBUS.

Цитата
Можно сделать пакет "передача мастера" плюс, на случай потерь, захват "мАстерства" по таймауту в зависимости от собственного адреса (ИД).

Можно, но тогда это будет "стандарты нестандартные, системы бессистемные"
Bovolk
Тоже поставили задачу прикрутить Modbus.
В описании протокола сказано, что в начале и конце сообщения должен быть интервал тишины, когда же подчиненный может начинать отвечать? Т.е. Мастер делает паузу 3.5, затем передает пакет и снова делает паузу 3.5. Подчиненному когда начинать делать стартовую паузу, сразу после окончания передачи CRC мастером или после его завершающей паузы 3,5?
ucMike
Наверное, главной проблемой станет борьба с коллизиями. В модбасе ведомые устройства молчат, как примерные ученики, пока не спросят.
Возможный вариант: гонять метку ведущего. Во всех устройствах выделить пару регистров. Первый - признак, что устройство хочет быть ведомым. Через некоторый интервал ведущий опрашивает все устройства. Если появились желающие, то пишет во второй регистр метку ведущего. Получил ответ - сам стал ведомым и тихо ждет своей очереди. Это уже было в TokenRing
Однако, может оказаться два ведущих или никого.

Другой вариант. Драйвер RS485 следит за линией и самостоятельно борется с ошибками. А Ethernet, особенно коаксильный вариант.

P.S. С PROFIBUS не знаком (не требовалось).
ucMike
Цитата(ucMike @ Dec 4 2008, 01:13) *
P.S. С PROFIBUS не знаком (не требовалось).


Упс. Profibus как раз.
defunct
Цитата(Bovolk @ Nov 16 2008, 13:01) *
Подчиненному когда начинать делать стартовую паузу, сразу после окончания передачи CRC мастером или после его завершающей паузы 3,5?

По завершающей паузе некоторые слейвы определяют границу пакета. (не все ж считают CRC на лету). Пауза между пакетами должна быть не менее 3.5. По приему CRC слейв может сразу же приступить к формированию ответа, но слать ответ в линию он должен не ранее чем через 3.5 сивольного интервала.
ukpyr
modbus plus - multimaster :
http://prodcs.ru/files/ModPlusDesignManual.pdf

можно сделать временнОе мультиплексирование, например мастер делает опрос узлов с периодом 5 сек, слейв может давать запросы между запросами мастера, со смещением 2.5 сек после запроса мастера.
koyodza
Цитата(defunct @ Jan 1 2009, 08:05) *
По завершающей паузе некоторые слейвы определяют границу пакета. (не все ж считают CRC на лету). Пауза между пакетами должна быть не менее 3.5. По приему CRC слейв может сразу же приступить к формированию ответа, но слать ответ в линию он должен не ранее чем через 3.5 сивольного интервала.

Довольно распространенное заблуждение насчет определения конца пакета путем подсчета CRC.
Стандарт однозначно определяет конец пакетов по таймауту (не менее 3,5 байтовых интервалов для скоростей ниже 19200 и 1,75 мсек для скоростей выше 19200).
Совсем не обязательно считать CRC на лету. Более того, обычно это даже вредно.
Ответ в линию начинается после приема запроса, таймаута (3,5), обработки пакета (подсчета CRC + обработки), и (в случае полудуплексной линии) дополнительного времени на переключение направления, обычно делается порядка нескольких мсек
@Ark
Цитата
Вопросы:
1. Можно ли сделать так, чтобы любое устройство могло взять на себя роль главного?
2. Каким образом вообще передавать информацию главному? Через регистры, что ли?
3. С чего вообще начинать?

3. Начинать нужно с детализации постановки задачи и выстраивания вашей системы на различных уровнях иерархии управления.
2. Начните с физического уровня. Определите, какое максимальное количество устройств может быть на линии. Какие объемы информации нужно передавать и с какой периодичностью. Тогда станет понятна необходимая скорость обмена и возможная частота опроса устройств.
1. Если за основу выбран протокол MODBUS, то я бы не советовал Вам делать систему со многими ведущими. На много проще, когда ведущий один. Желательно, что бы им было устройство с наибольшими собственными ресурсами -персональный компьютер (ПК), например.
0. На каждом уровне иерархии, ведущими могут быть различные устройства системы. Совсем не обязательно, чтобы ведущий был один и тот же на всех уровнях. Такое прямое, "лобовое" решение - не всегда самое лучшее. Например, на протокольном уровне ведущим может быть ПК, а на более высоком уровне - им может быть, к примеру, какой-нибудь выносной пульт управления. Хотя он будет подчиненным устройством с точки зрения MODBUS, но фактическое управление системой будет осуществляться с него. ПК будет периодически читать его по MODBUS, получая, таким способом, указания, что необходимо делать в данный момент. Далее, эти "указания" обрабатываются в ПК и преобразуются в последовательность протокольных команд для других подчиненных устройств... Подобным же образом можно реализовать и передачу функций ведущего устройства (высокоуровневого) другим устройствам или получить систему с многими ведущими. При этом, формально, протокол не будет нарушен, и коллизии между устройствами не будут возникать (по крайней мере на физическом уровне).
rezident
koyodza, @Ark, зачем нужно старую тему поднимать? Думаете, что топикстартер, создавший ее год назад и тогда же последний раз в ней отметившись, прочитает?
@Ark
Sorry, не посмотрел на дату. smile.gif Просто тема показалась интересной...
koyodza
Цитата(rezident @ Oct 18 2009, 00:36) *
koyodza, @Ark, зачем нужно старую тему поднимать? Думаете, что топикстартер, создавший ее год назад и тогда же последний раз в ней отметившись, прочитает?

Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это. Сообщения ведь попадают в "Копилку Вечности", вдруг кто-то из начинающих когда-то забредёт сюда (даже в правилах написано - новую тему создавать после того, как ничего не нашел поиском), и подумает что так и нужно делать...
D&M
Здравствуйте.У меня такой вопрос: Есть теплосчетчик с RS485 и Modbus RTU, есть программа для снятия архивов с него, через сом-порт и переходник 232-485 все снимается. Есть желание соединить к счетчику GSM- модем с RS-485 выходом и опрашивать архивы удаленно по CSD. Но в программе нет функции дозвона, только по сом-порту. Можно ли сделать так- соединить модем к com-порту компьютера, дозвониться гипертерминалом, отключить гипертерминал(чтобы освободить порт), запустить программу снятия архивов, после снятия, отключить связь гипертерминалом ? Если да, то какие подводные камни могут возникнуть при этом, или есть какой нибудь другой способ, кроме написания своей проги для опроса счетчика ,конечно.
HARMHARM
Цитата(D&M @ Oct 24 2009, 09:12) *
Можно ли сделать так- соединить модем к com-порту компьютера, дозвониться гипертерминалом, отключить гипертерминал(чтобы освободить порт), запустить программу снятия архивов, после снятия, отключить связь гипертерминалом ? Если да, то какие подводные камни могут возникнуть при этом, или есть какой нибудь другой способ, кроме написания своей проги для опроса счетчика ,конечно.

Проще сделать своё устройство с виртуальным USB CDC, и устанавливать соединение перед снятием логов. Для программы это будет прозрачно. Единственное что - могут быть задержки при передаче, и это не удастся побороть.
D&M
устройство с виртуальным USB CDC- это как я понял железка, которая прикидывается сом-портом, а сама подключается на USB и к к ней подключается сотовый модем. А задержки могут быть из-за этой железки или на сотовом канале и могут ли они влиять modbus протоколу или только на скорость работы? Раз вы говорите "проще так сделать", значит и по моему варианту тоже можно? если так, то можно написать простенькую программу дозвона с автоматическим вызовом программы счетчика и отключением.
D&M
или как ? жду разных предложений.. Кстати- USB CDC-это идея..
rezident
Цитата(D&M @ Oct 25 2009, 01:41) *
или как ? жду разных предложений..
Ваша задача разбивается на два вопроса.
Во-первых, вы не огласили какой именно MODBUS используется? Modbus RTU весьма плохо "ложится" на коммутируемые линии (телефоная связь). Для коммутируемых линий Mobus ASCII предназначался.
Во-вторых, программы автодозвона есть готовые. Насчет бесплатности не в курсе, не исследовал этот вопрос. Задача этой программы установить связь и обеспечить "прозрачный" режим работы модема. То бишь ваша программа не будет знать, что у нее не проводная связь, а коммутируемая.
А вообще такие задачи решают с помощью OPC-сервера. Программы, которая занимается установлением связи, опросом удаленных устройств и доставкой данных с конвертацией их в требуемый для другой программы (SCADA-системы) формат.
D&M
Тогда может посоветуете OPC-сервер,который может дозваниваться по GSM и SCADA систему.
D&M
Посмотрел,продумал разные варианты и пришел к выводу- MODBUS-RTU не очень подходит для GSM, и прога для снятия архивов, т.к. нужны только накопленные значения с 2-3 каналов(2-3 показания механических счетчиков) и 2 температуры. Лучше наверно сделать железку например на ATMEGA162, которая будет на стороне счетчика опрашивать по Modbus и по запросу передавать эти 5 цифр в любом виде, может быть DTMF-ом или по другому. Только железок много собирать- счетчиков штук 100.
rezident
D&M, я вам в личку написал. Не смотрели?
D&M
ответил
Ronin
Цитата(D&M @ Oct 26 2009, 18:46) *
Посмотрел,продумал разные варианты и пришел к выводу- MODBUS-RTU не очень подходит для GSM, и прога для снятия архивов, т.к. нужны только накопленные значения с 2-3 каналов(2-3 показания механических счетчиков) и 2 температуры. Лучше наверно сделать железку например на ATMEGA162, которая будет на стороне счетчика опрашивать по Modbus и по запросу передавать эти 5 цифр в любом виде, может быть DTMF-ом или по другому. Только железок много собирать- счетчиков штук 100.


Не знаю чем RTU не подходит для GSM. что CSD что GPRS это такие же байты как и в любом другом канале. CRC если что ошибки призвана прибивать.

варианты:

1. Проще делать как описал rezident. правда громоздко и некрасиво. это способ для непрограммеров.

2. Модем c RS485 что из себя представляет ? я почему спрашиваю, по дефолту обычные модемы RS232, а с RS485 это уже специальные версии. Вместо них может попробовать "GSM(GPRS)-удлинители com-порта", вроде у Аналитика нечто подобное было, да и у других контор, в сопоставимом ценовом диапазоне.

3. Либо если не напрягает сделать 100 железок, может проще сделать 1 (либо 1+100, как нравится), но которая будет сама обзванивать нижний уровень и что-нибудь ещё полезное делать, например по новым виртуальным адресам счётчики разбрасывать smile.gif
D&M
1,3 варианты продумал,говорил про модем teleofis-rx108-r-rs485, вообще счетчики разочаровали-пробовал ОРС-модбус сервером опрашивать по адресам регистров по документации-самый нужный параметр не выдает- итоговое накопленное, тогда и смысла нет в затее..
zltigo
Цитата(Ronin @ Nov 3 2009, 22:15) *
GPRS это такие же байты как и в любом другом канале

Ну а время, время между этими самыми байтами, как с ним дела обстоят? Огласите.
MrYuran
Цитата(zltigo @ Nov 4 2009, 22:17) *
Ну а время, время между этими самыми байтами, как с ним дела обстоят? Огласите.

По ГПРС пинги по полторы секунды - не редкость.
А Modbus-TCP для кого придумали? По моему скромному, самое оно для таких сетей
D&M
Нету Modbus-TCP, есть Modbus-RTU в моем рассказе.
zltigo
Цитата(MrYuran @ Nov 5 2009, 09:17) *
По ГПРС пинги по полторы секунды - не редкость.

Угу.
Цитата
А Modbus-TCP для кого придумали? По моему скромному, самое оно для таких сетей

Вот это Вы Автору, который хочет знать только RTU и видит в нем только байты, и не видит никаких проблем объясните.
Ronin
Цитата(zltigo @ Nov 4 2009, 22:17) *
Ну а время, время между этими самыми байтами, как с ним дела обстоят? Огласите.


Т.е. Mobus ASCII тут будет гораздо лучше ? Именно в отношении RTU vs ASCII выше было обсуждение.
К тому же D&M вообще CSD пока обсуждает имхо.

Цитата(MrYuran @ Nov 5 2009, 09:17) *
По ГПРС пинги по полторы секунды - не редкость.


и более... sad.gif
D&M
У счетчика Modbus-RTU, а в модеме только CSD..
Ronin
Цитата(D&M @ Nov 6 2009, 15:41) *
У счетчика Modbus-RTU, а в модеме только CSD..


Вы сначала определитесь со всей структурой системы, а затем переходите к решению отдельных пунктов.

Например:
1. Что на верхнем уровне (компьютер) - какая-то готовая программа, нечто самописное, нечто на основе SCADA/OPC...
Отсюда уже станет ясно, сможет ли эта программа сама всех обзванивать или иметь дополнительный функционал, и нужны ли будут нижеследующие промежуточные звенья:
2. Контроллер опроса верхнего уровня - "железка", которая сама будет обзванивать, опрашивать счетчики и преобразовывать данные в понятный формат для (п.1) программе, естественно и поддерживать обмен по протоколу который эта программа (п.1) поддерживает.
2а. модем.
3а. модем.
3. Контроллер опроса нижнего уровня - "железка" которая будет производить дополнительную обработку собранных данных до передачи в канал связи.
4. Ваши счетчик(и)

В зависимости от конкретных условий - фунционала ПО п.1, канала связи и т.д., п.2 и п.3 могут отсутствовать.
defunct
Цитата(koyodza @ Oct 18 2009, 19:51) *
Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это.

Стандарты порой устаревают. А сильно распространненные нарушения часто становятся частью страндарта.
Грубых нарушений стандарта в упор не вижу, если CRC сошлась ложно, то пакет отбракуется по длине и прием продолжится.
С другой стороны, на кой в холостую ждать 3.5 символьных интервала (это ж вагон и еще маленькая тележка времени особенно на 9600 и ниже), когда их можно потратить с пользой, например на вычитку архива из медленного eeprom'а по текущему запросу мастера.

Цитата
Сообщения ведь попадают в "Копилку Вечности", вдруг кто-то из начинающих когда-то забредёт сюда (даже в правилах написано - новую тему создавать после того, как ничего не нашел поиском), и подумает что так и нужно делать...

Может для "Копилки Вечности" у вас найдется способ отмерить таймаут в 1.75ms под Windows?
@Ark
Цитата
... Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это. Сообщения ведь попадают в "Копилку Вечности"....

Ну, если писать с прицелом в "Копилку Вечности", то нужно быть более точными в формулировках.
Прием сообщения считается завершенным, если обнаружена пауза не менее 3.5 дительностей передачи одного символа, а правильность приема определяется по значению CRC. Начинать передачу ответа можно сразу по истечении длительности интервала ожидания конца сообщения (3,5 символа), не делая каких-либо дополнительных пауз. По этой причине, для экономии времени, правильнее сразу начинать анализ сообщения и формирование ответа, уже в процессе приема сообщения, не дожидаясь конца передачи и завершающей паузы. Естественно, что делать какие-либо критичные действия (например, запись переменных) и отправлять ответ, можно только после успешного завершения приема и проверки корректности сообщения. А вот, например, проверять код номера устройства, допустимость параметров команды, вести подсчет контрольной суммы, производить чтение данных - вполне можно уже в процессе приема сообщения. И ни каким нарушением стандарта это не является.
aaarrr
Цитата(@Ark @ Nov 8 2009, 04:37) *
А вот, например, проверять код номера устройства, допустимость параметров команды, вести подсчет контрольной суммы, производить чтение данных - вполне можно уже в процессе приема сообщения. И ни каким нарушением стандарта это не является.

Из всего перечисленного какой-то практический смысл имеет только проверка адреса. Все остальное - это просто создание себе вороха проблем ради весьма сомнительной экономии. Пусть и в рамках стандарта.
@Ark
Цитата
Из всего перечисленного какой-то практический смысл имеет только проверка адреса. Все остальное - это просто создание себе вороха проблем ради весьма сомнительной экономии.

Эта "сомнительная экономия" требуется, когда необходимо сократить время ответа устройства до минимально возможного, и, тем самым, повысить быстродействие всей системы. Если для Вас это не критично - можете не экономить, никто не заставляет. smile.gif
aaarrr
Ну, сколько удалось наносекунд сэкономить, а? Серьезно спрашиваю.
Если такое аж требуется, значит что-то не так с выбором протоколов и интерфейсов.
@Ark
Цитата
... значит что-то не так с выбором протоколов и интерфейсов.

Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить! biggrin.gif
rezident
Ради справедливости хотелось бы заметить, что не всегда есть возможность разбирать пакет "на лету" по причине многоуровневой организации связи. Вообще говоря, ModBus это довольно высокий уровень в сетевой модели OSI. Когда у устройства только один коммуникационный интерфейс и только один поддерживаемый протокол, то там можно конечно наоптимзировать. Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям UART. Но в прерывании UART не желательно еще и паузы отслеживать (в крайнем случае можно лишь каждый байт сопровождать меткой времени, интерлив этих меток анализировать не его задача) и за сетевыми адресами следить и CRC считать. Там потоковые буферы работают. А у буфера только три параметра: указатель на его начало, индекс текущего элемента и счетчик кол-ва байт. Все! Больше ничего буферу не нужно. И что там именно принимается или передается функции прерываний уже не интересует. Есть что-то в буфере передачи - передаем (если передача разрешена) пока не закончится это что-то. На приеме: если что-то пришло, без ошибок, фиксируемых аппаратурой UART, и есть место в буфере приема, то принимаем. Только такая организация физического уровня позволяет его использовать вне зависимости от вышестоящего протокола.
P.S. вдогонку, а кроме UART есть (существуют) еще и другие интерфейсы smile.gif
P.P.S. вообще лично я отношусь отрицательно, когда в реализации связи не предусмотрены настраиваемые задержки. Не нужны тебе задержки - занули их, но пускай они будут. Самому же потом будет проще адаптировать свою аппаратуру к чужим сетям.
aaarrr
Ну, как и следовало ожидать, конкретные цифры озвучены не были.

Цитата(@Ark @ Nov 8 2009, 05:21) *
Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить! biggrin.gif

Считаете, простое решение менее разумно? А я вот полагаю, что куда менее разумно доводить до абсурда "оптимизацию".

Цитата(defunct @ Nov 8 2009, 05:47) *
Пусть сэкономим 5ms на пакет. Много это или мало... хм.. на тысяче пакетов сэкономим 5 секунд, на 10K - 50 секунд уже существенно.

Ну, 5ms сэкономим разве что при скорости 9600 (два байта CRC и 3.5 паузы). И сколько секунд в этом случае займут 10К пакетов?
Экономия получается на уровне единиц процентов в самом лучшем случае.
defunct
Цитата(rezident @ Nov 8 2009, 04:32) *
Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям UART. Но в прерывании UART не желательно еще и паузы отслеживать (в крайнем случае можно лишь каждый байт сопровождать меткой времени, интерлив этих меток анализировать не его задача) и за сетевыми адресами следить и CRC считать.

Насчет приемной части пожалуй позволю себе с Вами не согласиться. При использовании последовательных интерфейсов, определением границ пакета удобнее всего заниматься там, где идет посимвольный поток. А где такой поток идет нативно? - Как раз в RX прерывании UARTa. Смену протокола, не меняя (не нарушая) структуру драйвера UART'a тоже элементарно сделать - предусмотрев подмену потоковой функции-обработчика. Крайне желательно чтобы эта функция-обработчик занималась определением сетевого адреса, отбрасывая мусор нам непредназначенный, тем самым экономя и время, и память.

Пусть есть сл. обработчик прерывания (упрощенно):

Код
__interrupt void uart_RxExtHandler(void)
{
    U8 status = UART_STATUS_REG;
    U8 ch = UART_DATA_REG;

    if (status != OK )
    {
        DoHandleError();
        return;
    }

    
    if (rx_cb) // Есть спец-функция обработки потока?
        rx_cb( ch );  // пользуем ее
    else // нет, тогда...
    {
                      ... положить в generic uart буфер или сделать что-то еще
    }
}


Смена протокола сведется к смене обработчика потока:

rx_cb = MEK_RxCharHandler;
rx_cb = Modbus_RxCharHandler;
rx_cb = hc_RxCharHandler;
rx_cb = ppp_RxCharHandler;
rx_cb = slip_RxCharHandler;
...
и т.д. и т.п.

Пример возможного обработчика потока:
Код
/*****************************************
* ppp_RxCharHandler()                    *
*    Attached when lower layer is UP     *
* using byte staffing (flag sequence)    *
* to extract packets                     *
* ---> val - current char from the link  *
* <--- returns nothing                   *
*****************************************/
static void ppp_RxCharHandler(U8 val)
{
    PPACKET_BUF pInPkt = linkContext.pInPkt;
    #if (AUTO_ESCAPE)
        static U8 prevch = 0;
        U8 esc_val = (prevch == PPP_ESCAPE) ? val ^ 0x20 : val;
    #else
        #define esc_val val
    #endif

    if (!pInPkt) // return if no storage
        return;

    linkContext.pppRxOctetCnt += 1;
    linkContext.pppRxTimeSinceLastOctet = 0;
    
    if (val == PPP_FLAG) // new packet / end of packet
    {
        ppp_NewPacket( pInPkt );
    }
    else
    { // receiving packet
        #if (AUTO_ESCAPE)
        if (!ppp_IsEscaped( linkContext.inACCM, val))
        {
            pInPkt->payload[ pInPkt->Length++ ] = esc_val;
            pInPkt->fcs = ppp_fcs16( pInPkt->fcs, &esc_val, 1);
            if (pInPkt->fcs == PPPGOODFCS16)
                ppp_NewPacket( pInPkt );
        }
        #else
            pInPkt->payload[ pInPkt->Length++ ] = esc_val;
        #endif
        
        if (pInPkt->Length >= MAX_LINK_PACKET_SIZE)
        { // break receving (exceed max len)
            linkContext.pppRxDiscardMaxLen += 1;
            pInPkt->Length = 0;
        }
    }

    #if (AUTO_ESCAPE)
        prevch = val;
    #endif
}

То что в этом обработчике делается весьма просто и без лишних затрат памяти - escaped characters, нативное определение границ пакета, - делать в аппликейшине накладнее. Кроме того например Microsoft не утруждает себя посылкой закрывающего флага 0x7E в конце пакета, MS считает что достаточно одного 0x7E флага в начале пакета. Поэтому, чтобы не терять время в ожидании таймаута <хрен знает какой длины> или следующего пакета с разделительным флагом - FCS (CRC) текущего пакета считается на лету, при совпадении пакет сразу же отцепляется.


Цитата
На приеме: если что-то пришло, без ошибок, фиксируемых аппаратурой UART, и есть место в буфере приема, то принимаем. Только такая организация физического уровня позволяет его использовать вне зависимости от вышестоящего протокола.

Ну мы говорим не про физ уровень, а про канальный уровень.
Приведенная выше организация решает обратную задачу, - как сделать протокол пригодным к использованию с любым каналом и экономить память занимаемую канальным уровнем.
Байт-обработчики можно использовать и для пакетных интерфесов, т.к. никто не мешает вызвать их n раз для n байт принятого пакета. Она не противоречит и Вашей организации. Можно из буфера приема (если есть память под этот отдельный буфер приема) читать символы побайтово, и скармливать байт-обработчику, только это будет двойная работа, и нет ясности как быть с таймаутами (не думаю что Вы всерьез предложили наградить каждый принятый байт довеском их одно-, двух-, трех-, четырех- байтой метки времени).
@Ark
Цитата
Ну, как и следовало ожидать, конкретные цифры озвучены не были...

А какие могут быть конкретные цифры, без указания конкретной задачи?
Пример могу привести. При реализации операции чтения по MODBUS (например, значений АЦП), часто требуется первичную обработку данных делать в самом устройстве (получение и усреднение нескольких значений, масштабирование результата, пересчет и приведение к нужному виду). А не гнать поток "сырой информации" мастеру, перекладывая на него их обработку, и загружая канал. В этом случае формирование ответа может занимать значительное время - сравнимое со временем приема сообщения...
Цитата
Считаете, простое решение менее разумно?....

Для приведенного примера - более простое решение просто не приемлемо. Считать 100 значений АЦП и передать по каналу усредненный результат, или 100 раз передать по MODBUS "сырые" значения - разницу трудно не заметить.
aaarrr
Пример из пальца высосан: вдруг, по команде извне, начинаем АЦПировать и накапливать 100 значений, вместо того, чтобы делать это постоянно и спокойно отдавать при необходимости готовый результат. Ах, ну да, у нас ведь ресурсов нет на такие сложности.
А можно еще какой-нибудь 1-wire термометр так опрашивать - огромная экономия выйдет, если запустить преобразование с опережением в 5.5 символов UART'а.
@Ark
Цитата
... вдруг, по команде извне, начинаем АЦПировать и накапливать 100 значений, вместо того, чтобы делать это постоянно и спокойно отдавать при необходимости готовый результат.

... Только этот "готовый результат", полученный "постоянным и спокойным АЦПированием" - ни кому не нужен, когда необходимо получить мгновенное значение с максимальной точностью и минимальной временной задержкой. Вообще, что я Вам доказываю - каждый выбирает технические решения так, как считает нужным. Вам не нравятся мои подходы, а мне - Ваши. На том и остановимся. В конечном итоге - меня лично интересует только мнение заказчика по этому поводу, и ни чье больше...
Удачи!
aaarrr
Цитата(@Ark @ Nov 8 2009, 18:30) *
... Только этот "готовый результат", полученный "постоянным и спокойным АЦПированием" - ни кому не нужен, когда необходимо получить мгновенное значение с максимальной точностью и минимальной временной задержкой.

Да нет, скорее вряд ли кому нужно "мгновенное значение", полученное с "минимальной временной задержкой", обеспеченной средствами Модбаса (т.е. примерно никак не обеспеченной).

Цитата(@Ark @ Nov 8 2009, 18:30) *
Удачи!

И Вам!
rezident
2 defunct, еще раз обращаю внимание, что я писал про общий случай, а не про тот, когда устройство только связью занимается. И не про канальный уровень, а про физический, когда обработка прерывания по времени должна занимать как можно меньше времени. Потому, что могут быть и другие прерывания тоже критичные ко времени. Ничего не имею против вашего мнения, но получается, что вы сами себе возражали, т.к. переиначили мое сообщение так, чтобы вам было удобно возражать smile.gif
@Ark
Цитата
... скорее вряд ли кому нужно "мгновенное значение", полученное с "минимальной временной задержкой", обеспеченной средствами Модбаса (т.е. примерно никак не обеспеченной).

Вашими методами, конечно, может получится "никак не обеспеченной", а за других - не "расписывайтесь". wink.gif
aaarrr
Цитата(@Ark @ Nov 8 2009, 19:06) *
Вашими методами, конечно, может получится "никак не обеспеченной", а за других - не "расписывайтесь". wink.gif

А что будет с вашей "минимальной временной задержкой", случись, скажем, ошибка при передаче? Минимальным задержкам место внутри одного устройства, а не в распределенной системе, связанной протоколом сорокалетней давности.

Гениально просто: слейв получил команду "считать что-то с АЦП", и не убеждаясь в достоверности оной (мы ведь спешим, пожар!), начинает накапливать мильен отсчетов. А потом - бац! - CRC не совпало. Что делать? Конечно, отработать аварийный выход (и так для любой команды чтения, ага).

Красиво?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.