Jump to content

    

Работа с COM портом с++ builder

А если в Win таки реализовывать. Какой порядок (размер) таймаутов можно использовать ?

таймауты 5мс (банальным sleep ом) - там получаются вполне нормально, но нестабильно - будут время от времени вылезать 15-20мс паузы. если вы повысите приоритет задачи - то возможно удасться избавиться от таких выпадений. в этом плане линух оказался менее предсказуемым (ядро 2й версии) - там непредсказуеые лаги я получал по 50мс.

если будете пользоваться настройками DCD как вам выше расписали - то они реализуются скорее всего ядром, и разрешение 1мс они вполне реализуют.

для засекания времени нужны не таймауты а измерение времени - эта штука гораздо более проворная и малозатратная. для точного засекания времени у венды тоже есть стандартные средства, и вы найдете пачку библиотек и примеров типа Ultra High Precision Timing для венды.

 

Мне это танцы с бубном надоели, думаю делать внешний "буферизатор" на контроллере, обеспечивающий

требуемый реалтайм для фрейминга, а для "закачки" в PC задействовать CTS-RTS.

Это правильное решение ?

чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка?

CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события. но вы покладете комп на обработку этих прерываний если они будут лететь интенсивно, а судя по размеру ваших пакетов - они будут свистеть интенсивно. - на вендовой (да и на линуховой) машине гораздо быстрее будет работать обмен с маркером чем с прерыванием.

Share this post


Link to post
Share on other sites
без претензий на звание специалиста :)

--

 

Абсолютно !!! Я ни разу не претендую на звание специалиста, всязи с чем и задаю этот малоинтересный местному сообществу вопрос.

 

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

Каким бы компонентом Вы не пользовались, они (скорее всего) в конечном итоге делает ситемный вызво ReadFile()

или ReadFileEx() и подготавливает блок DCB - структура управления-настройками СOM-порта, а также COMMTIMEOUT структура.

Это понятно, что так оно и есть. Была даже идея заморочится самостоятельно разбираться с АПИ и т.д. Хоть и понятно что знани для этого прямо скажем совсем мало... Но общее представление о работе с компортом я получил.

 

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

надежный и быстрый обмен в Вашим устройством, а таймауты (они потребуются в любом случае) придется организовывать самому.

Я использую прямой вызов ReadFile() с настройкой DCB. Устойчиво принимаются на PC пакеты от моего

девайса на 57600 c межпакетной паузой 50 мс

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

 

По этой теме есть хорошая книжка Агурова, там есть описание всей низкоуровневой "кухни" работы с компортами.

На данный момент занимаюсь более углублённым изучением этой книги.

 

 

 

Share this post


Link to post
Share on other sites
Начались старые байки.

Надо думать что TCP/IP под Windows весь построенный на таймерах мне приснился. :biggrin:

Нет, Все еще хуже :(. Вам приснилось, что Вы знаете, что такое уровень TCP/IP. TCP/IP вообще не занимается фреймингом, проблемы которого здесь вылезли. В описании протокола TCP/IP вообще нет ни одного слова таймер за ненадобностью.

Сюрприз!

 

TCP/IP по большей части шас живет на Ethernet, а 90 процентов вопросов "пакетизации" выполняет контроллер.

SLIP - если в этом смысле - то да.

1) Не 90, а ровно 100%

2) Ни SLIP, ни PPP тоже НЕ используют таймауты для выделения фрейма.

Share this post


Link to post
Share on other sites
В огороде бузина, а в Киеве дядька - у "любого" протокола таймауты это обязательные АВАРИЙНЫЕ ветки. Использование таймаутов для фрейминга, это фича УБОГИХ протоколов. Использование убогих протоколов с таймаутами для фрейминга в системах типа Windows не имеющих поддержки реального времени есть 100% махровая любительщина :(. Так что протокол менять однозначно, а не бороться до конца жизни с тем, что надежный фреймиг по небольшим таймаутам под Win нереализуем в принципе.

ЭЭхххх, даже не могу ничего возразить - просто потому что "протокол" это очень громко сказано, и определение УБОГИЙ вполне себе подходит. Никогда до этого не сталкивался с организацией передачи данных между устройством и ПК. Посему и наступил на эти грабли. В связи с тем что само по себе устройство не весть что, думал как-то обойтись малой кровью точнее малыми трудозатратами. Т.е. раз в интервал времени сформировать пакет и отправить его на ПК, а уже на стороне ПК всё это собрать. Скорость передачи не имеет большого значения - не первостепенная задача. Сейчас у меня передача 32кБ занимает около 5 минут, меня это вполне устраивает. Чтение данных в таком объёме предполагается раз в месяц в лучшем случае, а то и реже. От скорости передачи СОМ это не зависит, скорость ограничена именно интервалами отправки пакетов. т.е. и на 9600 и на 115200 время передачи занимает одинаковое.

И да это любительщина эпитеты к слову любительщина можно подбирать самостоятельно и долго, я с ними согласен.

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

Протокол менять... Ну, менять можно то что есть и работает :) Сейчас вобщем-то ничего нет. Что вы порекомендуете ? Как изменить протокол и как его реализовать ?

 

 

чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка?

CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события. но вы покладете комп на обработку этих прерываний если они будут лететь интенсивно, а судя по размеру ваших пакетов - они будут свистеть интенсивно. - на вендовой (да и на линуховой) машине гораздо быстрее будет работать обмен с маркером чем с прерыванием.

 

