|
Работа с COM портом с++ builder, Есть небольшие проблемы при работе своего устройства с СОМ |
|
|
|
Nov 16 2016, 19:39
|

Частый гость
 
Группа: Свой
Сообщений: 114
Регистрация: 14-08-07
Из: Харьков, Украина
Пользователь №: 29 773

|
Здавствуйтке. Уже несколько дней, а то и недель занимаюсь тем, что изучаю, читаю, пробую, эксперементирую, но так положительного резутата и не получил, посему хочу обратиться к специалистам этого форума. Постановка задачи примерно следующая, есть устройство, мною сделанное, требуется вычитать из него данные в ПК для дальнейшей обработки. Устройство работает по RS-232. На стороне ПК стоит преобразователь USB-RS232TTL (какой именно, если это принципиально, могу посмотреть). Обмен реализован следующим образом: ПК посылает команду начала передачи данных. после приема команды на передачу устройство передаёт первый пакет . ПК принимает, анализирует его если всё ОК, то высылает байт подтверждения, ( так же может послать останов передачи, повтора пакета). устройство формирует новый пакет исходя из принятого байта. Вроде всё работает более менее нормально, за исключением следующего. При вычитке данных из буфера время от времени происходит какая-то ситуация при которой вычитываются данные со смещением и тогда происходит ошибка анализа пакета, посылается запрос на повтор пакета, и опять вычитка со смещением и так циклически. До останова передачи данных. Для раброты с КОМ-портом использую AsyncPro. Функции вычитки байта и пакета дынных привожу ниже Код unsigned char TReadBuffer::ReadByte(char *byte, short int TimeOut) { //Ожидаем ответа TimeCounter = TimeOut; TimeOutCounter->Enabled=true;
while (ComPort->CharReady()==false) { if (TimeCounter==0) { return erTimeOut;} Application->ProcessMessages(); } *byte = ComPort->GetChar(); return erNoError; }
//---------------------------------------------------------------------------
short int TReadBuffer::RecivePacket(unsigned char *buffer, unsigned char Count) { unsigned char b; for (short int i=0; i<Count; i++){ if (ReadByte(&b, ReadByteTimeOut) == 0) { *buffer=b; buffer++;} else return erTimeOut; } ComPort->FlushInBuffer(); return erNoError; } //--------------------------------------------------------------------------- ComPort->FlushInBuffer(); - поставил дабы при сбое очистить буфер и начать всё сначала. Пробовал ставить как в данный модуль или ставил при возникновении CRC-error... Результат приммерно одинаковый, раз в какое-т овремя происходит смещение чтения.... Не могу понять почему. Понимаю, что где-то неправильно организованы контроль наличия байта в буфере и чтение, но не могу понять где и что.... AsyncPro позволяет писать логи того что принимается и передаётся, согласно задумке. пакеты передаются правильно. после приёма правильного пакета, передаётся байт необходимости повтора пакета, получается точно такой же пакет! и уже отправляется байт что всё ОК, потом несколько пакетов передаются нормально, и опять .... Пакеты короткие по 7 байт. 57 32 0B 10 00 00 72 00 3A 02 32 01 00 6B 61 62 63 64 02 00 D4 65 66 67 68 03 00 66 B7 58 84 01 04 00 6E 03 B7 58 8E 05 00 EA 8E 05 00 EA 01 E4 B7 58 06 00 11 01 E4 B7 это то что получается в buffer. до "разыва" всё идёт хорошо, а вот следующий пакет уже содержит часть предыдущего 8E 05 00 EA . Пакет должен был выглядеть 01 E4 B7 58 06 00 11 Не знаю доступно ли я изложил свою проблему, но она есть и я не знаю как её побороть, т.к. опыта в программировании малова-то. Большое спасибо за помощь
--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
|
|
|
|
|
Nov 16 2016, 21:54
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Diko @ Nov 17 2016, 01:29)  B вот как выглядит лог asyncpro : 0002.442 Dispatch ReadCom 00000007 [B8][3D][94][01][4F][00][09] 0002.443 Dispatch WriteCom 00000001 [31] 0002.470 Dispatch ReadCom 00000006 [E5][B8][3D][9E][50][00] 0002.470 Trigger Avail 00000003 0002.471 Dispatch ReadCom 00000001 [CD] 0002.472 Trigger Avail 00000001 0002.472 Dispatch WriteCom 00000001 [32] 0002.501 Dispatch ReadCom 00000007 [E5][B8][3D][9E][50][00][CD] 0002.502 Dispatch WriteCom 00000001 [32] вот непонятно почему тут вы отвечаете 32 Цитата 0002.530 Dispatch ReadCom 00000007 [E5][B8][3D][9E][50][00][CD] 0002.532 Dispatch WriteCom 00000001 [31] а вот тут - 31? одинаковые же пакеты?
Сообщение отредактировал AlexRayne - Nov 16 2016, 21:55
|
|
|
|
|
Nov 16 2016, 22:03
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Diko @ Nov 16 2016, 23:39)  short int TReadBuffer::RecivePacket(unsigned char *buffer, unsigned char Count) { unsigned char b; for (short int i=0; i<Count; i++){ if (ReadByte(&b, ReadByteTimeOut) == 0) { *buffer=b; buffer++;} else return erTimeOut; } ComPort->FlushInBuffer(); return erNoError; } //---------------------------------------------------------------------------[/code] Закладываться на таймауты чтения по порту, даже не засекая реальное время - это вы слишком игриво работаете. поэтому и получаете что имеете. ваш протокол должен иметь логически детерминированную структуру позволяющую определить начало и конец или длинну фрейма. если вы закладываетесь на паузы - то их надо реально измерять и однозначно задавать на обоих концах интерфейса, вот как это делает модбас. но мадбас - сильно затратный по ресурсам процессора протокол, как раз изза контроля таймингов. дорабатывайте протокол - надо четко определять начало фрейма и его длинну. в вариантах что я встречал в качестве заголовка фрейма используется какойто маркер - скажем 1-2 байта констанных. это уже сильно вас выручит.
|
|
|
|
|
Nov 17 2016, 06:28
|

