реклама на сайте
подробности

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


Частый гость
**

Группа: Свой
Сообщений: 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

Не знаю доступно ли я изложил свою проблему, но она есть и я не знаю как её побороть, т.к. опыта в программировании малова-то.
Большое спасибо за помощь


--------------------
Жизнь сложна и не предсказуема, незачем её усложнять.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
k155la3
сообщение Nov 17 2016, 07:05
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(Diko @ Nov 16 2016, 23:39) *
Здавствуйтке.
Уже несколько дней, а то и недель занимаюсь тем, что изучаю, читаю, пробую, эксперементирую, но так положительного резутата и не получил, посему хочу обратиться к специалистам этого форума.
. . . .

без претензий на звание специалиста sm.gif
--
Вам правильно подсказывают насчет таймаутов.
Каким бы компонентом Вы не пользовались, они (скорее всего) в конечном итоге делает ситемный вызво 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). Если таковых не найдете - ищите другое
или исользуйте прямые вызовы и настройки ОС.

По этой теме есть хорошая книжка Агурова, там есть описание всей низкоуровневой "кухни" работы с компортами.
Go to the top of the page
 
+Quote Post
Ruslan1
сообщение Nov 17 2016, 07:53
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025



Вот кусок кода из работающей программы, лет много назад писал. Понимаю, что сильно неоптимально и ресурсоемко потому что в ожидании, но работает. Писал как временную затычку пока не напишу как надо. Причем, как все временное- работает уже долго и много где, никак руки не доходят переписать (хотя кое-где этот тестовый софт просто как основной пользуют, нон-стоп, годами sm.gif


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);
}


Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Diko   Работа с COM портом с++ builder   Nov 16 2016, 19:39
- - Diko   Покопался в том что у меня происходит и вот что ув...   Nov 16 2016, 21:29
|- - AlexRayne   Цитата(Diko @ Nov 17 2016, 01:29) B вот к...   Nov 16 2016, 21:54
|- - AlexandrY   Функция ReadByte для AsyncPro написана идеологичес...   Nov 16 2016, 22:02
- - AlexRayne   Цитата(Diko @ Nov 16 2016, 23:39) short i...   Nov 16 2016, 22:03
|- - AlexandrY   Цитата(AlexRayne @ Nov 17 2016, 00:03) За...   Nov 17 2016, 03:36
|- - zltigo   QUOTE (AlexandrY @ Nov 17 2016, 06:36) Та...   Nov 17 2016, 08:43
|- - k155la3   Цитата(zltigo @ Nov 17 2016, 12:43) . . ....   Nov 17 2016, 09:16
||- - Ruslan1   Цитата(k155la3 @ Nov 17 2016, 11:16) А ес...   Nov 17 2016, 09:35
||- - AlexRayne   Цитата(k155la3 @ Nov 17 2016, 13:16) А ес...   Nov 17 2016, 17:05
||- - k155la3   Цитата(AlexRayne @ Nov 17 2016, 20:05) . ...   Nov 18 2016, 10:22
||- - iosifk   Цитата(k155la3 @ Nov 18 2016, 13:22) 1. В...   Nov 18 2016, 10:48
||- - k155la3   Цитата(iosifk @ Nov 18 2016, 14:48) Это с...   Nov 18 2016, 11:05
||- - AlexandrY   Цитата(k155la3 @ Nov 18 2016, 13:05) Если...   Nov 18 2016, 11:10
||- - k155la3   Цитата(AlexandrY @ Nov 18 2016, 15:10) Та...   Nov 18 2016, 11:26
|- - AlexandrY   Цитата(zltigo @ Nov 17 2016, 10:43) В ого...   Nov 17 2016, 10:19
|- - k155la3   Цитата(AlexandrY @ Nov 17 2016, 14:19) . ...   Nov 17 2016, 11:15
|- - zltigo   QUOTE (AlexandrY @ Nov 17 2016, 12:19) На...   Nov 17 2016, 19:12
- - Diko   Цитата(AlexRayne @ Nov 17 2016, 00:54) во...   Nov 17 2016, 06:28
|- - AlexandrY   Цитата(k155la3 @ Nov 17 2016, 09:05) Если...   Nov 17 2016, 07:20
- - Diko   Цитата(k155la3 @ Nov 17 2016, 10:05) без ...   Nov 17 2016, 17:55
- - Diko   Цитата(zltigo @ Nov 17 2016, 11:43) В ого...   Nov 17 2016, 19:38
|- - iosifk   Цитата(Diko @ Nov 17 2016, 22:38) И да эт...   Nov 17 2016, 19:50
||- - zltigo   QUOTE (iosifk @ Nov 17 2016, 21:50) Прото...   Nov 17 2016, 20:36
||- - Ruslan1   Ага. я тоже за SLIP RFC1055. обрамил кодом команды...   Nov 17 2016, 20:46
|- - AlexandrY   Цитата(Diko @ Nov 17 2016, 21:38) Как изм...   Nov 18 2016, 07:55
|- - Diko   Цитата(AlexandrY @ Nov 18 2016, 10:55) В ...   Nov 18 2016, 20:49
- - Diko   Спасибо. Буду поизучать в этом направлении.   Nov 17 2016, 20:15
- - Diko   Всем откликнувшимся огромное спасибо. Благодаря эт...   Nov 19 2016, 15:43


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 01:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01405 секунд с 7
ELECTRONIX ©2004-2016