Да можно ввести и маркеры, сейчас над этим и думаю. Пакеты коротки не потому что они идут с большой скоростью, а просто так сложилось ....

Без особых на причин. 32кб передаются около 5 минут.

 

Share this post


Link to post
Share on other sites
И да это любительщина эпитеты к слову любительщина можно подбирать самостоятельно и долго, я с ними согласен.

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

Протокол менять... Ну, менять можно то что есть и работает :) Сейчас вобщем-то ничего нет. Что вы порекомендуете ? Как изменить протокол и как его реализовать ?

Протокол с байт-стаффингом. Ищите:

Wake

Ридико Леонид Иванович

 

Примеры кода там выложены..

 

Share this post


Link to post
Share on other sites

Спасибо. Буду поизучать в этом направлении.

Share this post


Link to post
Share on other sites
Протокол с байт-стаффингом. Ищите:

Wake

Если без дополнительной скорее всего не нужной шелухи, то останется просто SLIP https://tools.ietf.org/html/rfc1055

 

 

Share this post


Link to post
Share on other sites

Ага. я тоже за SLIP RFC1055.

обрамил кодом команды в начале и CRC16 в конце - и вперед.

очень нравится.

Share this post


Link to post
Share on other sites
Как изменить протокол и как его реализовать ?

 

В AsyncPro этих протоколов уже есть как собак нерезаных.

Простейший путь кинуть на форму компонент ApdDataPacket

post-2050-1479455534_thumb.png

 

Настраиваете признаки начали и конца пакета и перехватываете ивент OnPacket.

И получаете готовый всегда собранный пакет.

Если ошибка, то получаете ивент OnTimeout

 

Читайте APRO_ReferenceGuide.pdf стр. 141

Share this post


Link to post
Share on other sites
. . . .

( 1) чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка?

 

(2) CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события.

. . . .

(1) - протокол бинарный, перадаются в том числе числа int_32, double(64), соотв-но маркер получится слегка длинноватый. Очевидно (8+1) байт.

Надо будет это осмыслить насчет целесообразности. Зато можно будет работать "потоком".

(2) спасибо за инф. Я тестилку делал на базе CTS-RTS, но по опросу. До прерываний будет время доберемся.

 

 

 

 

 

. . . .

Пакеты коротки не потому что они идут с большой скоростью, а просто так сложилось ....

. . . .

 

Если пакеты короткие (5-10-20 байт), можете использовать следующий изворот.

 

1. Все данные передаются как 7-битные (т.е. байт с нулевым старшим битом)

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

с установленным старшим битом.

3. Как впихнуть 8-битные данные в 7 бит ?

Очень просто. Сперва в виде байтов c очищенным D7 передаются разряды данных D0-D6.

Потом - все "непереданные" D7-биты данных пакуются в требуемое кол-во байт последовательно, в биты D0...D6

Длина тела пакета (данных) получается Data_len+(data_len/7) байт.

 

Недостаток - затраты времени на (рас)паковку и избыточность. Затраты RAM на всеэто.

Достоинства - поточный разбор, 128 возможных "служебных" кодов, включая старт/стоп пакета STX ETX

 

 

Share this post


Link to post
Share on other sites
1. Все данные передаются как 7-битные (т.е. байт с нулевым старшим битом)

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

с установленным старшим битом.

3. Как впихнуть 8-битные данные в 7 бит ?

Очень просто. Сперва в виде байтов c очищенным D7 передаются разряды данных D0-D6.

Потом - все "непереданные" D7-биты данных пакуются в требуемое кол-во байт последовательно, в биты D0...D6

Длина тела пакета (данных) получается Data_len+(data_len/7) байт.

 

Недостаток - затраты времени на (рас)паковку и избыточность. Затраты RAM на всеэто.

Достоинства - поточный разбор, 128 возможных "служебных" кодов, включая старт/стоп пакета STX ETX

Это сложно и так делать не советую. Уж если передавать байт данных двумя посылками в линию, то передавайте его стандартными символьными кодами. А "возврат каретки + перевод строки" - это стандартный же разграничитель кадра. И можно работать с любой терминалкой...

 

Share this post


Link to post
Share on other sites
Это сложно и так делать не советую.

Если протокол текстовый, наподобие Modbus/Ascii - то да.

Если же бинарный, то эта комбинация (CrLf) может вылезти в любом поле данных.

Edited by k155la3

Share this post


Link to post
Share on other sites
Если протокол текстовый, наподобие Modbus/Ascii - то да.

Если же бинарный, то эта комбинация (CrLf) может вылезти в любом поле данных.

 

Так кодировать надо Base64 и нечего не вылезет. :biggrin:

Share this post


Link to post
Share on other sites
Так кодировать надо Base64 и нечего не вылезет. :biggrin:

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

Этого должно хватить на ближайшие 10 лет. Далее придется вводить следующий. :(

 

 

 

 

Share this post


Link to post
Share on other sites
В AsyncPro этих протоколов уже есть как собак нерезаных.

Простейший путь кинуть на форму компонент ApdDataPacket

 

Читайте APRO_ReferenceGuide.pdf стр. 141

 

Сапсибо! Вариант решения возникшей проблемы

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this