Частый гость
 
Группа: Свой
Сообщений: 114
Регистрация: 14-08-07
Из: Харьков, Украина
Пользователь №: 29 773

|
Цитата(AlexRayne @ Nov 17 2016, 00:54)  вот непонятно почему тут вы отвечаете 32
а вот тут - 31? одинаковые же пакеты? Вот здесь-то как раз и засада  В том что устройство отвечает "правильно", а вот ПО на стороне ПК немного неправильно вычитывает из буфера. И соответственно считает, что пакет неверен и отправляет 32 - хочу ещё раз этот пакет. Вот что видно на стороне ПО... B8 3D 94 01 4F 00 09 E5 B8 3D 9E 50 00 50 CD E5 B8 3D 9E 50 00 E5 B8 3D 9E 50 00 CD Цитата(AlexandrY @ Nov 17 2016, 01:02)  Функция ReadByte для AsyncPro написана идеологически неправильно. Нельзя ждать там прихода данных и делать ProcessMessages. ProcessMessages очень скверная функция могущая застрять на неопределенное время. Надо перехватить событие поступления данных и читать столько сколько событие скажет.
AsyncPro - это многопоточный движок. Ему не надо помогать циклами ожидания. Как-то так я и думал...  Точнее я даже в этом был уверен. Почему-то у меня не сложилось с событиями ( что точно я уж не поминю, точно делал функцию приёма в событии но толи не доконца разобрался толи ещё какая-то беда была. Работала функция не совсем так как я хотел, а всвязи с тем что не доконца понимаю что не так, решил сделать так как понимаю, ну или кажется что понимаю. Подозрения на ProcessMessages были, но здесь два но. Первое то что я решил ну раньше или позже будет вычитан байт из буфера ... не важно, никуда из буфера не денеться. Второе я убирал ProcessMessages из функции, координально ничего не изменилось). Можете ли привести пример как правильно организовать приём "пакета" с использованием событий в AsyncPro, пакет не большой 7 байт. Цитата(AlexandrY @ Nov 17 2016, 06:36)  Таймауты - стандартная фича любого протокола. Реальное там время или не реальное не так важно в данном случае. В Windows нет понятия реального времени. В компоненте AsyncPro есть собственное поле задания таймаута. Им и надо пользоваться, а не пытаться заново строить велосипед. Где-то в хелпе я это видел, но когда занимался общим изучением, поэтому сейчас потерял этот момент, и отложил на день другой поиски.
--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
|
|
|
|
|
Nov 17 2016, 07:05
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Diko @ Nov 16 2016, 23:39)  Здавствуйтке. Уже несколько дней, а то и недель занимаюсь тем, что изучаю, читаю, пробую, эксперементирую, но так положительного резутата и не получил, посему хочу обратиться к специалистам этого форума. . . . . без претензий на звание специалиста  -- Вам правильно подсказывают насчет таймаутов. Каким бы компонентом Вы не пользовались, они (скорее всего) в конечном итоге делает ситемный вызво ReadFile() или ReadFileEx() и подготавливает блок DCB - структура управления-настройками СOM-порта, а также COMMTIMEOUT структура. Так вот, если компонента позволяет настраивать эти таймауты - проблем не будет. Если же нет - Вы не сможете обеспечить надежный и быстрый обмен в Вашим устройством, а таймауты (они потребуются в любом случае) придется организовывать самому. Я использую прямой вызов ReadFile() с настройкой DCB. Устойчиво принимаются на PC пакеты от моего девайса на 57600 c межпакетной паузой 50 мс Таймаутов (которые в COMMTIMEOUTS) 3 шт. Код . . . . COMMTIMEOUTS CommTimeOutsW1; GetCommTimeouts(cContext0->hPort, &CommTimeOutsW1); CommTimeOutsW1.ReadIntervalTimeout = 1; CommTimeOutsW1.ReadTotalTimeoutMultiplier = 100; CommTimeOutsW1.ReadTotalTimeoutConstant = 4000; SetCommTimeouts(cContext0->hPort, &CommTimeOutsW1); . . . . Если имеется исходник компоненты, которым Вы пользуетесь, посмотрите в нем методы, касающиеся таймаутов. (поиском, где поминаются структуры COMMTIMEOUTS). Если таковых не найдете - ищите другое или исользуйте прямые вызовы и настройки ОС. По этой теме есть хорошая книжка Агурова, там есть описание всей низкоуровневой "кухни" работы с компортами.
|
|
|
|
|
Nov 17 2016, 07:20
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(k155la3 @ Nov 17 2016, 09:05)  Если имеется исходник компоненты, которым Вы пользуетесь, посмотрите в нем методы, касающиеся таймаутов. Тут загвоздка, однако. Исходники AsyncPro написаны на Pascal. Я всегда говорил любителям RAD studio, что без перехода на pascal этот тул использовать эффективно невозможно. Но лучше все-таки компонетнт nrCommОн в отличие от AsyncPro не выкидывает фатальных исключений при выдергивании COM-USB переходника из компьютера, а просто закрывает порт.
|
|
|
|
|
Nov 17 2016, 07:53
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Вот кусок кода из работающей программы, лет много назад писал. Понимаю, что сильно неоптимально и ресурсоемко потому что в ожидании, но работает. Писал как временную затычку пока не напишу как надо. Причем, как все временное- работает уже долго и много где, никак руки не доходят переписать (хотя кое-где этот тестовый софт просто как основной пользуют, нон-стоп, годами  ModbusPort1: это ApdComPort компонент из Асинка Timer1 - таймер компонент CODE // returns the number of the received bytes. // unsigned short TForm1::modbus1(u8 *txdat, u8 txlen, u8 *rxdat, u8 rxlen) { unsigned short nbyte; unsigned char rxpkt[1000]; unsigned short i; int old_NbytesInBuf; int end_cnt_timer1_value; int timeout_rx_begin;
if ( true == ModbusRxBeginTimeoutIsBig) timeout_rx_begin = TIMEOUT_BEGIN_RX_LONG; else timeout_rx_begin = TIMEOUT_BEGIN_RX_STANDARD;
SerialCommunicationErrCode = SERPORT_NO_ERROR;
try { // timeout before the sending Timer1->Enabled = true; // Timer1->Interval = 10; //interval is 10ms Timer1->Interval = 1; //interval is 10ms
cnt_timer1 = 0; while (cnt_timer1 < 2) Application->ProcessMessages(); Timer1->Enabled = false;
modbus_LocalPortIsUsed:;
ModbusPort1->FlushInBuffer();
ModbusPort1->PutBlock(txdat,txlen); // rx begin
while (ModbusPort1->OutBuffUsed != 0) Application->ProcessMessages(); //waiting for the end of tramsmitting
//waiting for the first RX byte Timer1->Enabled = true; Timer1->Interval = 100; //100 ms cnt_timer1 = 0; while (ModbusPort1->InBuffUsed == 0) { Application->ProcessMessages(); if (cnt_timer1 >= timeout_rx_begin) { Timer1->Enabled = false; goto err; //íè÷åãî íå ïðèíÿòî } }
//waiting for all next bytes of the RX message Timer1->Enabled = true; Timer1->Interval = 100; //100ms cnt_timer1 = 0;
cnt_timer1 = 0;
old_NbytesInBuf = 1; while (ModbusPort1->InBuffUsed < rxlen) { Application->ProcessMessages(); if (cnt_timer1 >= TIMEOUT_INTRO_PKT_RX) goto end_rx; //timeout exit
if (old_NbytesInBuf != ModbusPort1->InBuffUsed) { //at least one byte has been received old_NbytesInBuf = ModbusPort1->InBuffUsed; Timer1->Enabled = false; Timer1->Interval = 100; //100ms cnt_timer1 = 0; Timer1->Enabled = true; } } end_rx:; nbyte = 0; while (nbyte < ModbusPort1->InBuffUsed) //get all bytes from the buffer { rxpkt[nbyte & 0xff] = ModbusPort1->PeekChar(nbyte+1); nbyte++; } Timer1->Enabled = false;
for (i = 0; i<nbyte; i++,rxdat++) *rxdat = rxpkt[i];
return nbyte; err:; return 0;
} //the end of 'try' operator
catch(...) { // any exception during communication Logging ("serial port communication problem"); SerialCommunicationErrCode = SERPORT_EXCEPTION; return 0; }
}
//другая функция void __fastcall TForm1::Timer1Timer(TObject *Sender) { cnt_timer1++; //in 1 ms Form1->Label2->Caption = IntToStr(cnt_timer1); }
|
|
|
|
|
Nov 17 2016, 09:16
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(zltigo @ Nov 17 2016, 12:43)  . . . . Так что протокол менять однозначно, а не бороться до конца жизни с тем, что надежный фреймиг по небольшим таймаутам под Win нереализуем в принципе. (?) А если в Win таки реализовывать. Какой порядок (размер) таймаутов можно использовать ? (?) Мне это танцы с бубном надоели, думаю делать внешний "буферизатор" на контроллере, обеспечивающий требуемый реалтайм для фрейминга, а для "закачки" в PC задействовать CTS-RTS. Это правильное решение ?
|
|
|
|
|
Nov 17 2016, 09:35
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(k155la3 @ Nov 17 2016, 11:16)  А если в Win таки реализовывать. Какой порядок (размер) таймаутов можно использовать ? Никакие. Не поддается выражению в цифрах. Эмпирически- что-нибудь большое, чтобы в подавляющем большинстве случаем хватало, ноапример, пара секунд.  Это касается и любого Юникса, кроме специальных RTOS с детерминированным временем Это касается и любых каналов передачи данных (Данных, а не сигналов!). Любой интернет-канал или кабельный модем на выделенке или радиоканале может дать задержки, которые больше того на что способна операционка компьютера. Цитата(k155la3 @ Nov 17 2016, 11:16)  Мне это танцы с бубном надоели, думаю делать внешний "буферизатор" на контроллере, обеспечивающий требуемый реалтайм для фрейминга, а для "закачки" в PC задействовать CTS-RTS. Это правильное решение ? Да. Сам так делал, для доставки модбас РТУ в компьютер. Более того- делал и универсальный сборщик из Модбаса и КАНа: с точки зрения компьютера это было одно модбас устройство, имеющее в себе зеркало всех текущих данных, собранных с разных устройств по разным интерфейсам с разными периодами обновления.
|
|
|
|
|
Nov 17 2016, 11:15
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(AlexandrY @ Nov 17 2016, 14:19)  . . . . Надо думать что TCP/IP под Windows весь построенный на таймерах мне приснился.  TCP/IP по большей части шас живет на Ethernet, а 90 процентов вопросов "пакетизации" выполняет контроллер. SLIP - если в этом смысле - то да. Но использовался полный интерфейс RS232 с аппаратным управлением потоком. При наличии одного (!) вспомогательного сигнала, означающего PacketStart уже все намного проще. (по аналогии с SPI, где эту функцию выполнеяет линия CS) Цитата(Ruslan1 @ Nov 17 2016, 13:35)  . . . . Спасибо за инф.
|
|
|
|
|
Nov 17 2016, 17:05
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(k155la3 @ Nov 17 2016, 13:16)  А если в Win таки реализовывать. Какой порядок (размер) таймаутов можно использовать ? таймауты 5мс (банальным sleep ом) - там получаются вполне нормально, но нестабильно - будут время от времени вылезать 15-20мс паузы. если вы повысите приоритет задачи - то возможно удасться избавиться от таких выпадений. в этом плане линух оказался менее предсказуемым (ядро 2й версии) - там непредсказуеые лаги я получал по 50мс. если будете пользоваться настройками DCD как вам выше расписали - то они реализуются скорее всего ядром, и разрешение 1мс они вполне реализуют. для засекания времени нужны не таймауты а измерение времени - эта штука гораздо более проворная и малозатратная. для точного засекания времени у венды тоже есть стандартные средства, и вы найдете пачку библиотек и примеров типа Ultra High Precision Timing для венды. Цитата Мне это танцы с бубном надоели, думаю делать внешний "буферизатор" на контроллере, обеспечивающий требуемый реалтайм для фрейминга, а для "закачки" в PC задействовать CTS-RTS. Это правильное решение ? чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка? CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события. но вы покладете комп на обработку этих прерываний если они будут лететь интенсивно, а судя по размеру ваших пакетов - они будут свистеть интенсивно. - на вендовой (да и на линуховой) машине гораздо быстрее будет работать обмен с маркером чем с прерыванием.
|
|
|
|
|
Nov 17 2016, 17:55
|

Частый гость
 
Группа: Свой
Сообщений: 114
Регистрация: 14-08-07
Из: Харьков, Украина
Пользователь №: 29 773

|
Цитата(k155la3 @ Nov 17 2016, 10:05)  без претензий на звание специалиста  -- Абсолютно !!! Я ни разу не претендую на звание специалиста, всязи с чем и задаю этот малоинтересный местному сообществу вопрос. Цитата(k155la3 @ Nov 17 2016, 10:05)  Вам правильно подсказывают насчет таймаутов. Каким бы компонентом Вы не пользовались, они (скорее всего) в конечном итоге делает ситемный вызво ReadFile() или ReadFileEx() и подготавливает блок DCB - структура управления-настройками СOM-порта, а также COMMTIMEOUT структура. Это понятно, что так оно и есть. Была даже идея заморочится самостоятельно разбираться с АПИ и т.д. Хоть и понятно что знани для этого прямо скажем совсем мало... Но общее представление о работе с компортом я получил. Цитата(k155la3 @ Nov 17 2016, 10:05)  Так вот, если компонента позволяет настраивать эти таймауты - проблем не будет. Если же нет - Вы не сможете обеспечить надежный и быстрый обмен в Вашим устройством, а таймауты (они потребуются в любом случае) придется организовывать самому. Я использую прямой вызов ReadFile() с настройкой DCB. Устойчиво принимаются на PC пакеты от моего девайса на 57600 c межпакетной паузой 50 мс Компонент позволяет настраивать какие-то таймауты - какие и как достоверно не разбирался пока что. Цитата(k155la3 @ Nov 17 2016, 10:05)  По этой теме есть хорошая книжка Агурова, там есть описание всей низкоуровневой "кухни" работы с компортами. На данный момент занимаюсь более углублённым изучением этой книги.
--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
|
|
|
|
|
Nov 17 2016, 19:12
|

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

|
QUOTE (AlexandrY @ Nov 17 2016, 12:19)  Начались старые байки. Надо думать что TCP/IP под Windows весь построенный на таймерах мне приснился.  Нет, Все еще хуже  . Вам приснилось, что Вы знаете, что такое уровень TCP/IP. TCP/IP вообще не занимается фреймингом, проблемы которого здесь вылезли. В описании протокола TCP/IP вообще нет ни одного слова таймер за ненадобностью. Сюрприз! QUOTE (k155la3 @ Nov 17 2016, 13:15)  TCP/IP по большей части шас живет на Ethernet, а 90 процентов вопросов "пакетизации" выполняет контроллер. SLIP - если в этом смысле - то да. 1) Не 90, а ровно 100% 2) Ни SLIP, ни PPP тоже НЕ используют таймауты для выделения фрейма.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 17 2016, 19:38
|

Частый гость
 
Группа: Свой
Сообщений: 114
Регистрация: 14-08-07
Из: Харьков, Украина
Пользователь №: 29 773

|
Цитата(zltigo @ Nov 17 2016, 11:43)  В огороде бузина, а в Киеве дядька - у "любого" протокола таймауты это обязательные АВАРИЙНЫЕ ветки. Использование таймаутов для фрейминга, это фича УБОГИХ протоколов. Использование убогих протоколов с таймаутами для фрейминга в системах типа Windows не имеющих поддержки реального времени есть 100% махровая любительщина  . Так что протокол менять однозначно, а не бороться до конца жизни с тем, что надежный фреймиг по небольшим таймаутам под Win нереализуем в принципе. ЭЭхххх, даже не могу ничего возразить - просто потому что "протокол" это очень громко сказано, и определение УБОГИЙ вполне себе подходит. Никогда до этого не сталкивался с организацией передачи данных между устройством и ПК. Посему и наступил на эти грабли. В связи с тем что само по себе устройство не весть что, думал как-то обойтись малой кровью точнее малыми трудозатратами. Т.е. раз в интервал времени сформировать пакет и отправить его на ПК, а уже на стороне ПК всё это собрать. Скорость передачи не имеет большого значения - не первостепенная задача. Сейчас у меня передача 32кБ занимает около 5 минут, меня это вполне устраивает. Чтение данных в таком объёме предполагается раз в месяц в лучшем случае, а то и реже. От скорости передачи СОМ это не зависит, скорость ограничена именно интервалами отправки пакетов. т.е. и на 9600 и на 115200 время передачи занимает одинаковое. И да это любительщина эпитеты к слову любительщина можно подбирать самостоятельно и долго, я с ними согласен. В данном проекте я наступил на идиологические грабли. Сделать сейчас как-нибудь чтобы побыстрее, а потом уж переделаю как надо... Сам за такое "вжаривал". Протокол менять... Ну, менять можно то что есть и работает  Сейчас вобщем-то ничего нет. Что вы порекомендуете ? Как изменить протокол и как его реализовать ? Цитата(AlexRayne @ Nov 17 2016, 20:05)  чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка? CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события. но вы покладете комп на обработку этих прерываний если они будут лететь интенсивно, а судя по размеру ваших пакетов - они будут свистеть интенсивно. - на вендовой (да и на линуховой) машине гораздо быстрее будет работать обмен с маркером чем с прерыванием. Да можно ввести и маркеры, сейчас над этим и думаю. Пакеты коротки не потому что они идут с большой скоростью, а просто так сложилось .... Без особых на причин. 32кб передаются около 5 минут.
--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
|
|
|
|
|
Nov 17 2016, 19:50
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(Diko @ Nov 17 2016, 22:38)  И да это любительщина эпитеты к слову любительщина можно подбирать самостоятельно и долго, я с ними согласен. В данном проекте я наступил на идиологические грабли. Сделать сейчас как-нибудь чтобы побыстрее, а потом уж переделаю как надо... Сам за такое "вжаривал". Протокол менять... Ну, менять можно то что есть и работает  Сейчас вобщем-то ничего нет. Что вы порекомендуете ? Как изменить протокол и как его реализовать ? Протокол с байт-стаффингом. Ищите: Wake Ридико Леонид Иванович Примеры кода там выложены..
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Nov 18 2016, 07:55
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Diko @ Nov 17 2016, 21:38)  Как изменить протокол и как его реализовать ? В AsyncPro этих протоколов уже есть как собак нерезаных. Простейший путь кинуть на форму компонент ApdDataPacket
Настраиваете признаки начали и конца пакета и перехватываете ивент OnPacket. И получаете готовый всегда собранный пакет. Если ошибка, то получаете ивент OnTimeout Читайте APRO_ReferenceGuide.pdf стр. 141
|
|
|
|
|
Nov 18 2016, 10:22
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(AlexRayne @ Nov 17 2016, 20:05)  . . . . ( 1) чем городить такое лучше поправить протокол - для этого не нужно городить железо, и оно будет надежно работать почти везде. неужели невозможно ввести маркер заголовка?
(2) CTS-RTS вам поможет мало. лучше посмотрите в сторону линии DTR-DSR - кажется они дают прерывание и можно повесить обработчик этого события. . . . . (1) - протокол бинарный, перадаются в том числе числа int_32, double(64), соотв-но маркер получится слегка длинноватый. Очевидно (8+1) байт. Надо будет это осмыслить насчет целесообразности. Зато можно будет работать "потоком". (2) спасибо за инф. Я тестилку делал на базе CTS-RTS, но по опросу. До прерываний будет время доберемся. Цитата(Diko @ Nov 17 2016, 22:38)  . . . . Пакеты коротки не потому что они идут с большой скоростью, а просто так сложилось .... . . . . Если пакеты короткие (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
|
|
|
|
|
Nov 18 2016, 10:48
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(k155la3 @ Nov 18 2016, 13:22)  1. Все данные передаются как 7-битные (т.е. байт с нулевым старшим битом) 2. Все заголовки пакетов, концевики, и прочие служебные символы, требуемые для фрейминга, передаются с установленным старшим битом. 3. Как впихнуть 8-битные данные в 7 бит ? Очень просто. Сперва в виде байтов c очищенным D7 передаются разряды данных D0-D6. Потом - все "непереданные" D7-биты данных пакуются в требуемое кол-во байт последовательно, в биты D0...D6 Длина тела пакета (данных) получается Data_len+(data_len/7) байт.
Недостаток - затраты времени на (рас)паковку и избыточность. Затраты RAM на всеэто. Достоинства - поточный разбор, 128 возможных "служебных" кодов, включая старт/стоп пакета STX ETX Это сложно и так делать не советую. Уж если передавать байт данных двумя посылками в линию, то передавайте его стандартными символьными кодами. А "возврат каретки + перевод строки" - это стандартный же разграничитель кадра. И можно работать с любой терминалкой...
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Nov 18 2016, 20:49
|

Частый гость
 
Группа: Свой
Сообщений: 114
Регистрация: 14-08-07
Из: Харьков, Украина
Пользователь №: 29 773

|
Цитата(AlexandrY @ Nov 18 2016, 10:55)  В AsyncPro этих протоколов уже есть как собак нерезаных. Простейший путь кинуть на форму компонент ApdDataPacket
Читайте APRO_ReferenceGuide.pdf стр. 141 Сапсибо! Вариант решения возникшей проблемы
--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|